Grammar where braces have lower precedence - grammar

I have the following grammar. I want to somehow convert this into a grammar where '()' has lower precedence than '-' and '/'
E -> E - E | T
T -> T / T | F
F -> id | ( E )
I have been trying to do this for a while now, it would be great if somebody could help.
Thanks in advance.

Related

How can I query for blank columns? [duplicate]

What is best way to check if value is null or empty string in Postgres sql statements?
Value can be long expression so it is preferable that it is written only once in check.
Currently I'm using:
coalesce( trim(stringexpression),'')=''
But it looks a bit ugly.
stringexpression may be char(n) column or expression containing char(n) columns with trailing spaces.
What is best way?
The expression stringexpression = '' yields:
TRUE   .. for '' (or for any string consisting of only spaces with the data type char(n))
NULL   .. for NULL
FALSE .. for anything else
So to check for: "stringexpression is either NULL or empty":
(stringexpression = '') IS NOT FALSE
Or the reverse approach (may be easier to read):
(stringexpression <> '') IS NOT TRUE
Works for any character type including char(n). The manual about comparison operators.
Or use your original expression without trim(), which is costly noise for char(n) (see below), or incorrect for other character types: strings consisting of only spaces would pass as empty string.
coalesce(stringexpression, '') = ''
But the expressions at the top are faster.
Asserting the opposite is even simpler: "stringexpression is neither NULL nor empty":
stringexpression <> ''
About char(n)
This is about the data type char(n), short for: character(n). (char / character are short for char(1) / character(1).) Its use is discouraged in Postgres:
In most situations text or character varying should be used instead.
Do not confuse char(n) with other, useful, character types varchar(n), varchar, text or "char" (with double-quotes).
In char(n) an empty string is not different from any other string consisting of only spaces. All of these are folded to n spaces in char(n) per definition of the type. It follows logically that the above expressions work for char(n) as well - just as much as these (which wouldn't work for other character types):
coalesce(stringexpression, ' ') = ' '
coalesce(stringexpression, '') = ' '
Demo
Empty string equals any string of spaces when cast to char(n):
SELECT ''::char(5) = ''::char(5) AS eq1
, ''::char(5) = ' '::char(5) AS eq2
, ''::char(5) = ' '::char(5) AS eq3;
Result:
eq1 | eq2 | eq3
----+-----+----
t | t | t
Test for "null or empty string" with char(n):
SELECT stringexpression
, stringexpression = '' AS base_test
, (stringexpression = '') IS NOT FALSE AS test1
, (stringexpression <> '') IS NOT TRUE AS test2
, coalesce(stringexpression, '') = '' AS coalesce1
, coalesce(stringexpression, ' ') = ' ' AS coalesce2
, coalesce(stringexpression, '') = ' ' AS coalesce3
FROM (
VALUES
('foo'::char(5))
, ('')
, (' ') -- not different from '' in char(n)
, (NULL)
) sub(stringexpression);
Result:
stringexpression | base_test | test1 | test2 | coalesce1 | coalesce2 | coalesce3
------------------+-----------+-------+-------+-----------+-----------+-----------
foo | f | f | f | f | f | f
| t | t | t | t | t | t
| t | t | t | t | t | t
null | null | t | t | t | t | t
Test for "null or empty string" with text:
SELECT stringexpression
, stringexpression = '' AS base_test
, (stringexpression = '') IS NOT FALSE AS test1
, (stringexpression <> '') IS NOT TRUE AS test2
, coalesce(stringexpression, '') = '' AS coalesce1
, coalesce(stringexpression, ' ') = ' ' AS coalesce2
, coalesce(stringexpression, '') = ' ' AS coalesce3
FROM (
VALUES
('foo'::text)
, ('')
, (' ') -- different from '' in a sane character types
, (NULL)
) sub(stringexpression);
Result:
stringexpression | base_test | test1 | test2 | coalesce1 | coalesce2 | coalesce3
------------------+-----------+-------+-------+-----------+-----------+-----------
foo | f | f | f | f | f | f
| t | t | t | t | f | f
| f | f | f | f | f | f
null | null | t | t | t | t | f
db<>fiddle here
Old sqlfiddle
Related:
Any downsides of using data type "text" for storing strings?
To check for null and empty:
coalesce(string, '') = ''
To check for null, empty and spaces (trim the string)
coalesce(TRIM(string), '') = ''
Checking for the length of the string also works and is compact:
where length(stringexpression) > 0;
A lot of the answers are the shortest way, not the necessarily the best way if the column has lots of nulls. Breaking the checks up allows the optimizer to evaluate the check faster as it doesn't have to do work on the other condition.
(stringexpression IS NOT NULL AND trim(stringexpression) != '')
The string comparison doesn't need to be evaluated since the first condition is false.
another way is
nullif(trim(stringExpression),'') is not null
If there may be empty trailing spaces, probably there isn't better solution. COALESCE is just for problems like yours.
Something that I saw people using is stringexpression > ''. This may be not the fastest one, but happens to be one of the shortest.
Tried it on MS SQL as well as on PostgreSQL.
In ran into a kind of similar case, were I had to do this . My Table definition look like :
id(bigint)|name (character varying)|results(character varying)
1 | "Peters"| [{"jk1":"jv1"},{"jk1":"jv2"}]
2 | "Russel"| null
To filter out the results column with null or empty in it , what worked was :
SELECT * FROM tablename where results NOT IN ('null','{}');
This returned all rows which are not null on results.
I'm not sure how to fix this query to return the same all rows which are not null on results.
SELECT * FROM tablename where results is not null;
--- hmm what am I missing,casting ? any inputs?
found this post looking for a solution to 'don't show me data that is '' (blank or single space char) or null'. in my case, we only want to show the user records with these values populated. i hope this response helps another looking for the same. the answers above didn't work in my case.
our app is running rails with postgres. looking at how rails builds the query for .where.not(company_website: [nil, '']) in our app, which works just fine, i can see the resulting sql statement in console.
WHERE NOT ((contacts.company_website = '' OR contacts.company_website IS NULL))
i added this bit and it works as intended.
I like answer by yglodt, but calculating exact length may be expensive for big sets and big strings, so I go with:
coalesce(trim('a') > '','f')
My preffered way to compare nullable fields is:
NULLIF(nullablefield, :ParameterValue) IS NULL AND NULLIF(:ParameterValue, nullablefield) IS NULL . This is cumbersome but is of universal use while Coalesce is impossible in some cases.
The second and inverse use of NULLIF is because "NULLIF(nullablefield, :ParameterValue) IS NULL" will always return "true" if the first parameter is null.
If database having large number of records then null check can take more time
you can use null check in different ways like :
1) where columnname is null
2) where not exists()
3) WHERE (case when columnname is null then true end)

ANTLR4 Grammar mathematical operator associativity and order of operations

I am attempting to create an ANTLR4 grammar to carry out mathematical operations. However, I'm finding some difficulty balancing the order of operations alongside operator associativity. (e.g. x+y+z is right-associative should be understood as x+(y+z) and subtraction is left associative, so x-y-z should be understood as (x-y)-z ).
This example defines the operations with correct associativity.
expr
: value = INTEGER #Integer
| value = VARIABLE #Variable
| <assoc=right> left = expression op = '^' right = expression #Operation
| <assoc=left> left = expression op = '/' right = expression #Operation
| <assoc=right> left = expression op = '*' right = expression #Operation
| <assoc=right> left = expression op = '+' right = expression #Operation
| <assoc=left> left = expression op = '-' right = expression #Operation
However, the order of operations dictates that multiplication and division are evaluated with equal precedence, from left to right. The same goes for multiplication and subtraction.
This example maintains the order of operations, but denies the ability to add the associativity.
expr
: value = INTEGER #Integer
| value = VARIABLE #Variable
| <assoc=right> left = expression op = OP_POW right = expression #Operation
| left = expression op = ('/' | '*') right = expression #Operation
| left = expression op = ('+' | '-') right = expression #Operation
Any attempts I've made to fix this end up using left-recursive rules. Is there a way to maintain operator associativity AND the correct order of operations using ANTLR4? Any help is appreciated. Thanks in advance.

format string with comma

I am getting a string output as : A B C D
I want to get it converted to: A,B,C and D.
Is there and function in PostgreSQL to do it.
Try this:
select REPLACE('A B C D', ' ', ',')
And to replace A,B,C,D to A,B,C and D use the following:
select substring('A,B,C,D',1,
length('A,B,C,D')-position(',' in reverse('A,B,C,D')))
|| ' and ' ||
substring('A,B,C,D',length('A,B,C,D')-position(',' in reverse('A,B,C,D'))+2);
You can combine the above with replace to make it single query.
I would use a two-step approach. The first step replaces all spaces with a comma. And then the last comma is replaced with the AND using a regular expression:
regexp_replace(replace('A B C D',' ',','), '(.*)(,)(\w+)$', '\1 and \3')
Online example
No need to complicate things.
A single regex function that capture each element and lets you do whatever you want with it.
select regexp_replace(mycol, '(\S)+\s+(\S+)\s+(\S)\s+(\S+)','\1,\2,\3 and \4')
from mytab
-
+----------------+
| regexp_replace |
+----------------+
| A,B,C and D |
+----------------+
SQL Fiddle

ANTLR is taking the wrong branch

I have this very simple grammar:
grammar LispExp;
expression : LITERAL #LiteralExp
| '(' '-' expression ')' #UnaryMinusExp
| '(' OP expression expression ')' #OpExp
| '(' 'if' expression expression expression ')' #IfExp;
OP : '+' | '-' | '*' | '/' | '==' | '<';
LITERAL : '0'|('1'..'9')('0'..'9')*;
WS : ('\t' | '\n' | '\r' | ' ') -> skip;
It should be able to parse a "lisp-like" expression, but when I try to parse this:
(+ (+ 5 (* 7 (/ 5 (- 2 (- 9) ) ) ) ) 8)
ANTLR fails to recognize the last unary minus, and generates the following (with antlr v4) :
(expression ( + (expression ( + (expression 5) (expression ( * (expression 7) (expression ( / (expression 5) (expression ( - (expression 2))) ( -) 9 )) expression ))
So, how can I make ANTLR understand the priority of unary minus over binary expression?
You are using a combined grammar LispExp, as opposed to separate lexer grammar LispExpLexer and parser grammar LispExpParser. When working with combined grammars, if you use a string literal in a parser rule the code generator will create anonymous tokens according to those string literals, and silently override the lexer.
In this case, your expression rule includes the string literal '-'. All instances of - in your input will be assigned this token type, which means they will not ever have the token type OP. Your input contains a subexpression (- 2 (- 9) ) which can only be parsed if the first - is an OP token, so according to the parser you have a syntax error in your input.
If you update your code to use separate lexer and parser grammars, any attempt to use a string literal in the parser grammar which is not defined in the lexer grammar will produce an error when you attempt to generate your lexer and parser.

Best way to check for "empty or null value"

What is best way to check if value is null or empty string in Postgres sql statements?
Value can be long expression so it is preferable that it is written only once in check.
Currently I'm using:
coalesce( trim(stringexpression),'')=''
But it looks a bit ugly.
stringexpression may be char(n) column or expression containing char(n) columns with trailing spaces.
What is best way?
The expression stringexpression = '' yields:
TRUE   .. for '' (or for any string consisting of only spaces with the data type char(n))
NULL   .. for NULL
FALSE .. for anything else
So to check for: "stringexpression is either NULL or empty":
(stringexpression = '') IS NOT FALSE
Or the reverse approach (may be easier to read):
(stringexpression <> '') IS NOT TRUE
Works for any character type including char(n). The manual about comparison operators.
Or use your original expression without trim(), which is costly noise for char(n) (see below), or incorrect for other character types: strings consisting of only spaces would pass as empty string.
coalesce(stringexpression, '') = ''
But the expressions at the top are faster.
Asserting the opposite is even simpler: "stringexpression is neither NULL nor empty":
stringexpression <> ''
About char(n)
This is about the data type char(n), short for: character(n). (char / character are short for char(1) / character(1).) Its use is discouraged in Postgres:
In most situations text or character varying should be used instead.
Do not confuse char(n) with other, useful, character types varchar(n), varchar, text or "char" (with double-quotes).
In char(n) an empty string is not different from any other string consisting of only spaces. All of these are folded to n spaces in char(n) per definition of the type. It follows logically that the above expressions work for char(n) as well - just as much as these (which wouldn't work for other character types):
coalesce(stringexpression, ' ') = ' '
coalesce(stringexpression, '') = ' '
Demo
Empty string equals any string of spaces when cast to char(n):
SELECT ''::char(5) = ''::char(5) AS eq1
, ''::char(5) = ' '::char(5) AS eq2
, ''::char(5) = ' '::char(5) AS eq3;
Result:
eq1 | eq2 | eq3
----+-----+----
t | t | t
Test for "null or empty string" with char(n):
SELECT stringexpression
, stringexpression = '' AS base_test
, (stringexpression = '') IS NOT FALSE AS test1
, (stringexpression <> '') IS NOT TRUE AS test2
, coalesce(stringexpression, '') = '' AS coalesce1
, coalesce(stringexpression, ' ') = ' ' AS coalesce2
, coalesce(stringexpression, '') = ' ' AS coalesce3
FROM (
VALUES
('foo'::char(5))
, ('')
, (' ') -- not different from '' in char(n)
, (NULL)
) sub(stringexpression);
Result:
stringexpression | base_test | test1 | test2 | coalesce1 | coalesce2 | coalesce3
------------------+-----------+-------+-------+-----------+-----------+-----------
foo | f | f | f | f | f | f
| t | t | t | t | t | t
| t | t | t | t | t | t
null | null | t | t | t | t | t
Test for "null or empty string" with text:
SELECT stringexpression
, stringexpression = '' AS base_test
, (stringexpression = '') IS NOT FALSE AS test1
, (stringexpression <> '') IS NOT TRUE AS test2
, coalesce(stringexpression, '') = '' AS coalesce1
, coalesce(stringexpression, ' ') = ' ' AS coalesce2
, coalesce(stringexpression, '') = ' ' AS coalesce3
FROM (
VALUES
('foo'::text)
, ('')
, (' ') -- different from '' in a sane character types
, (NULL)
) sub(stringexpression);
Result:
stringexpression | base_test | test1 | test2 | coalesce1 | coalesce2 | coalesce3
------------------+-----------+-------+-------+-----------+-----------+-----------
foo | f | f | f | f | f | f
| t | t | t | t | f | f
| f | f | f | f | f | f
null | null | t | t | t | t | f
db<>fiddle here
Old sqlfiddle
Related:
Any downsides of using data type "text" for storing strings?
To check for null and empty:
coalesce(string, '') = ''
To check for null, empty and spaces (trim the string)
coalesce(TRIM(string), '') = ''
Checking for the length of the string also works and is compact:
where length(stringexpression) > 0;
A lot of the answers are the shortest way, not the necessarily the best way if the column has lots of nulls. Breaking the checks up allows the optimizer to evaluate the check faster as it doesn't have to do work on the other condition.
(stringexpression IS NOT NULL AND trim(stringexpression) != '')
The string comparison doesn't need to be evaluated since the first condition is false.
another way is
nullif(trim(stringExpression),'') is not null
If there may be empty trailing spaces, probably there isn't better solution. COALESCE is just for problems like yours.
Something that I saw people using is stringexpression > ''. This may be not the fastest one, but happens to be one of the shortest.
Tried it on MS SQL as well as on PostgreSQL.
In ran into a kind of similar case, were I had to do this . My Table definition look like :
id(bigint)|name (character varying)|results(character varying)
1 | "Peters"| [{"jk1":"jv1"},{"jk1":"jv2"}]
2 | "Russel"| null
To filter out the results column with null or empty in it , what worked was :
SELECT * FROM tablename where results NOT IN ('null','{}');
This returned all rows which are not null on results.
I'm not sure how to fix this query to return the same all rows which are not null on results.
SELECT * FROM tablename where results is not null;
--- hmm what am I missing,casting ? any inputs?
found this post looking for a solution to 'don't show me data that is '' (blank or single space char) or null'. in my case, we only want to show the user records with these values populated. i hope this response helps another looking for the same. the answers above didn't work in my case.
our app is running rails with postgres. looking at how rails builds the query for .where.not(company_website: [nil, '']) in our app, which works just fine, i can see the resulting sql statement in console.
WHERE NOT ((contacts.company_website = '' OR contacts.company_website IS NULL))
i added this bit and it works as intended.
I like answer by yglodt, but calculating exact length may be expensive for big sets and big strings, so I go with:
coalesce(trim('a') > '','f')
My preffered way to compare nullable fields is:
NULLIF(nullablefield, :ParameterValue) IS NULL AND NULLIF(:ParameterValue, nullablefield) IS NULL . This is cumbersome but is of universal use while Coalesce is impossible in some cases.
The second and inverse use of NULLIF is because "NULLIF(nullablefield, :ParameterValue) IS NULL" will always return "true" if the first parameter is null.
If database having large number of records then null check can take more time
you can use null check in different ways like :
1) where columnname is null
2) where not exists()
3) WHERE (case when columnname is null then true end)