compiler-constructiongrammarbnfc

BNFC Bad Coercion in rule


I am trying to write a compiler with BNFC. I am going to use BNFC to generate the abstract syntax tree. But I am getting errors for the and I can't seem to figure out why. There doesn't seem to be much documentation on it.

Here are the errors I am getting:

Bad coercion in rule _. Prog ::= Block
Bad coercion in rule _. Declarations ::= Declaration ";" Declarations
Bad coercion in rule _. Declarations ::=
Bad coercion in rule _. Declaration ::= Var_declaration
Bad coercion in rule _. Declaration ::= Fun_declaration
Bad coercion in rule _. Type ::= "int"
Bad coercion in rule _. Type ::= "real"
Bad coercion in rule _. Type ::= "bool"
Bad coercion in rule _. Array_dimensions ::= "[" Expr "]" Array_dimensions
Bad coercion in rule _. Array_dimensions ::=
Bad coercion in rule _. Fun_block ::= Declarations Fun_body
Bad coercion in rule _. Param_list ::= "(" Parameters ")"
Bad coercion in rule _. Parameters ::= Basic_declaration More_parameters
Bad coercion in rule _. Parameters ::=
Bad coercion in rule _. More_parameters ::= "," Basic_declaration More_parameters
Bad coercion in rule _. More_parameters ::=
Bad coercion in rule _. Basic_declaration ::= Ident Basic_array_dimensions ":" Type
Bad coercion in rule _. Basic_array_dimensions ::=
Bad coercion in rule _. Program_body ::= "begin" Prog_stmts "end"
Bad coercion in rule _. Fun_body ::= "begin" Prog_stmts "return" Expr ";" "end"
Bad coercion in rule _. Prog_stmts ::= Prog_stmt ";" Prog_stmts
Bad coercion in rule _. Prog_stmts ::=
Bad coercion in rule _. Identifier ::= Ident Array_dimensions
Bad coercion in rule _. Expr ::= Bint_term
Bad coercion in rule _. Bint_term ::= Bint_factor
Bad coercion in rule _. Bint_factor ::= Int_expr Compare_op Int_expr
Bad coercion in rule _. Bint_factor ::= Int_expr
Bad coercion in rule _. Int_expr ::= Int_expr Addop Int_term
Bad coercion in rule _. Int_expr ::= Int_term
Bad coercion in rule _. Int_term ::= Int_term Mulop Int_factor
Bad coercion in rule _. Int_term ::= Int_factor
Bad coercion in rule _. Int_factor ::= "(" Expr ")"
Bad coercion in rule _. Modifier_list ::= "(" Arguments ")"
Bad coercion in rule _. Modifier_list ::= Array_dimensions
Bad coercion in rule _. Arguments ::= Expr More_arguments
Bad coercion in rule _. Arguments ::=
Bad coercion in rule _. More_arguments ::= "," Expr More_arguments
Bad coercion in rule _. More_arguments ::=

Here is a sample of the BNFC file:

_.Prog ::= Block;

M_Prog. Block ::= Declarations Program_body;

_.Declarations ::= Declaration ";" Declarations;
_. Declarations ::= ;

_. Declaration ::= Var_declaration;
_. Declaration ::= Fun_declaration;

M_Var. Var_declaration ::= "var" Ident Array_dimensions ":" Type;

_. Type ::= "int";
_. Type ::= "real";
_. Type ::= "bool"; 

_. Array_dimensions ::= "[" Expr "]" Array_dimensions;
_. Array_dimensions ::=;

M_Fun. Fun_declaration ::= "fun" Ident Param_list ":" Type "{" Fun_block "}";

_. Fun_block ::= Declarations Fun_body; 

_. Param_list ::= "(" Parameters ")";

_. Parameters ::= Basic_declaration More_parameters;
_. Parameters ::= ;

_. More_parameters ::= ","  Basic_declaration More_parameters;
_. More_parameters ::= ;

_. Basic_declaration ::= Ident Basic_array_dimensions ":" Type;

_. Basic_array_dimensions ::= "[" "]" Basic_array_dimensions;
_. Basic_array_dimensions ::=;

It seems to be that I am using the _. label incorrectly. But the manual only has a line or two describing it's use. What am I doing wrong here?


Solution

  • From the documentation:

    Underscores are of course only meaningful as replacements of one-argument constructors where the value type is the same as the argument type.

    Which means that you can only use _ if you have exactly one non-terminal in the right side of your rule and that non-terminal is the same as the one on the left site. So you can do something like _. A ::= "(" A ")" ; but not _. A ::= "(" B ")" ; nor _. A ::= "(" A A ")" ;.

    In your example, I suggest that you give a label to every rule, _ is mostly used to simplify the AST in some corner cases.

    BTW there is also a syntax shortcut for lists of things.