-
Notifications
You must be signed in to change notification settings - Fork 217
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
FEAT: parse tree evaulator and listener #1169
FEAT: parse tree evaulator and listener #1169
Conversation
Signed-off-by: Chen <[email protected]>
Signed-off-by: Chen <[email protected]>
Signed-off-by: Chen <[email protected]>
Signed-off-by: Chen <[email protected]>
Signed-off-by: Chen <[email protected]>
Signed-off-by: Chen <[email protected]>
Signed-off-by: Chen <[email protected]>
Signed-off-by: Chen <[email protected]>
Signed-off-by: Chen <[email protected]>
Signed-off-by: Chen <[email protected]>
Signed-off-by: Chen <[email protected]>
…tree-evaulator-and-listener Signed-off-by: Chen <[email protected]>
Signed-off-by: Chen <[email protected]>
Signed-off-by: Chen <[email protected]>
Signed-off-by: Chen <[email protected]>
Signed-off-by: Chen <[email protected]>
Signed-off-by: Chen <[email protected]>
Signed-off-by: Chen <[email protected]>
Signed-off-by: Chen <[email protected]>
This PR needs to receive modification after merging of #1165 |
@@ -35,4 +35,8 @@ public OperatorProvider(final List<Operator<?>> operators) { | |||
} | |||
return operator; | |||
} | |||
|
|||
public boolean containsOperatorSymbol(final int symbol) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As we already have getOperator
, should this be have a different name? Perhaps: containsOperator
or supportsOperator
?
* walker.walk(listener, ...); | ||
* final Object result = listener.getResult(); | ||
*/ | ||
class ParseTreeEvaluatorListener extends DataPrepperExpressionBaseListener { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice! I like how this came out.
* walker.walk(listener, ...); | ||
* final Object result = listener.getResult(); | ||
*/ | ||
class ParseTreeEvaluatorListener extends DataPrepperExpressionBaseListener { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice! I like how this came out.
void testEvaluateSuccess() throws ExpressionCoercionException { | ||
try (final MockedConstruction<ParseTreeEvaluatorListener> ignored = | ||
mockConstruction(ParseTreeEvaluatorListener.class, (mock, context) -> when(mock.getResult()).thenReturn(true))) { | ||
when(coercionService.coerce(any(), any())).thenAnswer(invocation -> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't believe you need this when
in the try-with-resources. Moving it out will be clearer.
void testEvaluateSuccess() throws ExpressionCoercionException { | ||
try (final MockedConstruction<ParseTreeEvaluatorListener> ignored = | ||
mockConstruction(ParseTreeEvaluatorListener.class, (mock, context) -> when(mock.getResult()).thenReturn(true))) { | ||
when(coercionService.coerce(any(), any())).thenAnswer(invocation -> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't believe you need this when
in the try-finally.
void testEvaluateFailureInWalk() { | ||
try (final MockedConstruction<ParseTreeEvaluatorListener> ignored = | ||
mockConstruction(ParseTreeEvaluatorListener.class)) { | ||
doThrow(new RuntimeException()).when(parseTreeWalker).walk( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please move doThrow
out of try-with-resources.
void testEvaluateFailureInCoerce() throws ExpressionCoercionException { | ||
try (final MockedConstruction<ParseTreeEvaluatorListener> ignored = | ||
mockConstruction(ParseTreeEvaluatorListener.class, (mock, context) -> when(mock.getResult()).thenReturn(true))) { | ||
when(coercionService.coerce(any(), any())).thenThrow(new ExpressionCoercionException("test message")); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please move when
out of try-with-resources.
void testEvaluateFailureInCoerce() throws ExpressionCoercionException { | ||
try (final MockedConstruction<ParseTreeEvaluatorListener> ignored = | ||
mockConstruction(ParseTreeEvaluatorListener.class, (mock, context) -> when(mock.getResult()).thenReturn(true))) { | ||
when(coercionService.coerce(any(), any())).thenThrow(new ExpressionCoercionException("test message")); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please move when
out of try-with-resources.
when(coercionService.coerce(any(), any())).thenAnswer(invocation -> { | ||
Object[] args = invocation.getArguments(); | ||
final Object res = args[0]; | ||
final Class<Boolean> clazz = (Class<Boolean>) args[1]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that invocation
has a method that will cast for you. getArgument(1)
or something like that.
when(coercionService.coerce(any(), any())).thenAnswer(invocation -> { | ||
Object[] args = invocation.getArguments(); | ||
final Object res = args[0]; | ||
final Class<Boolean> clazz = (Class<Boolean>) args[1]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that invocation
has a method that will cast for you. getArgument(1)
or something like that.
Signed-off-by: Chen <[email protected]>
@@ -35,4 +35,8 @@ public OperatorProvider(final List<Operator<?>> operators) { | |||
} | |||
return operator; | |||
} | |||
|
|||
public boolean containsOperatorSymbol(final int symbol) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As we already have getOperator
, should this be have a different name? Perhaps: containsOperator
or supportsOperator
?
Signed-off-by: Chen <[email protected]>
throw new IllegalStateException("The ParseTreeEvaluatorListener has not been walked through exactly once by " + | ||
"a ParseTreeWalker."); | ||
} | ||
return operandStack.peek(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It might be safer to pop to prevent reuse of a listener considering each evaluate call needs a listener.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The reason I did not use pop is based off idempotency. It might be a little weird that the second getResult() call throws exception when called in succession.
operatorSymbolStack.push(nodeType); | ||
} else if (nodeType == DataPrepperExpressionParser.RPAREN) { | ||
// pop LPAREN at operatorSymbolStack top | ||
operatorSymbolStack.pop(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider verifying the top of the stack is a LPAREN.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you mean throw exception if it is not LPAREN? AFAICT, it should only happen if parentheses in the expression are unbalanced, which should already be ruled out by parser?
private void performSingleOperation(final Operator<?> operator) { | ||
final int numOfArgs = operator.getNumberOfOperands(); | ||
final Object[] args = new Object[numOfArgs]; | ||
for (int i = numOfArgs - 1; i >= 0; i--) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Checking operandStack.size() >= numOfArgs
and throwing a more informative error message may lead to a better customer experience.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure if it is necessary. Here is the reasoning: I suppose if the input parseTree is valid, we should never hit this error unless the evaluation algorithm is incorrect and fails to apply to certain corner cases. I do not think we should use exception or error message to guard against incorrect implementation. Also, the error message thrown here is not that helpful to cx on troubleshooting their if condition statement.
Description
This PR
Issues Resolved
Contributes to #1003
Check List
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.
For more information on following Developer Certificate of Origin and signing off your commits, please check here.