Referencing Multiple Non-Terminals in Production with Same Name in Yacc - ml-yacc

Let's assume I have the production:
Expression // These are my semantic actions
: Expression PLUS_TOKEN Expression ( create_node(Expression, Expression) )
| SimpleExpression ( SimpleExpression ) (* Returns a node of type expression *)
Notice how I can't tell which Expression is which in my top most production's semantic action. How do I refer to the left and right Expression? What if I have three or more 'Expression's appear in the same production?

Reference: http://www.smlnj.org/doc/ML-Yacc/mlyacc002.html
According to ML-Yacc documentation we refer to non-terminals with the following notation:
{non-terminal}{n+1}
such that n is the number of occurrences of the non-terminal to the left of the symbol. If n equals one then we can just use the non-terminal name.
Hence, the above example would look like this:
Expression // These are my semantic actions
: Expression PLUS_TOKEN Expression ( create_node(Expression1, Expression2) )
| SimpleExpression ( SimpleExpression ) (* Returns a node of type expression *)

Related

What is PostgreSQL syntax for complex array literals? (e.g. circle[])

The PostgreSQL docs state that, though some literals have special syntax, generic syntax for literal values looks like type 'data', 'data'::type, or CAST('data' AS type). For instance, one could write the integer 16 as 16 or as '16'::int. Dollar-quoting is also allowed, so $$16$$:int works as well.
For some types, such as circle, the generic syntax is (as far as I can tell) the only way to write a literal. Four syntaxes are listed for circle: <(x, y), r>, ((x, y), r), (x, y), r, and x, y, r; however, none of these seem to work plain:
y=> create table t (c circle);
CREATE TABLE
y=> insert into t (c) values ( <(1,2),3> );
ERROR: syntax error at or near "<"
LINE 1: insert into t (c) values ( <(1,2),3> );
^
y=> insert into t (c) values ( ((1,2),3) );
ERROR: column "c" is of type circle but expression is of type record
LINE 1: insert into t (c) values ( ((1,2),3) );
^
HINT: You will need to rewrite or cast the expression.
y=> insert into t (c) values ( (1,2),3 );
ERROR: INSERT has more expressions than target columns
LINE 1: insert into t (c) values ( (1,2),3 );
^
y=> insert into t (c) values ( 1,2,3 );
ERROR: INSERT has more expressions than target columns
LINE 1: insert into t (c) values ( 1,2,3 );
^
On the contrary, using the generic syntax works fine:
y=> insert into t (c) values ( '1,2,3' );
INSERT 0 1
y=> select c from t;
c
-----------
<(1,2),3>
Also documented is the array syntax, which is comma-delimited and curly-enclosed. So the range 1-5 may be written, for instance, as '{1, 2, 3, 4, 5}'::int[].
Unfortunately, the array syntax does not seem to support values specified with the generic syntax: $${ 1 }$$::int[] is accepted, but $${ '1'::int }::int[] is rejected, as is $${ '1' }::int[].
Because array literal syntax does not accept generic-form syntax for elements, and because generic syntax seems to be the only way to write a circle literal, it appears that it is impossible to write a circle literal in PostgreSQL.
y=> select $${ }$$::circle[];
circle
--------
{}
(1 row)
y=> select $${ '<(1, 2), 3>'::circle }$$::circle[];
ERROR: invalid input syntax for type circle: "'<(1"
LINE 1: select $${ '<(1, 2), 3>'::circle }$$::circle[];
Is this indeed the case?
Note: yes, it's crucial that I want to write a circle[] literal. The reason is that my use-case is for specifying values in prepared statements in a PostgreSQL client, and, as the PostgreSQL protocol documentation says (emphasis mine):
Parameter data types can be specified by OID; if not given, the parser attempts to infer the data types in the same way as it would do for untyped literal string constants.
This means that, for instance, ARRAY[ '<(1,2),3>'::circle ] is not a valid solution, as it does not use literal syntax.
Turns out the solution is simple: escape the commas!
y=> select '{ <(1\,2)\,3>, <(4\,5)\,6> }'::circle[];
circle
---------------------------
{"<(1,2),3>","<(4,5),6>"}
(1 row)
Also an option is to double-quote the elements:
y=> select '{ "<(1,2),3>", "<(4,5),6>" }'::circle[];
circle
---------------------------
{"<(1,2),3>","<(4,5),6>"}
(1 row)
Credit to sehrope on Github for telling me this. Quote from the relevant part of the PostgreSQL docs:
[...] when writing an array value you can use double quotes around any individual array element. You must do so if the element value would otherwise confuse the array-value parser. For example, elements containing curly braces, commas [...], double quotes, backslashes, [etc,] must be double-quoted. [...] Alternatively, you can avoid quotes and use backslash-escaping to protect all data characters that would otherwise be taken as array syntax.

No operator matches the given name and argument type(s): What needs to be cast?

I'm getting an error, and I cannot figure out why. I know the error is telling me to cast a type but I'm not sure on what?
What part of CASE is the operator?
ERROR: operator does not exist: character varying = boolean
LINE 6: WHEN lower(foo.name) SIMILAR TO '%(foo
^
HINT: No operator matches the given name and argument type(s). You might need to add explicit type casts.
My query:
SELECT foo.name,
bar.city,
MAX(foo.total - bar.tax_amount),
CASE bar.name
WHEN lower(foo.name) SIMILAR TO '%(foo|bar|baz)%' THEN true
ELSE false
END
....
GROUP BY foo.name, bar.city;
I believe you simply want:
SELECT foo.name,
bar.city,
MAX(foo.total - bar.tax_amount),
(CASE WHEN lower(foo.name) SIMILAR TO '%(foo|bar|baz)%' THEN true
ELSE false
END)
....
GROUP BY foo.name, bar.city;
The CASE expression has two forms. One searches for values for a given expression. This takes a column or expression right after the CASE. The second searches through various expressions, stopping at the first one. This takes the WHEN clause right after the CASE.
Or even more simply:
SELECT foo.name, bar.city,
MAX(foo.total - bar.tax_amount),
(lower(foo.name) SIMILAR TO '%(foo|bar|baz)%')
....
GROUP BY foo.name, bar.city;
The CASE is not needed.
Your CASE expression had a syntax error, like #a_horse commented.
But you don't even need CASE at all in this particular case for a boolean result. Just:
foo.name ~* '(foo|bar|baz)'
That's all.
~* being the case-insensitive regular expression match operator.
Never use SIMILAR TO:
Difference between LIKE and ~ in Postgres

SAS nested select MAX statement

I am using the below but am receiving an error shown below. The part of the code that is throwing the error is MAX(EX_DT) EXPIRATION_DT and it underlines EXPIRATION_DT.
Thoughts?
22
ERROR 22-322: Syntax error, expecting one of the following: !, !!, &, *, **, +, ',', -, /, <, <=, <>, =, >, >=, ?, AND, AS,
CONTAINS, EQ, EQT, GE, GET, GT, GTT, LE, LET, LIKE, LT, LTT, NE, NET, OR, ^=, |, ||, ~=.
LEFT OUTER JOIN
(select LN_NO,
MAX(EX_DT) EXPIRATION_DT
FROM R1.SAMPLE_TABLE
GROUP BY LN_NO,
EXPIRATION_DT) T1
ON T1.NUM = TL.NUM
MAX(EX_DT) EXPIRATION_DT
need to change to
MAX(EX_DT) AS EXPIRATION_DT
You need to use the AS keyword if you want to give a new name to the value you are selecting. Otherwise SAS is expecting that second token to be the LABEL that you want to attach to the variable.
So the syntax is
expression string_literal
or
expression as varname
To specify both you can use
expression as varname string_literal
But you can use keywords to set the LABEL and other attributes like LENGTH, FORMAT, INFORMAT.
catx(', ',lastname,firstname) as fullname label='Person Name' length=40

Why Postgres array takes place after comparision operator while comparing?

Here i got noticed that in Postgres string array comparisons we should give array after comparison operator.
For Example:
SELECT campaign_products
FROM contacts
WHERE 'PMP' LIKE ANY(campaign_products) limit 10;
SELECT campaign_products
FROM contacts
WHERE 'as' = ANY(campaign_products);
But when i use like below it giving a syntax error:
SELECT campaign_products
from contacts
where ANY(campaign_products) = 'as';
ERROR: syntax error at or near "ANY"
LINE 1: SELECT campaign_products from contacts where ANY(campaign_pr...
Can some one explain me this and let me know if there is any way to give array left to comparison operator.
It's the SQL standard.
In ISO/IEC 9075-2 (2003), Foundation, it is defined as follows:
8.8 <quantified comparison predicate>
Format
<quantified comparison predicate> ::=
<row value predicand> <quantified comparison predicate part 2>
<quantified comparison predicate part 2> ::=
<comp op> <quantifier> <table subquery>
<quantifier> ::=
<all>
| <some>
<all> ::= ALL
<some> ::=
SOME
| ANY
So it's a question you'd have to take up with the SQL standard.
But seriously, why do you need ANY =? It should not be a problem to switch the sides so that the comparison is syntactically correct.
Think of = ANY or = SOME as operators where the left side is a value and the right side is a collection of values. PostgreSQL extends the SQL standard syntax by allowing arrays on the right hand side.

Pattern matching with identical wildcards

I'm working with PostgreSQL and want to know whether you can have a wildcard retain its value.
So for example say I had
select * from tableOne where field like ‘_DEF_’;
Is there a way to get the first and last wildcard to be the exact same character?
So an example matching result could be: ADEFA or ZDEFZ.
You can use a regular expression with a back-reference:
select *
from some_table
where some_column ~* '^(.)DEF(\1)$'
^(.)DEF(\1)$ means: some character at the beginning followed DEF followed by the first character must occur at the end of the string.
The () defines a group and the \1 references the first group (which is the first character in the input sequence in this example)
SQLFiddle example: http://sqlfiddle.com/#!15/d4c4d/1
Use regular expression:
with test as (
select 'xABa' as foo
union select 'xABx'
union select 'xJBx'
)
select * from test
where foo ~* E'^(.)AB\\1$'
Outputs:
foo
------
xABx
(1 row)