[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
>