help-bison
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Identifying start of new rule


From: Chris verBurg
Subject: Re: Identifying start of new rule
Date: Sat, 15 Jun 2013 21:19:22 -0700

Dear Test,

I have to start by saying I got a giggle out of your yyerror function,
because I saw the "EEK" and figured out it was my tutorial you read
through.  Awesome!  Glad it's still useful.  :)

I think the core of your problem is this rule:
    <expansion> ::= <expansion> <expansion>
which essentially turns <expansion> into an arbitrarily long list, and
since you have rules that start with <expansion>s that means it continues
right into the next definition.  It's gobbling up everything it possibly
can, and then getting confused because it over-gobbled the <expansion>
before "::=".

I can think of two immediate solutions:
1. introduce an 'end of rule' marker (such as the infamous semicolon) so
that the arbitrarily long list has a clearly defined end.  Then it will no
longer over-gobble into the next definition.
2. turn on GLR parsing so that it'll scan farther ahead before gobbling.
I'm not a particular fan of this, and I'm not even sure it would
necessarily work, but the details are at
http://www.gnu.org/software/bison/manual/html_node/GLR-Parsers.html

-Chris




On Sat, Jun 15, 2013 at 12:33 AM, Test User <address@hidden> 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);
> }
>
> _______________________________________________
> address@hidden https://lists.gnu.org/mailman/listinfo/help-bison
>


reply via email to

[Prev in Thread] Current Thread [Next in Thread]