handing lists of variable names in bison/yacc - c

I'm having trouble figuring out how to write a parser with bison.
In order to insert variables into my symbol table so that I can do some type-checking and other nonsense I need the variable name and type.
I'm particularly focusing on these lines:
%union {tokentype token;
char *type;
sPtr names; //stack pointer
}
<%token definitions>
%token <token> ID ICONST
%type <type> stype type
%type <names> IDlist
vardcl : IDlist ':' type
;
IDlist : IDlist ',' ID
| ID
;
type : ARRAY '[' integer_constant RANGE integer_constant ']' OF stype { $$ = $8 }
| stype { $$ = $1 }
;
stype : INT { $$ = "INT" }
| BOOLEAN { $$ = "BOOLEAN" }
;
If my grammar were like this:
vardcl : ID ':' type
;
I could just do something like:
vardcl : ID ':' type { SymbolTableInsert($1, $3); }
;
But instead my grammar looks like this:
vardcl : IDlist ':' type
;
IDlist : IDlist ',' ID
| ID
;
So I'm trying to put each ID into a data structure (I already use a stack for the symbol table so I figured I may as well use that) but I keep getting incompatibility errors about the type of the $arguments and I'm not sure I'm even pushing everything I need either:
IDlist : IDlist ',' ID { $$ = SCreate(CompareStrings); SPush($$, $3); }
| ID { $$ = SCreate(CompareStrings); SPush($$, $1);
;
I get the error "incompatible type for argument 2 of SPush, expected void * not tokentype". I get the same error when trying to insert things into my symbol table as well.
What's a good way to do this?
Thanks in advance for any help.

On the grammar side, everything looks ok. It looks like your problem is actually a problem with C: check the signature of your SPush function, it seems to be a function whose second argument is a void*, not tokentype (which is the declared type for ID).

Related

Assigning a single value to an array of a composite type by referencing a column name

Do you have any opinion?
CREATE OR REPLACE FUNCTION fnc_test()
RETURNs integer
AS
$$
declare
tb_var dba_reports[];
v_serialno int := 1;
begin
SELECT array_agg(tbl) into tb_var FROM "dba_reports" tbl;
RAISE NOTICE '%', tb_var[v_serialno].report_id;
tb_var[v_serialno].report_id :=99
return 1;
end;
$$
language plpgsql;
ERROR: syntax error at or near "."
LINE 14: tb_var[v_serialno].report_id :=99

Convert json array to character list esql

I have the following json syntax
{
"PRINTER": "P123",
"ID_INPUT": "111046",
"IDCOUNT": 3,
"TIME": "",
"IDLIST": [{ID_IN": "111046"},{"ID_IN": "111047"}, {"ID_IN": "111048"}]
}
My goal is to iterate over IDLIST and create a character string like "111046;111047;111048" in esql. But I have problems on processing the json. I tried:
DECLARE c INTEGER; -- cardinality
DECLARE i INTEGER 0; -- index
DECLARE idlist CHARACTER '';
-- find cardinality
SET c = CARDINALITY(InputRoot.JSON.Data.IDLIST[]); -- Q1
-- iterate over IDLIST
WHILE i < c DO
-- build new data structure
SET idlist = idlist || InputRoot.JSON.Data.IDLIST[i] || ';'; -- Q2
SET i = i + 1;
END WHILE;
Q1: Is it possible to get the cardinality this way?
Q2: Can I write my data structure like this?
Q3: Is there a better way to do this?
Using cardinality function is not necessary to get the desired string value. Also, cardinality is an expensive(processor intensive) function in IIB esql.
DECLARE idlist CHAR '';
FOR PTR AS InputRoot.JSON.Data.IDLIST.Item[] DO
SET idlist = idlist || PTR.ID_IN || ';' ;
END FOR;
SET idlist = TRIM(TRAILING ';' FROM idlist); --This is to get rid of the last ; in the string

YACC Not getting the values from successor nodes

I'm making a school project and I'm having some trouble.
I have this yacc grammer
FILE : '{' GEOMETRY '}'
;
GEOMETRY : key_type ':' value_point ',' key_coordinates ':' PONTO
;
PONTO : VETOR_MIN2 { printf("%s", $<str>1); }
;
VETOR_MIN2 : '[' numero ',' numero ']'
;
When I make that printf in the non terminal PONTO I only get this: [
but I should get something like this: [20, 10]
What it's missing here? Please help.
Thanks for your time.
The semantic value of a rule is the value that resides in $$ after that rule's actions have been run. If a rule does not have any actions (as is the case for VECTOR_MIN2), the default action is $$ = $1; (unless there is no $1 or the types don't match, in which case there is no default action).
If you want VECTOR_MIN2 to produce a different value, you'll need to add an action and assign a different value to $$.

PL/pgSQL "Malformed array literal" error within for loop

I have the following pl/pgsql function. (Obviously, this is not the full function, it's just the minimal amount of code needed to reproduce the problem)
CREATE OR REPLACE FUNCTION test_func(infos TEXT[][])
RETURNS void AS
$$
DECLARE
info TEXT[];
type TEXT[];
name TEXT;
BEGIN
FOREACH info SLICE 1 IN ARRAY infos LOOP
RAISE NOTICE 'Stuff: %', info;
type := info[1];
name := info[2];
RAISE NOTICE 'Done with stuff';
END LOOP;
RETURN;
END;
$$ LANGUAGE plpgsql;
When I run the function using SELECT test_func('{{something, things},{other, data}}'::TEXT[][]);, I get the following output:
NOTICE: Stuff: {something,things}
ERROR: malformed array literal: "something"
DETAIL: Array value must start with "{" or dimension information.
CONTEXT: PL/pgSQL function test_func(text[]) line 10 at assignment
I don't understand how this error is happening. When the value of info is printed, it shows {something,things}, which seems to me to be a proper array literal.
I am using PostgreSQL version 9.4.7, in case it matters.
The variable type should be text (not text[]):
CREATE OR REPLACE FUNCTION test_func(infos TEXT[][])
RETURNS void AS
$$
DECLARE
info TEXT[];
type TEXT;
name TEXT;
...

compiler design code to parse goto and blocks

Can someone please help me understand how to code lex and yacc file for a C program to parse goto and blocks(labels).
Here is some example I found on the net:
<statement> ::=
<variable> <inc> <semi>
| <variable> <assign> <null> <semi>
| <goto> <label> <semi>
But how to uniquely identify label. Can someone give me an example of this or any link where it is mentioned.
<label> here really means a symbol - an identifier - which must correspond to a label definition somewhere else for the program to be correct.
You don't need to "uniquely identify" as part of the parser, a label is identified by the syntax of the language. It is entirely legal to allow labels to overlap with other symbol / variable names. Just add a rule for a legal label, reuse the lexer TOKEN for IDENTIFIER, then store labels in a symbol table per function so you can detect duplicate labels.
Typically in C-like languages, a label is part of a statement rule. It doesn't usually make sense anywhere else. The way I do it:
labeled_statement:
IDENTIFIER ':' statement
{
$$ = $3;
$$->label = new Label($1);
}
;
Another way:
label:
IDENTIFIER ':'
{ $$ = new Label($1); }
;
labeled_statement:
label statement
{
$$ = $2;
$$->label = $1;
}
;

Resources