ANTLR Parsing rule covering block of text containing the "End"-Token - parsing

I am wondering whether there is a possibility for antlr parsing rules to create rules that match Strings containing the endtoken. I'll illustrate this by using an sql-example:
CREATE FUNCTION UFHDBTBL.FH_LIEF_SPERR_SK(pidpack INTEGER)
...
BEGIN ATOMIC
DECLARE sperrsk VARCHAR(2000) DEFAULT '';--
DECLARE erster INTEGER DEFAULT 0;--
FOR satz AS
SELECT sk_name1
FROM UFHDBTBL.FH01TM21 psk, UFHDBTBL.FH01T61 lsk
WHERE psk.id_pack = pidpack
DO
IF erster = 1 THEN
SET sperrsk = sperrsk || '<br>';--
END IF ;--
SET sperrsk = sperrsk || LTRIM(RTRIM(satz.sk_name1));--
IF erster = 0 THEN
SET erster = 1;--
END IF ;--
END FOR;--
RETURN sperrsk;--
END;
Currently, I tried the following parsing-rules to match all the stuff between "BEGIN ATOMIC" and "END;":
'BEGIN' ~('END') 'END'
'BEGIN' .+? 'END'
'BEGIN' (~('END')|~(';'))* 'END'
(The last ; is contained in the "create function rule" so don't worry about it)
Notice, that the block contains the tokens "END" and ";". Since I don't want to create a new token "END;" (which causes many other rules to fail), I hope there is some antlr guy around who's able to help me!

You could use something like the following to match everything until END; without creating a new single token to represent it.
'BEGIN'
( ~'END'
| 'END' ~';'
)*
'END' ';'

Related

unexpected token error in plsql procedure

CREATE PROCEDURE EPS.PROCEDURE_OTE_LTE_BIDDER_REPORT
(
IN P_USERID INTEGER,
IN P_AUCTIONID INTEGER,
IN P_REPORT_FLAG VARCHAR(3),
OUT O_ERROR_CODE INTEGER,
OUT OUTPUT_MESSAGE VARCHAR(100),
IN P_LOG_USERID INTEGER
)
LANGUAGE SQL
P1:BEGIN ATOMIC DECLARE SQLCODE INTEGER DEFAULT 0;
DECLARE V_USERID INTEGER;
DECLARE V_AUCTIONID INTEGER;
DECLARE V_REPORT_FLAG_TECHNOCOMMERCIALQUALIFIEDCUSTOMER VARCHAR(3);
DECLARE V_COUNT_TECHNOCOMMERCIALQUALIFIEDCUSTOMER INTEGER;
DECLARE V_REPORT_FLAG_SELECTIVEUSERWISETENDERREPORT VARCHAR(3);
DECLARE V_COUNT_SELECTIVEUSERWISETENDERREPORT INTEGER;
SELECT COUNT(*) INTO V_COUNT_TECHNOCOMMERCIALQUALIFIEDCUSTOMER FROM EPS.TECHNOCOMMERCIALQUALIFIEDCUSTOMER A
WHERE A.AUCTIONID=P_AUCTIONID AND A.USERID=P_USERID;
SELECT COUNT(*) INTO V_COUNT_SELECTIVEUSERWISETENDERREPORT FROM EPS.SELECTIVEUSERWISETENDERREPORT B
WHERE B.AUCTIONID=P_AUCTIONID AND B.USERID=P_USERID;
IF P_REPORT_FLAG = 'Y' THEN
IF V_COUNT_TECHNOCOMMERCIALQUALIFIEDCUSTOMER < 1 THEN
INSERT INTO EPS.TECHNOCOMMERCIALQUALIFIEDCUSTOMER (A.AUCTIONID,A.USERID,A.QUALIFIED) VALUES (P_AUCTIONID,P_USERID,'Y');
ELSE
SET OUTPUT_MESSEGE = 'DATA ALREADY PRESENT';
END IF;
ELSE
IF V_COUNT_TECHNOCOMMERCIALQUALIFIEDCUSTOMER > 0 THEN
DELETE FROM EPS.TECHNOCOMMERCIALQUALIFIEDCUSTOMER C WHERE C.AUCTIONID=P_AUCTIONID AND C.USERID=P_USERID;
ELSE
SET OUTPUT_MESSAGE = 'NO DATA FOUND';
END IF;
END IF;
IF P_REPORT_FLAG = 'Y' THEN
IF V_COUNT_SELECTIVEUSERWISETENDERREPORT < 1 THEN
INSERT INTO EPS.SELECTIVEUSERWISETENDERREPORT AA
( AA.AUCTIONID,
AA.USERID,
AA.TENDERREPORTTYPEID,
AA.STATUS,
AA.CREATEID,
AA.CREATEDATE,
AA.UPDATEID,
AA.UPDATEDATE
)
VALUES
(
P_AUCTIONID,
P_USERID,
103.
'A',
P_LOG_USERID,
CURRENT TIMESTAMP,
NULL,
NULL
);
ELSE
SET OUTPUT_MESSEGE = 'DATA ALREADY PRESENT';
END IF;
ELSE
IF V_COUNT_SELECTIVEUSERWISETENDERREPORT > 0 THEN
DELETE FROM EPS.SELECTIVEUSERWISETENDERREPORT CC WHERE CC.AUCTIONID=P_AUCTIONID AND CC.USERID=P_USERID;
ELSE
SET OUTPUT_MESSAGE = 'NO DATA FOUND';
END IF;
END IF;
END P1
I am getting this error
SQL Error [42601]: An unexpected token "END-OF-STATEMENT" was found following "Y PRESENT'". Expected tokens may include: "
END IF".. SQLCODE=-104, SQLSTATE=42601, DRIVER=4.7.85
SQL Error [42601]: An unexpected token "END-OF-STATEMENT" was found following "Y PRESENT'". Expected tokens may include: "
END IF".. SQLCODE=-104, SQLSTATE=42601, DRIVER=4.7.85
An unexpected token "END-OF-STATEMENT" was found following "Y PRESENT'". Expected tokens may include: "
END IF".. SQLCODE=-104, SQLSTATE=42601, DRIVER=4.7.85
An unexpected token "END-OF-STATEMENT" was found following "Y PRESENT'". Expected tokens may include: "
END IF".. SQLCODE=-104, SQLSTATE=42601, DRIVER=4.7.85
It helps to properly use a syntax editor that understands SQL, and take more care with checking your code. A good SQL editor may highlight your mistakes before you try to compile, as would any code review.
On a separate note, you should understand the difference between ANSI SQL PL and Oracle PL/SQL. Your code seems to use ANSI SQL PL syntax, although your mistakes may be mistakes for any flavour of SQL.
Here are some of the obvious syntax mistakes in your code (there may be others):
On the line INSERT INTO EPS.SELECTIVEUSERWISETENDERREPORT AA , the AA should be omitted.
For the same insert statement you have 103., when you might mean 103,.
For the line INSERT INTO EPS.TECHNOCOMMERCIALQUALIFIEDCUSTOMER (A.AUCTIONID,A.USERID,A.QUALIFIED) you probably mean instead
INSERT INTO EPS.TECHNOCOMMERCIALQUALIFIEDCUSTOMER (AUCTIONID,USERID,QUALIFIED)
The same mistake is present for the line with INSERT INTO EPS.SELECTIVEUSERWISETENDERREPORT (do not qualify the column names).
For the line beginning SET OUTPUT_MESSEGE = you probably mean SET OUTPUT_MESSAGE =, and this typo is present on other lines.

How to read the values from one flat file and use them in loop in PostgreSQL file?

The requirement is to read the values from one flat file and use them in for loop to modify the pgSQL queries.
I'm new to PostgreSQL. Please suggest any.
CREATE FUNCTION file_vals()
RETURNS varchar[] AS
$BODY$
return (readLines('my_file.txt'))
$BODY$
language plpgsql;
DO $ANONYMOUS_BLOCK$ declare
/* data */
begin
for c, l in user_c, file_vals()
loop
perform x.y(user => c.user, password => l);
RAISE NOTICE '%', c.user;
end loop;
end $ANONYMOUS_BLOCK$;
I'm trying to read the values from my_file.txt and also use the values in for loop to insert the values in database(x.y is the psql function) .
my_file.txt contains passwords:
a
b
c
d
user_c is cursor, which is having user values.
Need to use both the values i.e, user_c and file_vals in one single for loop statement.
Error:
psql:test.psql:6: ERROR: syntax error at or near "return"
LINE 4: return (readLines('my_file.txt'))
^
SET
psql:test.psql:20: ERROR: "c" is not a known variable
LINE 7: for c, l in user_c, file_vals()

Is it possible to consume tick in a Forth definition?

When reading about the tick (') operator I wondered if it can be useful inside a word definition. I know that there is ['] to be used inside a definition, but I thought about using it to read the word name following invocation.
An example:
4 variable cnt
: cycle: ( arg fn -- )
'
4 cnt !
begin
cr
dup execute
-1 cnt +!
cnt # 0 = until
drop
;
I can use cycle: to repeat some word invocation, as follows.
: hello ." hello" ;
cycle: hello
Which prints hello four times, as expected.
But the following code won't define a word that prints hello four times:
: 4hello cycle: hello ;
The tick operator still expects a word from the input stream following invocation of 4hello.
Is it possible to inject it somehow when using cycle: in a word definition, so it won't "leak" outside?
Yes, it's possible. You would have to make cycle: immediate. And then also change it to postpone its actions, rather than perform them at runtime.
Postponing means to delay the actions of words. Immediate words are compiled into the current definition, and normal words are arranged to be compiled when the current definition is executing.
In this case it might look something like this.
: (cycle) 4 0 do dup execute loop drop ;
: cycle: ' postpone literal postpone (cycle) ; immediate
Note that this version no longer works outside definitions.

mathematical 'not' of integer

Why delphi perform mathematical 'not' of integer rather than force to cast to boolean value in while do looping ?
Example
var myint:integer;
...
myint:=1;
while not myint=5 do
begin
myint:=myint+1;
showmessage('myint now is : '+inttostr(myint));
end;
Your expression uses two operators: not and =. In order to understand how it is parsed you need to consult the table of operator precedence.
Operators Precedence
----------------------------
# first (highest)
not
----------------------------
* second
/
div
mod
and
shl
shr
as
----------------------------
+ third
-
or
xor
----------------------------
= fourth (lowest)
<>
<
>
<=
>=
in
is
----------------------------
This shows that not has the highest precedence of all operators, and is of higher precedence than =. Which means that your expression is parsed as if it were:
(not myint) = 5
In this expression, because it is bound to an integral variable, not is biwise negation.
In order to get the result that you desire you must use parentheses to indicate that you wish to perform the equality test before the not:
not (myint = 5)
Now, in this expression, (myint = 5) is a logical expression and so the not operator is now logical negation.
The answer to a question of this nature is always found in the table of operator precedence and it will pay dividends to become familiar with this table. This table will tell you how any expression that omits parentheses is parsed.
Finally as Rudy points out, your specific expression is most cleanly written using the <> operator:
myint <> 5
The reason why delphi is doing this is that the not operator has a higher order than the equal comparison operator. It is an unary operator which is calculated first. In fact, is has to be calculated first before the = operator comes into action (which -of course- has the lowest order).
To force delphi calculating what you want, use parenthes:
if not (myint = 5) then....
// vs
if (not myint) = 5 then
// vs
if not myint = 5 then
As you know by now the latter two are equivalent.
BTW: Something similar (order precedence) happens with calculations like 3+4*5. Here, the multiplication is carried out before the addition because the * operator has a higher order compared to the + operator.

Type "inheritance" in xtext

As part of a course in my university, I have to build a simple DSL using XText. Currently I am having a problem with static type checking. Lets suppose I have two types of variables in my language, circle and triangle.
Both have their own set of parameters like e.g. radius or height/width. However, both do have common parameters like x/y (position). Therefore, I have to following xtext code:
//CircleAttributesInit makes sure, that the correct parameter are used
CircleDecl:
'circle' name = ID '(' (attributes += CircleAttributesInit)* ')'
;
//triangleAttributesInit makes sure, that the correct parameter are used
TriangleDecl:
'triangle' name = ID '(' (attributes += triangleAttributesInit)* ')'
;
CircleAccess returns INT:
circle = [CircleDecl] '.' ('radius')
;
TriangleAccess returns INT:
triangle = [TriangleDecl] '.' ('height' | 'width')
;
ObjectDecl:
name = (CircleDecl | TriangleDecl)
;
ObjectAccess returns INT:
objName = [ObjectDecl] '.' ('x' | 'y')
;
In my simple program, I can now type something like:
triangle tri (...)
circle c (...)
tri.height = ...
c.radius = ...
but access on the super type variables like :
tri.x = ....
c.y =....
does not work. The error message is: "Couldn't resolve reference to ObjectDecl 'tri/c'."
This kind of makes sense to me, since I never told xtext, that each TriangleDecl/CircleDecl object is also a ObjectDecl. But how do I do this?
it looks like you mix up some metalevels. as long as the attributes exist only on syntax level you have to take care yourself

Resources