So I am writing a grammar using the BNF-Convertor (BNFC) to parse a c++ program. The c++ program is as follows.
// a small C++ program
#include <iostream>
int main()
{
std::cout << "i";
return 0;
}
The BNF grammar I wrote for this is as follows.
PDefs. Program ::= [Def] ;
terminator Def "" ;
comment "//" ;
comment "/*" "*/" ;
comment "#" ;
DFun. Def ::= Type Id "(" [Arg] ")" "{" [Stm] "}" ;
separator Arg "," ;
terminator Stm "" ;
separator nonempty Id "::" ;
ADecl. Arg ::= Type Id ;
SExp. Stm ::= Exp ";" ;
Sids. Stm ::= Id ;
SDecl. Stm ::= Type Id ";" ;
SDecls. Stm ::= Type Id "," [Id] ";" ;
SInit. Stm ::= Type Id "=" Exp ";" ;
SReturn. Stm ::= "return" Exp ";" ;
SWhile. Stm ::= "while" "(" Exp ")" Stm ;
SBlock. Stm ::= "{" [Stm] "}" ;
SIfElse. Stm ::= "if" "(" Exp ")" Stm "else" Stm ;
EInt. Exp15 ::= Integer ;
EDouble. Exp15 ::= Double ;
ETrue. Exp15 ::= "true" ;
EFalse. Exp15 ::= "false" ;
EId. Exp15 ::= Id ;
EApp. Exp15 ::= Id "(" [Exp] ")" ;
EStr. Exp15 ::= "\"" Id "\"";
EPIncr. Exp14 ::= Exp15 "++" ;
EPDecr. Exp14 ::= Exp15 "--" ;
EIncr. Exp13 ::= "++" Exp14 ;
EDecr. Exp13 ::= "--" Exp14 ;
ETimes. Exp12 ::= Exp12 "*" Exp13 ;
EDiv. Exp12 ::= Exp12 "/" Exp13 ;
EPlus. Exp11 ::= Exp11 "+" Exp12 ;
EMinus. Exp11 ::= Exp11 "-" Exp12 ;
ELs. Exp9 ::= Exp9 "<<" Exp10 ;
ERs. Exp9 ::= Exp9 ">>" Exp10 ;
ELt. Exp9 ::= Exp9 "<" Exp10 ;
EGt. Exp9 ::= Exp9 ">" Exp10 ;
ELtEq. Exp9 ::= Exp9 "<=" Exp10 ;
EGtWq. Exp9 ::= Exp9 ">=" Exp10 ;
EEq. Exp8 ::= Exp8 "==" Exp9 ;
ENEq. Exp8 ::= Exp8 "!=" Exp9 ;
EAnd. Exp4 ::= Exp4 "&&" Exp5 ;
EOr. Exp3 ::= Exp3 "||" Exp4 ;
EAss. Exp2 ::= Exp3 "=" Exp2 ;
coercions Exp 15 ;
separator Exp "," ;
separator Id "," ;
Tbool. Type ::= "bool" ;
Tdouble. Type ::= "double" ;
Tint. Type ::= "int" ;
Tvoid. Type ::= "void" ;
token Id (letter (letter | digit | '_' )*) ;
token Ids (letter)* ;
I have written the rules for both :: and the left shift operators here << and >> right shift operators but for some reason it's not parsing correctly. What am I doing wrong?
According to my understanding this should work but it gives this error.
syntax error at line 6 before << "i" ; return
Your problem is that
std::coutis not anId. It might be an[Id]-- that is, a list ofIds -- because of the declarationbut that declaration conflicts with the later declaration
I don't know enough about BNFC to predict the result of that conflict, but it is hard to imagine that the result is what you want.
The syntax for an expression does not use
[Id]; it only allowsId:So the qualified name
std::coutis not going to be parsed as anExp15.You have two very different contexts in which you attempt to use lists of
Ids; they differ both syntactically and semantically. So you really cannot expect to use[Id]for both of them.Since you evidently want to be able to handle namespace'd names, I'd suggest explicitly defining
Nameas a non-empty::-separated list ofIds. You could use the[Id]macro instead of your own definition, of course; that's really a judgement of style. To me, it seems less clear but tastes vary.In the other context -- declarations -- the use of
[Id]is really not correct, although it might be sufficient for your simplified grammar. Here, I'd recommend using a newDeclaratornon-terminal, which you could initially define as justIdbut which you will eventually want to expand to include pointer declarators (*foo), array declarators (foo[3]) and maybe even function declarators. With theDeclaratornon-terminal, you can replacewith
Note: from the "LBNF Grammar Formalism", in section 7 (Macros):