If I've understood correct, two points come to mind: a) exp : exp exp | ...
Seems highly ambiguous for no good reason. BTW, did you really want to exclude the possibility of productions that have only one symbol on the right-hand side? Not sure why you wouldn't use very standard/common constructs for defining lists with n or more members. b) 2 token lookahead. You may want to google "yacc manual" and read their discussion of the yacc grammar being LR(2) and their solution of having the lexer look ahead and return a different token type for a name followed by a ':'. On Sat, Jun 15, 2013 at 12:33 AM, Test User <testuser...@gmail.com> wrote: > Hello All, > > I am trying to parse an arbitrary BNF file. My simple test file > test.txt file contains: > > <procedure_declaration> ::= PROCEDURE <procedure_body> > <procedure_body> ::= BEGIN <statement> END > <statement> ::= PRINT "hello world" > > In this grammar upper-case strings and strings in double-quotes are > terminal symbols. Lower-case strings in angle brackets are > non-terminal symbols. I am trying to implement the following grammar > (for rules in BNF) in my bison file: > > <rule> ::= <name> "::=" <expansion> > <name> ::= < identifier > > <expansion> ::= <expansion> <expansion> > <expansion> ::= <expansion> "|" <expansion> > <expansion> ::= <name> > <expansion> ::= <terminal> > > When I parse test.txt, I get: > Found name <procedure_declaration> > Found LITERAL_STRING: PROCEDURE > Found name <procedure_body> > Found name <procedure_body> > Success! > EEK, parse error! Message: syntax error > > I understand that the rule `<expansion> ::= <expansion> <expansion>' > *does* allow `PROCEDURE <procedure_body> <procedure_body>' to be > reduced to <rule>. However, the second <procedure_body> is followed by > ::= (token EXPANDS_TO in my bison file) and is therefore the start of > a new rule and not part of a previous rule. How do I tell bison that > the second <procedure_body> is the start of a new rule? > > I admit that I have not read the manual yet. I found someone's > tutorial in which he made up a short, useless sample language and I am > trying to adapt it to my needs. Please see my bison file test.y below. > > Regards, > Test User > > %{ > #include <stdio.h> > #include <stdlib.h> > > extern int yylex(); > extern int yyparse(); > extern FILE *yyin; > > void yyerror(const char *s); > %} > > %union { > char cval; > int ival; > float fval; > char *sval; > } > > /* define the "terminal symbol" token types */ > %token <sval> EXPANDS_TO > %token <cval> AT_SIGN > %token <cval> DOT > %token <cval> COMMA > %token <cval> EQUAL > %token <cval> LEFT_ROUNDB > %token <cval> RIGHT_ROUNDB > %token <cval> LEFT_SQUAREB > %token <cval> RIGHT_SQUAREB > %token <cval> LEFT_CURLYB > %token <cval> RIGHT_CURLYB > %token <cval> LEFT_ANGLEB > %token <cval> RIGHT_ANGLEB > %token <sval> IDENTIFIER > %token <sval> QUOTED_STRING > %token <sval> LITERAL_STRING > %token <fval> FLOAT > %token <ival> INTEGER > %token <cval> OR > %% > > rule: name EXPANDS_TO expansion { printf("Success!\n"); } > > name: LEFT_ANGLEB IDENTIFIER RIGHT_ANGLEB { printf("Found name > %c%s%c\n", $1, $2, $3); } > > expansion: expansion expansion ; > > expansion: expansion OR expansion ; > > expansion: name ; > > expansion: terminal ; > > terminal: LITERAL_STRING { printf("Found LITERAL_STRING: %s\n", $1); } > %% > FILE *yyin; > > int main(int argc, char *argv[]) > { > FILE *fpi = NULL; > if (strcmp(argv[1], "-") == 0) > fpi = stdin; > else > fpi = fopen(argv[1], "r"); > if (!fpi){ > fprintf(stderr, "I can't open %s\n", argv[1]); > return -1; > } > yyin = fpi; > do{ > yyparse(); > } while (!feof(yyin)); > return 0; > > } > > void yyerror(const char *s) { > printf("EEK, parse error! Message: %s\n", s); > // might as well halt now: > exit(-1); > } > > _______________________________________________ > help-bison@gnu.org https://lists.gnu.org/mailman/listinfo/help-bison > _______________________________________________ help-bison@gnu.org https://lists.gnu.org/mailman/listinfo/help-bison