ANTLR 4 TL Grammar seems incorrect - antlr

I downloaded the TL Grammar from https://raw.githubusercontent.com/bkiers/tiny-language-antlr4/master/src/main/antlr4/tl/antlr4/TL.g4
And after attempting to try it, I realized the grammar is unable to handle user defined function calls at the top-level
For example, if your file contents are:
def s(n)
return n+n;
end
s("5", "6");
And you listen for a FunctionCallExpression, you don't get a callback. However, if your file contents are:
def s(n)
return n+n;
end
s(s("5"))
you do get the call back.

Your input:
s("5", "6");
is matched by the statement (not an expression!):
functionCall
: Identifier '(' exprList? ')' #identifierFunctionCall
| ...
;
and "5", "6" are two expressions matched by exprList.
The first s in your input s(s("5")) will again match identifierFunctionCall, and the inner s will be matched as an expression (a functionCallExpression to be precise).
Here are the different parse trees:
s("5", "6");
'- parse
|- block
| '- statement
| |- identifierFunctionCall
| | |- s
| | |- (
| | |- exprList
| | | |- stringExpression
| | | | '- "5"
| | | |- ,
| | | '- stringExpression
| | | '- "6"
| | '- )
| '- ;
'- <EOF>
s(s("5"));
'- parse
|- block
| '- statement
| |- identifierFunctionCall
| | |- s
| | |- (
| | |- exprList
| | | '- functionCallExpression
| | | '- identifierFunctionCall
| | | |- s
| | | |- (
| | | |- exprList
| | | | '- stringExpression
| | | | '- "5"
| | | '- )
| | '- )
| '- ;
'- <EOF>
In short: the grammar works as it is supposed to.
EDIT
A valid TL script is a code block where each code block consists of statements. To simplify the grammar and eliminate some ambiguous rules (which was needed for the older ANTLRv3), it was easiest to not allow a statement to be a simple expression. For example, the following code is not a valid TL script:
1 + 2;
I.e. 1 + 2 is not a statement, but an expression.
However a function call might be a statement, but, when placed at the right hand side of an assignment statement, it could also be an expression:
foo(); // this is a statement
i = foo(); // now foo is an expression
That is why you observed one s(...) to trigger a certain enter...() method, while the other did not.

Related

Update of value in array of jsonb returns error"invalid input syntax for type json"

I have a column of type jsonb which contains json arrays of the form
[
{
"Id": 62497,
"Text": "BlaBla"
}
]
I'd like to update the Id to the value of a column word_id (type uuid) from a different table word.
I tried this
update inflection_copy
SET inflectionlinks = s.json_array
FROM (
SELECT jsonb_agg(
CASE
WHEN elems->>'Id' = (
SELECT word_copy.id::text
from word_copy
where word_copy.id::text = elems->>'Id'
) THEN jsonb_set(
elems,
'{Id}'::text [],
(
SELECT jsonb(word_copy.word_id::text)
from word_copy
where word_copy.id::text = elems->>'Id'
)
)
ELSE elems
END
) as json_array
FROM inflection_copy,
jsonb_array_elements(inflectionlinks) elems
) s;
Until now I always get the following error:
invalid input syntax for type json
DETAIL: Token "c66a4353" is invalid.
CONTEXT: JSON data, line 1: c66a4353...
The c66a4535 is part of one of the uuids of the word table. I don't understand why this is marked as invalid input.
EDIT:
To give an example of one of the uuids:
select to_jsonb(word_id::text) from word_copy limit(5);
returns
+----------------------------------------+
| to_jsonb |
|----------------------------------------|
| "078c979d-e479-4fce-b27c-d14087f467c2" |
| "ef288256-1599-4f0f-a932-aad85d666c9a" |
| "d1d95b60-623e-47cf-b770-de46b01042c5" |
| "f97464c6-b872-4be8-9d9d-83c0102fb26a" |
| "9bb19719-e014-4286-a2d1-4c0cf7f089fc" |
+----------------------------------------+
As requested the respective columns id and word_id from the word table:
+---------------------------------------------------+
| row |
|---------------------------------------------------|
| ('27733', '078c979d-e479-4fce-b27c-d14087f467c2') |
| ('72337', 'ef288256-1599-4f0f-a932-aad85d666c9a') |
| ('72340', 'd1d95b60-623e-47cf-b770-de46b01042c5') |
| ('27741', 'f97464c6-b872-4be8-9d9d-83c0102fb26a') |
| ('72338', '9bb19719-e014-4286-a2d1-4c0cf7f089fc') |
+---------------------------------------------------+
+----------------+----------+----------------------------+
| Column | Type | Modifiers |
|----------------+----------+----------------------------|
| id | bigint | |
| value | text | |
| homonymnumber | smallint | |
| pronounciation | text | |
| audio | text | |
| level | integer | |
| alpha | bigint | |
| frequency | bigint | |
| hanja | text | |
| typeeng | text | |
| typekr | text | |
| word_id | uuid | default gen_random_uuid() |
+----------------+----------+----------------------------+
I would suggest you to modify your sub query as follow :
update inflection_copy AS ic
SET inflectionlinks = s.json_array
FROM
(SELECT jsonb_agg(CASE WHEN wc.word_id IS NULL THEN e.elems ELSE jsonb_set(e.elems, array['Id'], to_jsonb(wc.word_id::text)) END ORDER BY e.id ASC) AS json_array
FROM inflection_copy AS ic
CROSS JOIN LATERAL jsonb_path_query(ic.inflectionlinks, '$[*]') WITH ORDINALITY AS e(elems, id)
LEFT JOIN word_copy AS wc
ON wc.id::text = e.elems->>'Id'
) AS s
The LEFT JOIN clause will return wc.word_id = NULL when there is no wc.id which corresponds to e.elems->>'id', so that e.elems is unchanged in the CASE.
The ORDER BY clause in the aggregate function jsonb_agg will ensure that the order is unchanged in the jsonb array.
jsonb_path_query is used instead of jsonb_array_elements so that to not raise an error when ic.inflectionlinks is not a jsonb array and it is used in lax mode (which is the default behavior).
see the test result in dbfiddle

Adding space at the end of a line in Gherkin

My question is:
I have a datatable with some values. and i want to the end of one of the values to have a whitespace.
eg.
| Name | Surname | Statement |
| AO | PO | This is a statement |
i want to add a whitespace after the word statement. How can i do that?
Depending on your stepdefinitions (using {string}, {word} or the ^...$ notation) you can do
| Name | Surname | Statement |
| AO | PO | "This is a statement " |
Or use the whitespace character
| Name | Surname | Statement |
| AO | PO | This is a statement\s |

XML default namespace and prefixed attributes

I stumbled over some odd behaviour in connection with prefixed attributes. I know - in general - that in most cases prefixed attributes are not used, as they belong to an element which is in a namespace already. But shortly I tried to answer a question and found something I could not understand, even after some research:
DECLARE #xml XML=
N'<test:root xmlns:test="SomeURL">
<test:SomeElement test:SomeAttribute="yeah!" />
</test:root>';
I can wildcard the namespace:
SELECT #xml.value(N'(/*:root/*:SomeElement/#*:SomeAttribute)[1]',N'nvarchar(max)');
I can give an alias to the namespace:
WITH XMLNAMESPACES('SomeURL' AS ns)
SELECT #xml.value(N'(/ns:root/ns:SomeElement/#ns:SomeAttribute)[1]',N'nvarchar(max)');
I thought - as there is only one namespace - I could use it as default:
WITH XMLNAMESPACES(DEFAULT 'SomeURL')
SELECT #xml.value(N'(/root/SomeElement/#SomeAttribute)[1]',N'nvarchar(max)'); --fails!
If I use the same as above but set a wildcard to the attribute it works:
WITH XMLNAMESPACES(DEFAULT 'SomeURL')
SELECT #xml.value(N'(/root/SomeElement/#*:SomeAttribute)[1]',N'nvarchar(max)');
When I use old fashioned FROM OPENXML I see, that the attribute is a member of test / SomeURL namespace, just as all elements:
DECLARE #hdoc INT;
EXEC sp_xml_preparedocument #hdoc OUTPUT, #xml;
SELECT * FROM OPENXML (#hdoc, '//*',3);
EXEC sp_xml_removedocument #hdoc;
The result:
+----+----------+----------+---------------+--------+--------------+----------+------+---------+
| id | parentid | nodetype | localname | prefix | namespaceuri | datatype | prev | text |
+----+----------+----------+---------------+--------+--------------+----------+------+---------+
| 0 | NULL | 1 | root | test | SomeURL | NULL | NULL | NULL |
+----+----------+----------+---------------+--------+--------------+----------+------+---------+
| 2 | 0 | 2 | test | xmlns | NULL | NULL | NULL | NULL |
+----+----------+----------+---------------+--------+--------------+----------+------+---------+
| 5 | 2 | 3 | #text | NULL | NULL | NULL | NULL | SomeURL |
+----+----------+----------+---------------+--------+--------------+----------+------+---------+
| 3 | 0 | 1 | SomeElement | test | SomeURL | NULL | NULL | NULL |
+----+----------+----------+---------------+--------+--------------+----------+------+---------+
| 4 | 3 | 2 | SomeAttribute | test | SomeURL | NULL | NULL | NULL |
+----+----------+----------+---------------+--------+--------------+----------+------+---------+
| 6 | 4 | 3 | #text | NULL | NULL | NULL | NULL | yeah! |
+----+----------+----------+---------------+--------+--------------+----------+------+---------+
This is a tiny issue, as it is easy to find a work around, but I'm curious...
Any light on this?
In XPath, as in XML, the default namespace does not apply to attributes. An element name written without a prefix assumes the default namespace, while an attribute name written without a prefix assumes "no namespace".

PostgreSQL: restoring table from sql using psql return 'ERROR: invalid input syntax for integer'

I trying to restore sql dump that looks like this:
COPY table_name (id, oauth_id, foo, bar) FROM stdin;
1 142 \N xxxxxxx
2 142 \N yyyyyyy
<dozen similar lines>
last line in this dump: \.
command to restore:
psql < table.sql
or
psql --file=dump.sql
\d+ table_name:
Table "public.table_name"
Column | Type | Modifiers | Storage | Stats target | Description
---------------------+-----------------------+-------------------------------------------------------------------------+----------+--------------+-------------
id | integer | not null default nextval('connected_table_name_id_seq'::regclass) | plain | |
oauth_id | integer | not null | plain | |
foo | character varying | | extended | |
bar | character varying | | extended | |
Looks sadly that standard method for backup and rollback does not work :(
Version of the psql: 9.5.4, version of the server: 9.5.2

How to create a decision table using Seleium/Xebium scenario in Fitnesse

I have create a couple of Scenarios in fitnesse using Xebium/Selenium. They works nice but I'd like to create a decision table from one of my scenario.
So I try with the following:
| Verifiera ärendet | selenium driver fixture |
| tabellRadsNr | längd | bredd | grisar | höns | getter | får | kod | felbeskrivning |
| 19 | 50 | 20 | 201 | 0 | 0 | 0 | R110 | Nekad |
And ends up with:
Could not invoke constructor for VerifieraÄrendet[1]
The instance decisionTable_25. does not exist
The scenario "Verifiera ärendet" works when I run it by itself so I guess that I am missing something....
The problem was that I mixed up parameter names and their value names. So the structure basically is
| scenarioname parametername2 |
| parametervaluename1 | parametervaluename2 |
| row1value1 | row1value2 |
| row2value1 | row2value2 |