[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Identifying start of new rule
From: |
Test User |
Subject: |
Identifying start of new rule |
Date: |
Sat, 15 Jun 2013 02:33:26 -0500 |
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);
}
- Identifying start of new rule,
Test User <=