I'm writing a compiler, using top-down table-driven parsing. I've converted my grammar into LL(1), and it's the following:
<START> -> <prog>
<aParams> -> <expr> <rept-aParams1>
<aParams> -> EPSILON
<aParamsTail> -> ',' <expr>
<addOp> -> '+'
<addOp> -> '-'
<addOp> -> 'or'
<arithExpr> -> <term> <rightrec-arithExpr>
<arraySize> -> '[' 'intNum' ']'
<arraySize> -> '[' ']'
<assignOp> -> '='
<assignStat> -> <variable> <assignOp> <expr>
<classDecl> -> 'class' 'id' <opt-classDecl2> '{' <rept-classDecl4> '}' ';'
<expr> -> <arithExpr>
<expr> -> <relExpr>
<fParams> -> <type> 'id' <rept-fParams2> <rept-fParams3>
<fParams> -> EPSILON
<fParamsTail> -> ',' <type> 'id' <rept-fParamsTail3>
<factor> -> <variable>
<factor> -> <functionCall>
<factor> -> 'intNum'
<factor> -> 'floatNum'
<factor> -> '(' <arithExpr> ')'
<factor> -> 'not' <factor>
<factor> -> <sign> <factor>
<funcBody> -> <opt-funcBody0> 'do' <rept-funcBody2> 'end'
<funcDecl> -> 'id' '(' <fParams> ')' ':' <type> ';'
<funcDecl> -> 'id' '(' <fParams> ')' ':' 'void' ';'
<funcDef> -> <funcHead> <funcBody> ';'
<funcHead> -> <opt-funcHead0> 'id' '(' <fParams> ')' ':' <type>
<funcHead> -> <opt-funcHead0> 'id' '(' <fParams> ')' ':' 'void'
<functionCall> -> <rept-functionCall0> 'id' '(' <aParams> ')'
<idnest> -> 'id' <rept-idnest1> '.'
<idnest> -> 'id' '(' <aParams> ')' '.'
<indice> -> '[' <arithExpr> ']'
<memberDecl> -> <funcDecl>
<memberDecl> -> <varDecl>
<multOp> -> '*'
<multOp> -> '/'
<multOp> -> 'and'
<opt-classDecl2> -> 'inherits' 'id' <rept-opt-classDecl22>
<opt-classDecl2> -> EPSILON
<opt-funcBody0> -> 'local' <rept-opt-funcBody01>
<opt-funcBody0> -> EPSILON
<opt-funcHead0> -> 'id' 'sr'
<opt-funcHead0> -> EPSILON
<prog> -> <rept-prog0> <rept-prog1> 'main' <funcBody>
<relExpr> -> <arithExpr> <relOp> <arithExpr>
<relOp> -> 'eq'
<relOp> -> 'neq'
<relOp> -> 'lt'
<relOp> -> 'gt'
<relOp> -> 'leq'
<relOp> -> 'geq'
<rept-aParams1> -> <aParamsTail> <rept-aParams1>
<rept-aParams1> -> EPSILON
<rept-classDecl4> -> <visibility> <memberDecl> <rept-classDecl4>
<rept-classDecl4> -> EPSILON
<rept-fParams2> -> <arraySize> <rept-fParams2>
<rept-fParams2> -> EPSILON
<rept-fParams3> -> <fParamsTail> <rept-fParams3>
<rept-fParams3> -> EPSILON
<rept-fParamsTail3> -> <arraySize> <rept-fParamsTail3>
<rept-fParamsTail3> -> EPSILON
<rept-funcBody2> -> <statement> <rept-funcBody2>
<rept-funcBody2> -> EPSILON
<rept-functionCall0> -> <idnest> <rept-functionCall0>
<rept-functionCall0> -> EPSILON
<rept-idnest1> -> <indice> <rept-idnest1>
<rept-idnest1> -> EPSILON
<rept-opt-classDecl22> -> ',' 'id' <rept-opt-classDecl22>
<rept-opt-classDecl22> -> EPSILON
<rept-opt-funcBody01> -> <varDecl> <rept-opt-funcBody01>
<rept-opt-funcBody01> -> EPSILON
<rept-prog0> -> <classDecl> <rept-prog0>
<rept-prog0> -> EPSILON
<rept-prog1> -> <funcDef> <rept-prog1>
<rept-prog1> -> EPSILON
<rept-statBlock1> -> <statement> <rept-statBlock1>
<rept-statBlock1> -> EPSILON
<rept-varDecl2> -> <arraySize> <rept-varDecl2>
<rept-varDecl2> -> EPSILON
<rept-variable0> -> <idnest> <rept-variable0>
<rept-variable0> -> EPSILON
<rept-variable2> -> <indice> <rept-variable2>
<rept-variable2> -> EPSILON
<rightrec-arithExpr> -> EPSILON
<rightrec-arithExpr> -> <addOp> <term> <rightrec-arithExpr>
<rightrec-term> -> EPSILON
<rightrec-term> -> <multOp> <factor> <rightrec-term>
<sign> -> '+'
<sign> -> '-'
<statBlock> -> 'do' <rept-statBlock1> 'end'
<statBlock> -> <statement>
<statBlock> -> EPSILON
<statement> -> <assignStat> ';'
<statement> -> 'if' '(' <relExpr> ')' 'then' <statBlock> 'else' <statBlock> ';'
<statement> -> 'while' '(' <relExpr> ')' <statBlock> ';'
<statement> -> 'read' '(' <variable> ')' ';'
<statement> -> 'write' '(' <expr> ')' ';'
<statement> -> 'return' '(' <expr> ')' ';'
<statement> -> <functionCall> ';'
<term> -> <factor> <rightrec-term>
<type> -> 'integer'
<type> -> 'float'
<type> -> 'id'
<varDecl> -> <type> 'id' <rept-varDecl2> ';'
<variable> -> <rept-variable0> 'id' <rept-variable2>
<visibility> -> 'public'
<visibility> -> 'private'
Using the tool here, I've generated a parse table and stack push map, which are the following:
Parse Table:
[[0,"','","'+'","'-'","'or'","'['","'intNum'","']'","'='","'class'","'id'","'{'","'}'","';'","'floatNum'","'('","')'","'not'","'do'","'end'","':'","'void'","'.'","'*'","'/'","'and'","'inherits'","'local'","'sr'","'main'","'eq'","'neq'","'lt'","'gt'","'leq'","'geq'","'if'","'then'","'else'","'while'","'read'","'write'","'return'","'integer'","'float'","'public'","'private'","$"],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,112,112,112,112,112,112,112,112,1,1,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,1,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,111],[0,112,2,2,112,112,2,112,112,112,2,112,112,112,2,2,3,2,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112],[0,4,112,112,112,112,112,112,112,112,112,112,112,112,112,112,111,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112],[0,112,5,6,7,112,111,112,112,112,111,112,112,112,111,111,112,111,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112],[0,111,8,8,112,112,8,111,112,112,8,112,112,111,8,8,111,8,112,112,112,112,112,112,112,112,112,112,112,112,111,111,111,111,111,111,112,112,112,112,112,112,112,112,112,112,112,112],[0,111,112,112,112,10,112,112,112,112,112,112,112,111,112,112,111,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112],[0,112,111,111,112,112,111,112,11,112,111,112,112,112,111,111,112,111,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112],[0,112,112,112,112,112,112,112,112,112,12,112,112,111,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112],[0,112,112,112,112,112,112,112,112,13,111,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,111,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112],[0,111,15,15,112,112,15,112,112,112,15,112,112,111,15,15,111,15,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112],[0,112,112,112,112,112,112,112,112,112,16,112,112,112,112,112,17,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,16,16,112,112,112],[0,18,112,112,112,112,112,112,112,112,112,112,112,112,112,112,111,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112],[0,111,25,25,111,112,21,111,112,112,20,112,112,111,22,23,111,24,112,112,112,112,112,111,111,111,112,112,112,112,111,111,111,111,111,111,112,112,112,112,112,112,112,112,112,112,112,112],[0,112,112,112,112,112,112,112,112,112,112,112,112,111,112,112,112,112,26,112,112,112,112,112,112,112,112,26,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,111],[0,112,112,112,112,112,112,112,112,112,28,112,111,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,111,111,112],[0,112,112,112,112,112,112,112,112,112,29,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,111,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112],[0,112,112,112,112,112,112,112,112,112,31,112,112,112,112,112,112,112,111,112,112,112,112,112,112,112,112,111,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112],[0,111,111,111,111,112,112,111,112,112,32,112,112,111,112,112,111,112,112,112,112,112,112,111,111,111,112,112,112,112,111,111,111,111,111,111,112,112,112,112,112,112,112,112,112,112,112,112],[0,112,112,112,112,112,112,112,112,112,34,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112],[0,111,111,111,111,35,112,111,111,112,112,112,112,111,112,112,111,112,112,112,112,112,111,111,111,111,112,112,112,112,111,111,111,111,111,111,112,112,112,112,112,112,112,112,112,112,112,112],[0,112,112,112,112,112,112,112,112,112,37,112,111,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,37,37,111,111,112],[0,112,111,111,112,112,111,112,112,112,111,112,112,112,111,111,112,111,112,112,112,112,112,38,39,40,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112],[0,112,112,112,112,112,112,112,112,112,112,42,112,112,112,112,112,112,112,112,112,112,112,112,112,112,41,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112],[0,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,44,112,112,112,112,112,112,112,112,43,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112],[0,112,112,112,112,112,112,112,112,112,46,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112],[0,112,112,112,112,112,112,112,112,47,47,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,47,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,111],[0,111,48,48,112,112,48,112,112,112,48,112,112,111,48,48,111,48,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112],[0,112,111,111,112,112,111,112,112,112,111,112,112,112,111,111,112,111,112,112,112,112,112,112,112,112,112,112,112,112,49,50,51,52,53,54,112,112,112,112,112,112,112,112,112,112,112,112],[0,55,112,112,112,112,112,112,112,112,112,112,112,112,112,112,56,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112],[0,112,112,112,112,112,112,112,112,112,112,112,58,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,57,57,112],[0,60,112,112,112,59,112,112,112,112,112,112,112,112,112,112,60,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112],[0,61,112,112,112,112,112,112,112,112,112,112,112,112,112,112,62,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112],[0,64,112,112,112,63,112,112,112,112,112,112,112,112,112,112,64,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112],[0,112,112,112,112,112,112,112,112,112,65,112,112,112,112,112,112,112,112,66,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,65,112,112,65,65,65,65,112,112,112,112,112],[0,112,112,112,112,112,112,112,112,112,68,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112],[0,112,112,112,112,69,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,70,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112],[0,71,112,112,112,112,112,112,112,112,112,72,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112],[0,112,112,112,112,112,112,112,112,112,73,112,112,112,112,112,112,112,74,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,73,73,112,112,112],[0,112,112,112,112,112,112,112,112,75,76,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,76,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112],[0,112,112,112,112,112,112,112,112,112,77,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,78,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112],[0,112,112,112,112,112,112,112,112,112,79,112,112,112,112,112,112,112,112,80,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,79,112,112,79,79,79,79,112,112,112,112,112],[0,112,112,112,112,81,112,112,112,112,112,112,112,82,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112],[0,112,112,112,112,112,112,112,112,112,84,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112],[0,86,86,86,86,85,112,86,86,112,112,112,112,86,112,112,86,112,112,112,112,112,112,86,86,86,112,112,112,112,86,86,86,86,86,86,112,112,112,112,112,112,112,112,112,112,112,112],[0,87,88,88,88,112,112,87,112,112,112,112,112,87,112,112,87,112,112,112,112,112,112,112,112,112,112,112,112,112,87,87,87,87,87,87,112,112,112,112,112,112,112,112,112,112,112,112],[0,89,89,89,89,112,112,89,112,112,112,112,112,89,112,112,89,112,112,112,112,112,112,90,90,90,112,112,112,112,89,89,89,89,89,89,112,112,112,112,112,112,112,112,112,112,112,112],[0,112,91,92,112,112,111,112,112,112,111,112,112,112,111,111,112,111,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112],[0,112,112,112,112,112,112,112,112,112,94,112,112,95,112,112,112,112,93,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,94,112,95,94,94,94,94,112,112,112,112,112],[0,112,112,112,112,112,112,112,112,112,102,112,112,111,112,112,112,112,112,111,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,97,112,111,98,99,100,101,112,112,112,112,112],[0,111,103,103,111,112,103,111,112,112,103,112,112,111,103,103,111,103,112,112,112,112,112,112,112,112,112,112,112,112,111,111,111,111,111,111,112,112,112,112,112,112,112,112,112,112,112,112],[0,112,112,112,112,112,112,112,112,112,106,112,112,111,112,112,112,112,111,112,112,112,112,112,112,112,112,111,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,104,105,112,112,112],[0,112,112,112,112,112,112,112,112,112,107,112,111,112,112,112,112,112,111,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,107,107,111,111,112],[0,111,111,111,111,112,112,111,111,112,108,112,112,111,112,112,111,112,112,112,112,112,112,111,111,111,112,112,112,112,111,111,111,111,111,111,112,112,112,112,112,112,112,112,112,112,112,112],[0,112,112,112,112,112,112,112,112,112,111,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,111,111,109,110,112]]
Push map:
{"1":[26],"2":[29,10],"4":[10,-1],"5":[-2],"6":[-3],"7":[-4],"8":[45,50],"9":[-7,-6,-5],"10":[-7,-5],"11":[-8],"12":[10,7,53],"13":[-13,-12,30,-11,23,-10,-9],"14":[5],"15":[27],"16":[32,31,-10,51],"18":[33,-10,51,-1],"19":[53],"20":[18],"21":[-6],"22":[-14],"23":[-16,5,-15],"24":[13,-17],"25":[13,47],"26":[-19,34,-18,24],"27":[-13,51,-20,-16,11,-15,-10],"28":[-13,-21,-20,-16,11,-15,-10],"29":[-13,14,17],"30":[51,-20,-16,11,-15,-10,25],"31":[-21,-20,-16,11,-15,-10,25],"32":[-16,2,-15,-10,35],"33":[-22,36,-10],"34":[-22,-16,2,-15,-10],"35":[-7,5,-5],"36":[15],"37":[52],"38":[-23],"39":[-24],"40":[-25],"41":[37,-10,-26],"43":[38,-27],"45":[-28,-10],"47":[14,-29,40,39],"48":[5,28,5],"49":[-30],"50":[-31],"51":[-32],"52":[-33],"53":[-34],"54":[-35],"55":[29,3],"57":[30,21,54],"59":[31,6],"61":[32,12],"63":[33,6],"65":[34,49],"67":[35,19],"69":[36,20],"71":[37,-10,-1],"73":[38,52],"75":[39,9],"77":[40,16],"79":[41,49],"81":[42,6],"83":[43,19],"85":[44,20],"88":[45,50,4],"90":[46,13,22],"91":[-2],"92":[-3],"93":[-19,41,-18],"94":[49],"96":[-13,8],"97":[-13,48,-38,48,-37,-16,27,-15,-36],"98":[-13,48,-16,27,-15,-39],"99":[-13,-16,53,-15,-40],"100":[-13,-16,10,-15,-41],"101":[-13,-16,10,-15,-42],"102":[-13,18],"103":[46,13],"104":[-43],"105":[-44],"106":[-10],"107":[-13,42,-10,51],"108":[44,-10,43],"109":[-45],"110":[-46]}
The construction of the parsing table is given as the following:
On the LL(1) Parsing Table's Meaning and Construction
The top row corresponds to the columns for all the potential terminal symbols, augmented with $ to represent the end of the parse.
The leftmost column and second row are all zero filled, to accomodate the way Fischer and LeBlanc wrote their parser's handling of abs().
The remaining rows correspond to production rules in the original grammar that you typed in.
Each entry in that row maps the left-hand-side (LHS) of a production rule onto a line-number. That number is the line in which the LHS had that specific column symbol in its predict set.
If a terminal is absent from a non-terminal's predict set, an error code is placed in the table. If that terminal is in follow(that non-terminal), the error is a POP error. Else, it's a SCAN error.
POP error code = # of predict table productions + 1
SCAN error code = # of predict table productions + 2
In practice, you'd want to tear the top, label row off of the table and stick it in a comment, so that you can make sense of your table. The remaining table can be used as is.
Given these, though, I'm not entirely sure how to proceed. I'm just curious what the general algorithm, given the two objects, would be to parse over a stream of tokens and determine it's syntactically correct.
This won't help you much because, as noted below, LL(1) parse tables generated for that grammar cannot be accurate.
However, for what it's worth, here's my reverse engineering of those tables. It's probable that you could get a deeper understanding of this procedure by reading the text book referenced by the tool. (Note: link is not an endorsement, neither of the book nor of the vendor. I just copied it from the tool.)
The terminal symbols appear in order in the top row of the parse table (the one which the instructions say should be removed for use). So terminal symbol 1 is ','
, symbol 2 is '+'
, and so on up to symbol 46, which is the $
conventionally used as an end-of-input marker. (That's different from '$'
, which would be a literal dollar sign.)
Non-terminal symbols don't appear explicitly (so you can't recover their names from the tables) but they are also numbered in order. There are 54 of them, and each row of the parse table (after the first two) corresponds to a non-terminal symbol.
There are 110 productions, which are listed (with their corresponding index) in the Predict set section of the output from that tool. Each production corresponds to one entry in the "push map", which (since this is Javascript) uses the string conversion of the production number as a key.
The corresponding value in the push map is a list of indices: negative indices refer to terminals and positive indices refer to non-terminals. The index 0 is not used, which is why row 0 of the parse map is unused. From these indices, it is possible to reconstruct the right-hand side of the production, but they are actually used to indicate what to push onto the parse stack at each step in the parse.
The stack contains the list current predictions, with the top element of the stack being the immediate prediction at this point in the parse.
So the algorithm is as follows:
Initialise the parser stack to [1, -46]
, which indicates that the current prediction consists of the right-hand side of the production <START> -> <prog>
followed by the end-of-input marker $
.
Repeat the following until terminated by an error or by acceptance:
rhs
from parseTable[stack.top()][lookahead]
. If rhs
has a value greater than the number of productions (in this case, the values 111 or 112) then the input is incorrect. Report an error and terminate the parse. (The value will tell you whether it was a scan error or a pop error, but that might not make much difference to you. It could be used to improve error reporting.)pushMap[rhs]
onto the stack, starting at the end. (For example, if rhs
were 4, you would use the list from pushMap["4"]
, which is [10, -1]
. So you would push first -1
and then 10
onto the parser stack.)pushMap[rhs]
doesn't exist, you just pop the parse stack; there is nothing to push.That algorithm does not include any procedure for producing a syntax tree for successful parses. But if you want to do anything more than just decide whether the input is a valid program or not, then you will definitely want to produce some kind of syntax tree.
I don't know how much credibility you should give the tool you are using.
Your grammar is not LL(1), but the tool does not provide any indication of that fact.
A simple example is
<arraySize> -> '[' 'intNum' ']'
<arraySize> -> '[' ']'
where the lookahead token [
does not predict a unique production. That would be easy to fix by left-factoring, but I don't see any evidence that the tool is capable of doing that.
A more serious problem is
<expr> -> <arithExpr>
<expr> -> <relExpr>
<arithExpr> -> <term> <rightrec-arithExpr>
<relExpr> -> <arithExpr> <relOp> <arithExpr>
Since a relExpr
can start with arithExpr
, the two productions for expr
overlap; it's not possible to predict from an examination of a single lookahead token (or, indeed, any constant number of lookahead tokens) whether the expr
is a comparison or not. You can't tell until you finish parsing the initial arithmetic expression (which could have an arbitrary length).
If you insist on LL(1), you would need to do something like:
<expr> -> <arithExpr> <optional-relExpr-tail>
<optional_relExpr-tail> -> EPSILON
<optional_relExpr-tail> -> <relop> <arithExpr>
Moreover, expr
leads to factor
, which could be either a variable
or a functionCall
, both of which start with idnest
(which ultimately leads to the terminal id
). But that's not the whole story either, because you might encounter the sequence <id> '(' <aParams> ')'
both in idnest
and in functionCall
.
Perhaps that tool doesn't intend to tell you that your grammar is not LL(1), but it seems to me like it should not generate tables in that case, since the tables are necessarily misleading. The prediction conflicts mean that the parsing table must prefer one or another competing production, and whichever one it does not prefer cannot appear in a parse, with the result that valid inputs will be rejected.
<opinion>
I believe that it is possible to create an LL(1) grammar for that language, but honestly it does not seem to me to be the best strategy. There are already so many book-keeping non-terminals in the grammar that it verges on the unreadable. If you insist on a top-down parser, use a generator which allows "extended" BNF: repetition and optionality operators on the right-hand side. Alternatively, you can use an LALR(1) generator with a much-simplified grammar, since LALR(1) allows both left-recursion and left-unfactored productions.
</opinion>