ANTLR ambigous reference - how to get output? - antlr

So I have a rule for statement which can lead to more statements:
statement returns[String txt]
: '{'{
$txt="{";
}
(statement{
$txt+=$statement.txt;
})*
'}'{
$txt+="}";
}
| ... //more rules // ...
;
I am getting
reference $statement is ambiguous; rule statement is enclosing rule and referenced in the production (assuming enclosing rule)
but don't know how to resolve it. Somehow I would need to tell ANTLR that I need the return txt of statement inside parent statement. Please help me out :)

If you use $statement, ANTLR doesn't know if you mean the rule itself, or the statement inside ( ... )*.
Try something like this:
statement returns[String txt]
: '{'{
$txt="{";
}
(s=statement{
$txt+=$s.txt;
})*
'}'{
$txt+="}";
}
| ...
;

Related

Drupal 7 - db_select: SQL function in where condition

I need to use this condition in my select statement:
WHERE YEAR(date) = YEAR(CURDATE())
but if I do, like this:
$query = db_select('table', 't');
$query->fields('t');
$query->condition('YEAR\(date\)', 'YEAR(CURDATE())', '=');
Drupal won't have it (even if I do not escape those parenthesis - it simply ignores them) because I get an error:
Column not found: 1054 Unknown column 'YEARdate' in 'where clause':
How to overcome this error?
Hmm.. just like this, it seems:
$query->where('YEAR(date) = YEAR(CURDATE())');
The where allows for the arbitrary SQL:
The where() method allows for the addition of arbitrary SQL as a conditional fragment. $snippet may contain any legal SQL fragment, and if it has variable content it must be added using a named placeholder. The $args array is an array of placeholders and values that will be substituted into the snippet. It is up to the developer to ensure that the snippet is valid SQL. No database-specific modifications are made to the snippet.
Hm, you could also use db_query, it allow you to write SQL queries "without Drupal".
I mean, you'll be able to add custom WHERE statements or any SQL-proper functions, like custom functions ;)
Eg.
$result = db_query('SELECT title FROM {node} WHERE type = "%s" AND title LIKE "%%%s%%"', 'type', 'title');
Use addExpression method :
https://api.drupal.org/api/drupal/includes!database!select.inc/function/SelectQuery%3A%3AaddExpression/7.x
$query = db_select('table', 't');
$query->fields('t');
$query->addExpression('YEAR(t.date) = YEAR(CURDATE())');
$result = $query->execute()->fetchAll();
var_dump($result);

DB2 PL/SQL structure, begin atomic including with query

I'm trying to use db2 pl/sql script giving a template code.
--#set delimiter !
begin atomic
for S as
<query statement that finds quests, "swaps", with a donor/donation & recipient pair>
do
<update statement that fixes Loot with the swap 'S'>;
end for;
-- handle each swap
end!
-- we're done once through
in my query statement i used something like this:
with
t1 (args) as (
...
)
...
select ...
where ... ;
in the update statement
update Loot set ... where ...
but the problem is, when i try to run the full sql code script on the database, I keep getting the message :
"An unexpected token "begin" was found following "<identifier>".
Expected tokens may include: "USER". SQLSTATE=42601 DB21007E End of file
reached while reading the command.
I want to know, how to use the proper syntax or format to include the "with queries" and also update statement to stop giving me the error. I have the "with query" working in a separate file, but when i combine both statements into the template, it would give me this error. Also as well, if I were to include triggers, which part of the code should i put it in. Thank you.
Here is an example that might help.
CREATE TABLE EG(I INT, J INT)!
INSERT INTO EG VALUES (1,1),(2,3)!
begin
for c as with w(i,u) as(values (2,5)) select i,u from w
do
update eg set j = j + c.u where i = c.i;
end for;
end
!
If this does not help your problem, please post a version of your code that we can run and which returns the error message that you are struggling with.

SPARQL Update not working

I am trying to perform a simple update of the value of a property that that has a given resource as its subject.
Here is my query:
WITH <http://127.0.0.1:3000/dendro_graph>
DELETE { <http://127.0.0.1:3000/project/datanotes/records/teste/filho%20do%20teste> <http://purl.org/dc/elements/1.1/creator> ?o0 .
}
INSERT
{
<http://127.0.0.1:3000/project/datanotes/records/teste/filho%20do%20teste> <http://purl.org/dc/elements/1.1/creator> "creator1" .
}
WHERE { <http://127.0.0.1:3000/project/datanotes/records/teste/filho%20do%20teste> <http://purl.org/dc/elements/1.1/creator> ?o0 .
}
The result of this is that the delete is executed, but the insert is not; I end up destroying all instances of the property, but no new value is added.
If I remove the WHERE clause, I end up with duplicate triples, because it seems the DELETE is not executed.
What am I doing wrong?
EDIT:
This code produces the duplicates:
WITH <http://127.0.0.1:3000/dendro_graph>
DELETE
{
<http://127.0.0.1:3000/project/datanotes/records/teste/filho%20do%20teste> <http://purl.org/dc/elements/1.1/creator> ?o0 .
}
INSERT
{
<http://127.0.0.1:3000/project/datanotes/records/teste/filho%20do%20teste> <http://purl.org/dc/elements/1.1/creator> "creator1" .
}
The query without the WHERE clause is not a legal SPARQL expression, and should have resulted in a syntax error. If the engine you're using accepts this, then that is a bug in that engine.
At first glance, ditto for the earlier operation, which you say deletes but does not insert: as far as I can see the SPARQL expression is correct, and if as you say the insert part does not get executed, that means you've discovered a bug in the engine that executes it. I recommend you get in touch with the developers directly.
Here is a workaround I used to get this working (finally thank God). It seems you can specify several operations to be executed over the graph in a single operation using the semicolon ;.
I ended up specifying the DELETE statement and then the UPDATE one
Check this out for code sample : SPARQL Update example for updating more than one triple in a single query

ANTLR: return always the same number of children

I have the following rule:
statement : TOKEN1 opt1=TOKEN2? opt2=TOKEN3 TOKEN4 -> ^(TOKEN1 opt1? opt2);
The AST generated by this rule will have one or two children (depending on if
opt1 was defined or not).
I need to have always a fixed number of children (in this case 2). I know that
this can be achieved by doing the following (UNDEFINED is an imaginary token):
statement : TOKEN1 opt1=TOKEN2 TOKEN4 -> ^(TOKEN1 opt1 UNDEFINED)
| TOKEN1 opt1=TOKEN2 opt2=TOKEN3 TOKEN4 -> ^(TOKEN1 opt1 opt2);
This is fine for just one optional token. The problem is when I have a higher
number of optional tokens. A lot of rules must written in order to catch all
possible combinations. How can this issue be solved in an elegant way?
I'm using ANTLR 3.4/C target by the way.
Thanks,
T.
You could do this:
grammar G;
tokens {
CHILD1;
CHILD2;
CHILD3;
}
...
statement
: ROOT t2=TOKEN2? t3=TOKEN3? t4=TOKEN4?
-> ^(ROOT ^(CHILD1 $t2?) ^(CHILD2 $t3?) ^(CHILD3 $t4?))
;
which will cause the AST to always have 3 child nodes (which may or may not have a tokens as child themselves).

multiple return values in ANTLR

I use ANTLR4 with Java and I would like to store the values that a rule returns while parses the input. I use a grammar like this:
db : 'DB' '(' 'ID' '=' ID ',' query* ')'
{
System.out.println("creating db");
System.out.println("Number of queries -> "+$query.qs.size());
}
;
query returns [ArrayList<Query> qs]
#init
{
$qs = new ArrayList<Query>();
}
: 'QUERY' '(' 'ID' '=' ID ',' smth ')'
{
System.out.println("creating query with id "+$ID.text);
Query query = new Query();
query.setId($ID.text);
$qs.add(query);
}
;
but what happens is that the Number of queries printed ($query.qs size) is always one. This happens because each time a QUERY element is recognized at input it is added to the $qs ArrayList, but for each other QUERY a new ArrayList is instantiated and this query is added to this new ArrayList. When all the queries are recognized then the action for the db : rule is invoked, but the $query.qs ArrayList has only the last query. I solved this problem by maintaining global ArrayLists that store the queries. But, is there another way to do it with ANTLR while the rules are returning, and not having my own global ArrayLists?
Many thanks in advance,
Dimos.
Well, the problem is resolved. I just added the ArrayList to the db rule like this:
db [ArrayList queries] : 'DB' ....
and then at query rule:
$db::queries.add(query)
So, everything is fine!
Thanks for looking, anyway!