We have a situation where the user will define some set of business rules or expressions. That will be look like,
if(riskvalue <= 100) // condition
notifyObservers() // action
remarks = remarkshistory //expression
if(allowedriskvalue <= riskvalue) //child condition
do something //can be expression or action
else
do some other thing
else
do some thing
We will plan to parse this and save it as a expression with it's type, like condition, expression and action.
We have some set of operands and functions that can be allowed in the rule definition.
Please suggest me some validation techniques to validate the rule definition.
And, I want suggestion that either,
use expression tree to execute the rule expressions?
use any custom rule parser / evaluator?
build the logic in dynamic class using code dom and execute it?
Thanks in advance!!!
Related
I am newbie to ANTLR4
I want to write a grammar that would parse the syntax using the values which it reads dynamically.
Say my grammar is as follows in image
I need help such the HANDLERID not only takes the values mentioned,but a list of values based on a function call,dynamic values. For example a function return list containing {'ACD','GHY','XYZ' ..}. Not to confuse with identifier,these values are names of some defined set of objects, so writing a grammar for IDENTIFIER is not solution.
Any help is appeciated.
Maybe actions are a viable solution? These are written in the target language and allow to do all kind of processing. Formulated as a predicate (appending a ? to the action block) they can even be used to guide the parser what path to take.
Here's a typical form:
decl: type ID ';' { System.out.println("found a decl"); };
or as a predicate:
HANDLERID: ID { isSpecialWord($ID.text) }?;
which will only be matched for IDs that your internal function isSpecialWord is returning true for. So essentially, you are not passing the lexer rule some values, but you do the evaluation in internal code.
I'm using the C++ version of ANTLR4 to develop a DSL for a music product. I used to (30 years ago!) do this kind of thing by hand so it's mostly a pleasure to have something like ANTLR, particularly now that I don't have to insert code in the actual grammar definition itself.
I want to do type checking of actual vs formal args in a function call. In the grammar segment below, the 'actualParameter' can return the type of the expression. However, the 'actualParameterList' needs to return an array (say) of these types so that the code for functionCall can compare to the formal parameter list.
If I was handwriting this, the calls to visit or visitChildren would take an extra parameter after context such that I could create a new array at the appropriate place and then have child nodes fill in the details.
I suppose that instead of just calling visitChildren inside the 'visitActualParameterList' I could create the array there and manually call each child rather than just a simple visitChildren but that feels like a hack, and it becomes very sensitive to minor changes in the grammar.
Is there a better approach?
functionCall: Identifier LeftParen actualParameterList? RightParen
;
actualParameterList:
actualParameter anotherActualParameter
;
actualParameter:
expression
;
anotherActualParameter:
Comma actualParameter anotherActualParameter
|
;
You're on the right path. I would suggest something like:
functionCall: Identifier LPAREN actualParameterList RPAREN
;
actualParameterList:
actualParameter (',' actualParameter)*
;
actualParameter:
expression
;
LPAREN : '(';
RPAREN : ')';
Using this, in the Visitor for actualParameterList you can check each child to see if it's of type actualParameterContext and if so, explicitly call Visit on that child, which will get you into your expression evaluation code (presumably handled in the visitor for actualParameter). This alleviates the need, as you say, to just generically visit children. It's very precise when you can check the type like this.
Here's an example of this pattern from my own code (in C# but surely you'll see the pattern in action):
for (int c = 0; c < context.ChildCount; c++)
{
if (context.GetChild(c) is SystemParser.ServerContext) // make sure correct type
{
string serverinfo = Visit(context.GetChild(c)); // visit the specific child and save return value, string in this case
sb.Append(serverinfo); // use result to fill array or do whatever
}
}
Now that you can see the pattern, back to your code. The syntax:
actualParameter (',' actualParameter)*
means that a parameter list has one actualParameter followed by zero or more additional ones with the * operator. I just threw the comma in there for visual clarity.
As you suggest, Visitor is the perfect pattern for this because you can explicitly visit any node you need to. It won't give you an array, but you can fill an array or any other necessary structure with the results of the visiting the children as you saw in the snip from my code. My Visitor returns strings, and I just appended to a StringBuilder. You can use the same pattern to build whatever you need.
I have a boolean expression in string format, example:
name := "Fred"
type := "Person"
I want to evaluate this expression as true or false.
exp := "(name == Fred) && (type == Person)"
Eventually, I would like to be able to execute conditional statements such as:
if (exp) {
...
}
However, from research this is not something Go supports out of the box. I have seen suggestions on using AST to parse and evaluate. But, I am fairly new to go and especially AST, thus not sure how to go about that. Can someone please provide any guidance on how I may go about evaluating a string boolean expression? I have not come across any packages that support this entirely.
The following is true in theory. But since you're using Go if you can use Go syntax then you can use Go's parser and AST. I don't see any code that can evaluate a Go AST at runtime. But you could probably write one that supported the parts you wanted. Then you'd have a Go interpreter.
The following is what you need to do to support any random expression syntax:
You are going to want to lex and parse. Build an AST (Abstract Syntax Tree) in memory. Then evaluate it.
Your tree nodes might be (my Go syntax is way wrong for this):
Scope {Tree {
Assignment { Symbol: "name", Symbol: "_literal_1" }
Assignment { Symbol: "exp", Value: Tree: {
AndOperation { Tree{...}, Tree{...} }
}
}
Etc.
Then your program can traverse your AST directly or you can write it into bytecode form, but that's really only useful if you want it to be smaller and easy to cache for later.
I am very new to Xtext/Xtend, therefore apologies in advance if the answer is obvious.
I would like to allow the end-users of my DSL to define a 'filter', that when applied and 'returns' true it means that they want to 'filter out' the given entity of data from consideration.
I want to allow them 2 ways of defining the filter
A) by introspecting the attributes of a given data object and apply basic rules like
if (obj.field1<CURRENT_DATE && obj.field2=="EXPIRED)
{ return true;} else {return false;}
B) by executing a controlled snippet using 'eval' of my host language
In other words, the user would be expected to type into a string/code block a valid
code snippet of the hosting language
I had decided that the easiest way for me support case A) would be to leverage the XBase rules (including expressions/etc)
Therefore I defined filters (mostly copying the ideas from Lorenzo's book)
Filter:
(FilterDSL | FilterCode);
FilterDSL:
'filterDSL' (type=JvmTypeReference)? name=ID
'(' (params+=FullJvmFormalParameter (',' params+=FullJvmFormalParameter)*)? ')'
body=XBlockExpression ;
FilterCode:
'filterCode' (type=JvmTypeReference)? name=ID
'(' (params+=FullJvmFormalParameter (',' params+=FullJvmFormalParameter)*)? ')'
'{'
body=STRING
'}';
Now when trying to implement the Java mapping for my DSL, via the inferrer stub in Xtend -- I am running into multiple problems.
All of them likely indicate that I am missing some fundamental understanding
Problem 1) fl.body is not defined. fl Is of type Filter, not FilterDSL or FilterCode
And I do not understand how to check what type a given instance is of, so that I can access the content of a 'body' feature.
Problem 2) I do not understand where 'body' attribute in the inferrer method is defined and why. Is this part of ECore? (I could not find it)
Problem 3) what's the proper way to allow a user to specify a code block? String seems to be not the right thing as it does not allow multiline
Problem 4) How do I correctly convert a code block into something that is accepted by the 'body' such that it ends up in the generated code.
Problem 5) How do I setup multiple inferrers (as I have more than one thing for which I need the code generated (mostly) by xBase code generator)
Appreciate in advance any suggestions, or pointer to code examples solving similar problems.
As a side observation, Inferrer and its interplay with XBase has sofar been the most confusing and difficult thing to understand.
in general: have a look at the xtend docs at xtend-lang.org
You can do a if (x instanceof Type) or a switch statement with Type guards (see domain model example)
i dont get that question. both your FilterDSL and FilterCode EClasses should have a field+getter/setter named body, FilterCode of type String, FilterDSL of type XBlockExpression. The JvmTypesBuilder add extension methods to JvmOperation called setBody(String) and setBody(XExpression), syntax sugar lets you call body = .... instead of setBody(...)
(btw you can do crtl+click to find out where a thing is defined)
strings are actually multiline
is answered by (2)
you dont need multiple inferrers, you can infer multiple stuff e.g. by calling toClass or toField multiple times for the same input
I'm not even sure about how to title this qn. But, hope there is an easy way to do it in dynamic language like groovy.
say I have a class Service, where I delegate the business logic. the methods in it are
funA(), funB()... funX().
Now I have a controller class, where I call the service closure, which can be invoked like service.funA() . Now based on a variable (which can have values A, B ... X), I need to cal the correct service closure. Basically to avoid writing lot of if conditional statements. Something like service."fun+var"() would do. I'm not sure whether it is possible to substitute variable in closure (function)name. or any way by passing function (name) as a parameter...not sure
I think PHP has a similar feature http://php.net/manual/en/functions.variable-functions.php
thanks for any pointer..
Yes, this is possible. This should do what you want:
service."fun${var}"()
The correct title is dynamic method invocation.