I am having problem with a project that my professor assigned me.We are given the following
Goal
::= (Function|Statement)* <EOF>
Function
::= "def" Identifier "(" Argument? ")" ":" Statement
Argument
::= Identifier ("=" Value )? ( "," Identifier ("=" Value )?)*
Statement
::= tab* "if" Comparison ":" Statement
|tab* "while" Comparison ":" Statement
|tab* "for" Identifier "in" Identifier ":" Statement
|tab* "return" Expression
|tab* "print" Expression ("," Expression)*
|tab* Identifier ( "=" | "-=" | "/=" ) Expression
|tab* Identifier "[" Expression "]" "=" Expression
|tab* Function Call
Expression
::= Expression ( "+" | "-" | "*" | "/" ) Expression
| ( "++" | "--" ) Expression
| Expression( "++" | "--" )
| Identifier "[" Expression "]"
| Function Call
| Value
| Identifier
| "(" Expression ")"
| "["Value ( "," Value)*"]"
Comparison
::= Expression ( ">" | "<" | "!=" | "==") Expression
| "true"
| "false"
Function Call
::= Identifier "(" Arglist? ")"
Arglist
::= Expression ( "," Expression )*
Value
::= Number | "<STRING_LITERAL>"|'<STRING_LITERAL>'
Number
::= <INTEGER_LITERAL>
Identifier
::= <IDENTIFIER>
<STRING_LITERAL> = A word that can contain letter(capitals or non capital) and white spaces
<INTEGER_LITERAL> = An integer number
<IDENTIFIER> = Name of a variable
And we have to implement a grammar file with the lexical and syntax analysis.I have implemented most of the lines but i am having problem implementing the rest since i get a shift/reduce conflict.My code is this
Helpers
digit = ['0' .. '9'];
letter = ['a' .. 'z']|['A' .. 'Z'];
cr = 13;
lf = 10;
all = [0..127];
eol = lf | cr | cr lf ;
not_eol = [all - [cr + lf]];
Tokens
tab = 9;
plus = '+';
dplus = '++';
minus = '-';
dminus = '--';
mult = '*';
div = '/';
eq = '=';
minus_eq = '-=';
div_eq = '/=';
exclam = '!';
l_br = '[';
r_br = ']';
l_par = '(';
r_par = ')';
comma=',';
def = 'def';
if = 'if';
elif = 'elif';
else = 'else';
for = 'for';
in = 'in';
while = 'while';
print = 'print';
return = 'return';
less = '<';
great = '>';
not_eq = '!=';
log_eq = '==';
true = 'true';
semi = ':';
false = 'false';
quote = '"';
blank = (' ' | lf | cr);
line_comment = '#' not_eol* eol;
number = digit+;
id = letter (letter | digit)*;
string = ('"'not_eol* '"' | ''' not_eol* ''');
Ignored Tokens
blank, line_comment;
Productions
programme = commands*;
commands ={stat} statement|
{expr}expression;
function = {function} def id l_par argument? r_par semi statement;
argument = {argument} id arg1? arg2*;
arg1 = {arg1} eq value;
arg2 = {arg2} comma id arg1?;
statement = {if}tab* if comparison semi statement |
{while}tab* while comparison semi statement |
{for}tab* for [id1]:id in [id2]:id semi statement |
{return}tab* return expression|
{print}tab* print expression |
{assign}tab* id eq expression |
{reduce_by}tab* id minus_eq expression |
{divide_by}tab* id div_eq expression |
{array_element_assing}tab* id l_br [ex2]:expression r_br eq [ex32]:expression;
comparison = {true} true|
{false} false|
{lessc} [lpar]:expression less [rpar]:expression|
{greatc}[lpar]:expression great [rpar]:expression|
{equal} [lpar]:expression log_eq [rpar]:expression|
{not_equal} [lpar]:expression not_eq [rpar]:expression;
expression = {multiplication} multiplication |
{addition} expression plus multiplication |
{subtraction} expression minus multiplication |
{array}id l_br expression r_br;
multiplication = {something} something |
{multiplication} multiplication mult something |
{division} multiplication div something |
{postfix} suffix;
suffix = {dplus} dplus something |
{dminus} dminus something ;
value = {number} number |
{string} string;
something ={identifier}id|
{numb}number|
{par} l_par expression r_par;
The lines i can't include without shift/reduce conflict are
In statement
|tab* Function Call
in expression
|Expression( "++" | "--" )
| Function Call
| "["Value ( "," Value)*"]"
and the lines
Function Call
::= Identifier "(" Arglist? ")"
Arglist
::= Expression ( "," Expression )*
I posted only the production section and not everything since the problem lies there.I would love some help on how to add those lines in my grammar without the shift/reduce conflict.I am trying to solve this some days now and it looks like i tried everything.Thanks for your help in advance.
Your grammar allows an expression
to be a command
(which you confusingly call commands
). The grammar you are given does not.
Since there is no command separator, your grammar allows consecutive expressions. However, that is ambiguous. Is a+b
a single expression, or two expressions a
and +b
? What about a(b)
? A function call, or expression a
followed by expression (b)
? And so on.
You need to rethink the decision about what a command is.
By the way, something
is an awful name for a non-terminal and I find it confusing that you call a colon (:
) semi
; a semicolon is actually ;
, which is what I assumed that semi
refers to.