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;
}
;
Related
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 $$.
Some time ago after not standing anymore lines like this:
if (arg)
invk(test);
else if (test)
{
alot();
stuff();
}
I decided for my self its better for readability in our 1920x1200 times, to not omit the {}.
So I wrote a tool that reformats my existing code.
later I noticed a bug in that tool resulting in
if (x)
{
...
}
else if(y)
{
...
}
else if(z)
{
...
}
had been changed (wihtout obvisiously changing the behavior) into:
if (x)
{
...
}
else
{
if(y)
{
...
}
else
{
if(z)
{
...
}
}
}
This made me realize (unintended) that this is actually what a else if does by syntax and semantical rules of C.
So is there even an statement like else if() existing or is it just an abuse of semantic that results in this usefull but (lets call it so for this purpose) obfuscation originated wording that breaks any formating rules and just serves as human readable?
As per the C11, chapter ยง6.8.4, selection statements, the available statement blocks are
if ( expression ) statement
if ( expression ) statement else statement
switch ( expression ) statement
and, regarding the else part,
An else is associated with the lexically nearest preceding if that is allowed by the
syntax.
So, there is no else if construct, exists as per standard C.
Obviously, an if (or if...else) block can exist as the statement in else block (nested if...else, we may say).
The choice of indentation , is left to the user.
Note:
Just to add, there is no reason for a separate else if construct to exist, the functionality can be achieved by nesting. See this wiki article. Relevant quote
The often-encountered else if in the C family of languages, and in COBOL and Haskell, is not a language feature but a set of nested and independent "if then else" statements combined with a particular source code layout. However, this also means that a distinct else-if construct is not really needed in these languages.
As every one is aware, there is several different styles of programming languages. The presence of a elseif is based on the style of language.
In a C/Pascal style the if statement is
if (...)
statment;
else
statement;
and you have a compound statement:
{
statment;
statment;
}
while in a Modula2 / VB / (python ?) style language you have
if (...)
statement;
...
statement;
else
statement;
...
statement;
end-if
in the Modula2 / VB you need a elseif statement because if you tried using else if you get
if (..)
else if (..)
else if (..)
end-if; end-if; end-if;
The end-if's at the end are rather ugly.
As #anatolyg noted this is why you have a #elif in C macro language.
Cobol-85 has a different take on the elseif statement. It provides an extended Select/case statement. In Cobol you have an evaluate:
evaluate option
when 1
...
when 2
...
but you can also do
evaluate true
when age > 21 and gender = 'male'
...
when age > 21 and gender = 'female'
In Cobol you can also mix the case and if structure
evaluate option also true
when 1 also age > 21 and gender = 'male'
....
when 1 also age > 21 and gender = 'female'
....
when 2 also any
....
One final point in java and C you sometimes see
if () {
} else if () {
} else if () {
}
To all intents and purposes, this is VB / Modula-2 written in Java/C.
Is it possible to use a variable in the assignfile command?
Eg.
f : Textfile ;
sFile : string ; {contains 'MyFile.txt' as content}
...
cFileDir = 'C:\Users\User\Desktop\Data Engine\Data\Country' ;
...
Assignfile(f, cFileDir + '\' + sFile) ;
...
I appreciate your help very much. if it's unclear I'll edit the question to add more details.
Is it possible to use a variable in the AssignFile command?
Yes.
The second parameter of AssignFile has type string.
The expression cFileDir + '\' + sFile has type string.
FWIW, AssignFile is known as a function rather than a command. Getting on top of terminology like this will help you learn the language more effectively.
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).
I wanted to use a named parameter placeholder inside the LIKE operator pattern so that the argument string is properly escaped.
Here's my modified code where I am using the at-param placeholder:
var stmt = new air.SQLStatement();
stmt.text = "SELECT * FROM comments WHERE title LIKE '%#search%';";
stmt.parameters["#search"] = "argument string";
stmt.execute();
Doing so yields an SQLError with the following details
message: Error #3315: SQL Error.
details: '#search' parameter name(s) found in parameters property but not in the SQL specified
As suggested by Mike Petty, I tried:
stmt.text = 'SELECT * FROM comments WHERE title LIKE "#%search%";';
Which yields to the same SQL Error details.
Documentation has this:
expr ::= (column-name | expr) LIKE pattern
pattern ::= '[ string | % | _ ]'
My suspicion is that it is skipped due to the qoutes, any ideas on how to make it work?
Found a solution for this, basically instead of doing it like this:
var stmt = new air.SQLStatement();
stmt.text = "SELECT * FROM comments WHERE title LIKE '%#search%';";
stmt.parameters["#search"] = "argument string";
stmt.execute();
You have to put a placeholder for the entire LIKE operator pattern and bind the pattern as a parameter.
var stmt = new air.SQLStatement();
stmt.text = "SELECT * FROM comments WHERE title LIKE #search;";
stmt.parameters["#search"] = "%" + userInput + "%";
stmt.execute();
Remove your :string from your string.
Like works just fine as:
SELECT * FROM comments WHERE comments.title LIKE '%string%';
It's hard to tell from your question, but is your current statement either throwing a SQLError, just doesn't compile, or just doesn't return any results?
If I had to guess I'd say you have a few issues here:
You shouldn't have to qualify the column in the where clause since you only have 1 table to select from
The parameter string is technically a reserved word by AIR / Actionscript (although the case is different) - still a bit confusing.
Even though the documentation and code allow you to use either the colon, or at-symbol, my preference is the # since it's a bit easier to see ;)
Don't forget to add an itemClass definition of the Class you expect for rows - this helps to avoid anonymous objects.
This should be fairly straight forward:
var stmt:SQLStatement = new SQLStatement();
stmt.itemClass = Comment;
stmt.text = 'SELECT * FROM comments WHERE title LIKE "#%search%";';
stmt.parameters['#search'] = userInput.text;
stmt.addEventListener(SQLEvent.RESULT, onResults);
stmt.execute();