Using ANTLR4 to create functions with no argument - function

I am still new to ANTLR4 and I am trying to achieve the following
I have business rules which consist of logical operation
(A= 'text' or B < 1) and getDataDB
the function getDataDB does not take any argument. the function will retrieve some data to validate it and return either true or false.
my grammar is below
/*
* Test grammar
*/
grammar FunctionRule;
parse: expr EOF
;
expr
: expr binop expr #logicalExpression
| lhs=VARIABLE compop rhs=VARIABLE #variableExpression
| lhs=VARIABLE compop rhs=STRING #stringExpression
| lhs=VARIABLE compop rhs=NUMBER #numberExpression
| TRUE #booleanTrue
| FALSE #booleanFalse
| function #functionExpression
| VARIABLE #booleanVariable
| LEFTPAREN expr RIGHTPAREN #enclosedExpression
;
binop : AND | OR
;
compop: EQUAL | LT | GT | LTE | GTE | NE
;
function : ID {System.out.println("HELLLL");};
TRUE: 'true' | 'TRUE' ;
FALSE: 'false' | 'FALSE';
STRING: '"' ~([\t\n\r]| '"')* '"'
;
ID : [getDataDB];
LEFTPAREN: '(';
RIGHTPAREN: ')';
EQUAL : '=' | 'EQ';
LT : '<' | 'LT';
GT : '>' | 'GT';
LTE : '<=' | 'LE';
GTE : '>=' | 'GE';
NE : '!=' | 'NE';
AND : 'AND' | '&' | 'and';
OR : 'OR' | 'or' | '|';
VARIABLE : [a-zA-Z]+[a-zA-Z0-9_.-]*;
NUMBER : [0-9]+ ('.'[0-9]+)?;
SPACE : [ \t\r\n] -> skip;
When I generate classes from the grammar, i did not see anything related to the function.
1-how do I define a function correctly in the grammar file.
2- where i can put the code for this function after creating the classes, is it only in the action clause, is there is a way to put the class name in the grammar where i can put the implementation
Thanks for the help!

ID : [getDataDB];
This means that ID matches a single letter that could be either one of g, e, t, D, a or B. What you likely wanted is ID: 'getDataDB'; which matches the string getDataDB. Note that calling this ID is highly misleading.
where i can put the code for this function
Are you writing an interpreter using a visitor? Then you'd put the code into the visitFunction method or rather in a getDataDB method that you call from visitFunction if the function name was equal to getDataDB (right now that would always be the case, but I'm assuming you eventually want to introduce more than one function).
Alternatively you could also structure your grammar slightly differently like this (removing the ID rule):
function : 'getDataDB' # GetDataDB
| 'otherFunction' # OtherFunction
;
Then you could define the functions in visitGetDataDB and visitOtherFunction respectively.
All that's assuming that you want function names to be keywords (which implies that there can't be user-definable functions). If you don't, you should not have separate tokens for function names, so zero-argument functions and variables become indistinguishable syntactically (unless you add a requirement to add () for functions, but it doesn't look like that's what you want). So you should just have one rule that could be either a variable or a zero-argument function and then check whether the given identifier is the name of a function in visitVariableOrNullaryFunction (which maybe you'd just call visitVariable for brevity).

Related

How to make request in jq

I'm trying to make request in jq:
cat testfile.txt | jq 'fromjson | select(.kubernetes.pod.memory.usage.bytes != null) .kubernetes.pod.memory.usage.bytes, ."#timestamp"'
My output is:
"2019-03-15T00:24:21.733Z"
"2019-03-15T00:25:10.169Z"
"2019-03-15T00:24:47.908Z"
105889792
"2019-03-15T00:25:04.446Z"
34557952
"2019-03-15T00:25:04.787Z"
How to delete excess dates?
For example output only:
105889792
"2019-03-15T00:25:04.446Z"
34557952
"2019-03-15T00:25:04.787Z"
You just need to add a pipe after select :
cat testfile.txt | jq 'fromjson | select(.kubernetes.pod.memory.usage.bytes != null) | .kubernetes.pod.memory.usage.bytes, ."#timestamp"'
Here's a DRYer (as in dry) solution:
.["#timestamp"] as $ts | .kubernetes.pod.memory.usage.bytes // empty | ., $ts
Note that this particular use of // assumes that you wish to treat null, false, and a missing key in the same way. If not, you can still use the same idea to stay DRY.

How to fix timeless execution in cypher query - Neo4j Graph Database?

I'm dealing with the import of Common Weakness Enumeration Catalog (.json file) to the Neo4j Graph Database, using cypher language query and the apoc library. Although i import properly the fields: Weaknesses, Views, External_References, i have an execution problem (without any error) with the import of the field: Categories which is executing without ending. Below i present the structure of .json file and my cypher code.
"Weakness_Catalog": {
"Weaknesses": {"Weakness":[...]}
"Categories": {"Category":[...]}
"Views": {"View":[...]}
"External_References": {"External_Reference":[...]}
}
Cypher Query
After several tests i think that the logic error is between the last 2 parts [with value....(catRef)], without them, the query executes pretty good, at normal time. I've also changed a setting param. at the db configuration file due to an error (cypher.lenient_create_relationship = true). And i tested the different import sequence with the same bad results (weakness, categories, views, ext. references etc.)
call apoc.load.json(files) yield value
unwind value.Weakness_Catalog.Weaknesses.Weakness as weakness
merge (i:GeneralInfo_CWE {Name:value.Weakness_Catalog.Name, Version:value.Weakness_Catalog.Version,
Date:value.Weakness_Catalog.Date, Schema:'https://cwe.mitre.org/data/xsd/cwe_schema_v6.4.xsd'})
merge(w:CWE {Name:'CWE-' + weakness.ID})
set w.Extended_Name=weakness.Name, w.Abstraction=weakness.Abstraction,
w.Structure=weakness.Structure, w.Status=weakness.Status, w.Description=weakness.Description,
w.Extended_Description= apoc.convert.toString(weakness.Extended_Description),
w.Likelihood_Of_Exploit=weakness.Likelihood_Of_Exploit,
w.Background_Details=apoc.convert.toString(weakness.Background_Details.Background_Detail),
w.Modes_Of_Introduction=[value in weakness.Modes_Of_Introduction.Introduction | value.Phase],
w.Submission_Date=weakness.Content_History.Submission.Submission_Date,
w.Submission_Name=weakness.Content_History.Submission.Submission_Name,
w.Submission_Organization=weakness.Content_History.Submission.Submission_Organization,
w.Modifications=[value in weakness.Content_History.Modification | apoc.convert.toString(value)],
w.Alternate_Terms=apoc.convert.toString(weakness.Alternate_Terms),
w.Notes=[value in weakness.Notes.Note | apoc.convert.toString(value)],
w.Affected_Resources=[value in weakness.Affected_Resources.Affected_Resource | value],
w.Functional_Areas=[value in weakness.Functional_Areas.Functional_Area | value]
merge (w)-[:belongsTo]->(i)
with w, weakness, value
unwind weakness.Related_Weaknesses.Related_Weakness as Rel_Weakness
match (cwe:CWE) where cwe.Name='CWE-' + Rel_Weakness.CWE_ID
merge (w)-[:Related_Weakness{Nature:Rel_Weakness.Nature}]->(cwe)
with w, weakness, value
unwind weakness.Applicable_Platforms as appPl
foreach (lg in appPl.Language |
merge(ap:Applicable_Platform{Type:'Language', Prevalence:lg.Prevalence,
Name:coalesce(lg.Name, 'NOT SET'), Class:coalesce(lg.Class, 'NOT SET')})
merge(w)-[:Applicable_Platform]->(ap))
with w, weakness, value, appPl
foreach (tch in appPl.Technology |
merge(ap:Applicable_Platform{Type:'Technology', Prevalence:tch.Prevalence,
Name:coalesce(tch.Name, 'NOT SET'), Class:coalesce(tch.Class, 'NOT SET')})
merge(w)-[:Applicable_Platform]->(ap))
with w, weakness, value, appPl
foreach (arc in appPl.Architecture |
merge(ap:Applicable_Platform{Type:'Architecture', Prevalence:arc.Prevalence,
Name:coalesce(arc.Name, 'NOT SET'), Class:coalesce(arc.Class, 'NOT SET')})
merge(w)-[:Applicable_Platform]->(ap))
with w, weakness, value, appPl
foreach (os in appPl.Operating_System |
merge(ap:Applicable_Platform{Type:'Operating System', Prevalence:os.Prevalence,
Name:coalesce(os.Name, 'NOT SET'), Class:coalesce(os.Class, 'NOT SET')})
merge(w)-[:Applicable_Platform]->(ap))
with w, weakness, value
foreach (example in weakness.Demonstrative_Examples.Demonstrative_Example |
merge(ex:Demonstrative_Example {Intro_Text:apoc.convert.toString(example.Intro_Text)})
set ex.Body_Text=[value in example.Body_Text | apoc.convert.toString(value)],
ex.Example_Code=[value in example.Example_Code | apoc.convert.toString(value)]
merge (w)-[:hasExample]->(ex))
with w, weakness, value
foreach (consequence in weakness.Common_Consequences.Consequence |
merge (con:Consequence{CWE:w.Name, Scope:[value in consequence.Scope | value]})
set con.Impact=[value in consequence.Impact | value],
con.Note=consequence.Note, con.Likelihood=consequence.Likelihood
merge(w)-[:hasConsequence]->(con))
with w, weakness, value
foreach (dec in weakness.Detection_Methods.Detection_Method |
merge(d:Detection_Method {Method:dec.Method})
merge(w)-[wd:canBeDetected{Description:apoc.convert.toString(dec.Description)}]->(d)
set wd.Effectiveness=dec.Effectiveness, wd.Effectiveness_Notes=dec.Effectiveness_Notes,
wd.Detection_Method_ID=dec.Detection_Method_ID)
with w, weakness, value
foreach (mit in weakness.Potential_Mitigations.Mitigation |
merge(m:Mitigation {Description:apoc.convert.toString(mit.Description)})
set m.Phase=[value in mit.Phase | value], m.Strategy=mit.Strategy,
m.Effectiveness=mit.Effectiveness, m.Effectiveness_Notes=mit.Effectiveness_Notes,
m.Mitigation_ID=mit.Mitigation_ID
merge(w)-[:hasMitigation]->(m))
with w, weakness, value
foreach (rap in weakness.Related_Attack_Patterns.Related_Attack_Pattern |
merge(cp:CAPEC {Name:rap.CAPEC_ID})
merge(w)-[:RelatedAttackPattern]->(cp))
with w, weakness, value
foreach (reference in value.Weakness_Catalog.External_References.External_Reference |
merge(r:External_Reference{Reference_ID:reference.Reference_ID})
set r.Author=[value in reference.Author | value], r.Title=reference.Title,
r.Edition=reference.Edition, r.URL=reference.URL,
r.Publication_Year=reference.Publication_Year, r.Publisher=reference.Publisher)
with w, weakness, value
unwind weakness.References.Reference as exReference
match (ref:External_Reference) where ref.Reference_ID=exReference.External_Reference_ID
merge(w)-[:hasExternal_Reference]->(ref)
with value
unwind value.Weakness_Catalog.Views.View as view
merge (v:CWE_VIEW{ViewID:view.ID})
set v.Name=view.Name, v.Type=view.Type, v.Status=view.Status,
v.Objective=apoc.convert.toString(view.Objective), v.Filter=view.Filter,
v.Notes=apoc.convert.toString(view.Notes),
v.Submission_Name=view.Content_History.Submission.Submission_Name,
v.Submission_Date=view.Content_History.Submission.Submission_Date,
v.Submission_Organization=view.Content_History.Submission.Submission_Organization,
v.Modification=[value in view.Content_History.Modification | apoc.convert.toString(value)]
foreach (value in view.Audience.Stakeholder |
merge (st:Stakeholder{Type:value.Type})
merge (v)-[rel:usefulFor]->(st)
set rel.Description=value.Description)
with v, view, value
unwind (case view.Members.Has_Member when [] then [null] else view.Members.Has_Member end) as members
optional match (MemberWeak:CWE{Name:'CWE-' + members.CWE_ID})
merge (v)-[:hasMember{ViewID:members.View_ID}]->(MemberWeak)
with v, view, value
unwind (case view.References.Reference when [] then [null] else view.References.Reference end) as viewExReference
optional match (viewRef:External_Reference{Reference_ID:viewExReference.External_Reference_ID})
merge (v)-[:hasExternal_Reference{ViewID:v.ViewID}]->(viewRef)
with value
unwind value.Weakness_Catalog.Categories.Category as category
merge (c:CWE_Category{CategoryID:category.ID})
set c.Name=category.Name, c.Status=category.Status, c.Summary=apoc.convert.toString(category.Summary),
c.Notes=apoc.convert.toString(category.Notes), c.Submission_Name=category.Content_History.Submission.Submission_Name,
c.Submission_Date=category.Content_History.Submission.Submission_Date,
c.Submission_Organization=category.Content_History.Submission.Submission_Organization,
c.Modification=[value in category.Content_History.Modification | apoc.convert.toString(value)]
with c, category
unwind (case category.References.Reference when [] then [null] else category.References.Reference end) as categoryExReference
optional match (catRef:External_Reference{Reference_ID:categoryExReference.External_Reference_ID})
merge (c)-[:hasExternal_Reference{CategoryID:c.CategoryID}]->(catRef)
So, the problem was that every time i use with, i'm working in nested loops. The more nested loops, the slower the query will be. A good way to speed up, is to create simplier queries when it's possible.
For example in the json file:
"Weakness_Catalog": {
"Weaknesses": {"Weakness":[...]}
"Categories": {"Category":[...]}
"Views": {"View":[...]}
"External_References": {"External_Reference":[...]}
}
i will execute one query for Weaknesses, one for Categories, one for Views and one for External_References.

Difference between `null` and `no output`

I've encountered some difference between null and nothing, can somebody explain it? As in most languages null is considered/used to represent nothing.
The select is documented to return no output. And adding(ie. +) null to X yields X. Now consider these demonstrative examples(takes no input):
adding nothing
here we have empty object, which we update with nothing:
{} | . |= . + ({} | select (.foo == 123))
which results in
null
adding null
same template but with alternative operator to substitute nothing to null:
{} | . |= . + ({} | select (.foo == 123)//null)
which results in
{}
Can someone explain the difference nothing vs null?
null is just a regular JSON value; and conceptually, it is totally different from the absence of a value, i.e, what you termed nothing. Take a look at these for example (empty is a filter that returns nothing):
$ jq -n '[null] | length'
1
$ jq -n '[empty] | length'
0
That {} + null returns {} back, and that {} | . |= empty does exactly what del(.) does are merely design choices.

create ++ operator in VHDL

I would like to have a new C++ style operator for the STD_LOGIC_VECTOR type. So far I managed to create and use the following function:
FUNCTION PLUS_ONE ( a : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR is
BEGIN
RETURN std_logic_vector( unsigned( a ) + 1);
END FUNCTION;
now if i create this:
FUNCTION "++" ( a : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR is
BEGIN
RETURN std_logic_vector( unsigned( a ) + 1);
END FUNCTION;
ISE throws the following error:
"++" is not a predefined operator.
Now the question is, is it possible to create new operators in VHDL an I am missing something
You can only overload operators in VHDL, you cannot create new operator symbols. Quoting the LRM (section 4.5.2):
The declaration of a function whose designator is an operator symbol
is used to overload an operator. The sequence of characters of the
operator symbol shall be one of the operators in the operator classes
defined in 9.2.
And the corresponding section of the manual says:
condition_operator ::= ??
logical_operator ::= and | or | nand | nor | xor | xnor
relational_operator ::= = | /= | < | <= | > | >= | ?= | ?/= | ?< | ?<= | ?> | ?>=
shift_operator ::= sll | srl | sla | sra | rol | ror
adding_operator ::= + | – | &
sign ::= + | –
multiplying_operator ::= * | / | mod | rem
miscellaneous_operator ::= ** | abs | not
As much as I like brevity, I must admit that choosing shorthand operators over standard ways of writing expressions is "syntactic sugar", and has a potential to obfuscate the code. It is interesting to note that "trendier" languages like Python and Ruby don't have a ++ operator as well.
Could VHDL support the ++ operator? I'm currently working on a VHDL parser, and I risk saying that adding a postfix ++ operator would break quite a few rules of the language grammar, especially because unary operators expect to take an operand to the right of the symbol. Owing to this and to the fact that aren't many strong arguments in favor of such a change, I don't expect to see it anytime soon. All thigs considered, my personal choice has been to stick with value := value + 1 for standard data types.

ANTLR: problem differntiating unary and binary operators (e.g. minus sign)

i'm using ANTLR (3.2) to parse some rather simple grammar. Unfortunately, I came across a little problem. Take the follwoing rule:
exp
: NUM
| '(' expression OPERATOR expression ')' -> expression+
| '(' (MINUS | '!') expression ')' -> expression
;
OPERATOR contains the same minus sign ('-') as is defined with MINUS. Now ANTLR seems to be unable to deal with these two rules. If I remove either one, everything works fine.
Anyone ideas?
Make the unary expression the one with the highest precedence. I'd also use a different token for the unary - to make the distinction between the minus better. A demo:
grammar Exp;
options {
output=AST;
}
tokens {
UNARY;
}
parse
: exp EOF
;
exp
: additionExp
;
additionExp
: multiplyExp ('+'^ multiplyExp | '-'^ multiplyExp)*
;
multiplyExp
: unaryExp ('*'^ unaryExp | '/'^ unaryExp)*
;
unaryExp
: '-' atom -> ^(UNARY atom)
| '!' atom -> ^('!' atom)
| atom
;
atom
: '(' exp ')' -> exp
| Number -> Number
;
Number : ('0'..'9')+ ('.' ('0'..'9')+)? ;
Spaces : (' ' | '\t' | '\r'| '\n') {$channel=HIDDEN;} ;
A quick test with the source:
3 * -4 + 7 / 6 * -(3 + -7 * (4 + !2))
produced the following AST:
image created using http://graph.gafol.net/