我正在尝试使用 flex 和 bison 编写扫描仪和解析器来解析一个简单的脚本文件。我只能解析脚本文件的第一行。之后,程序以错误“yyerror:语法错误”终止。如何让我的程序继续到脚本的下一行?
我正在使用带有以下编译选项的 Window7。
汇编:
flex lex.l
bison -d yacc.y
g++ lex.yy.c yacc.tab.c -lfl -o scanner.exe
在这里,我附上了 .l、.y 文件和我的 script.txt 文件。
文件:lex.l
%{
#include <iostream>
#include <stdio.h>
#include "yacc.tab.h"
#define YY_DECL extern "C" int yylex()
using namespace std;
%}
DOT "."
COLON ":"
SEMICOLON ";"
COMMA ","
ANGLE_LEFT "<"
ANGLE_RIGHT ">"
AT "@"
EQUAL "="
SQUARE_OPEN "["
SQUARE_CLOSE [^\\]"]"
OPENBRACE "\("
CLOSEBRACE "\)"
QUOTE "\""
QUOTE_OPEN "\""
QUOTE_CLOSE [^\\]"\""
SPACE " "
TAB "\t"
CRLF "\r\n"
QUOTED_PAIR "\\"[^\r\n]
DIGIT [0-9]
ALPHA [a-zA-Z]
QTEXT [0-9a-zA-Z!#$%&'()*+,\-.\/:;<=>?@\[\]^_`{|}~]
%%
{SPACE}*{OPENBRACE}{SPACE}* { return TOK_OPENBRACE; }
{SPACE}*{CLOSEBRACE}{SPACE}* { return TOK_CLOSEBRACE; }
{SPACE}*{SEMICOLON}{SPACE}* { return TOK_SEMICOLON; }
{SPACE}*{COMMA}{SPACE}* { return TOK_COMMA; }
{QUOTE_OPEN}({SPACE}*{QTEXT}*{QUOTED_PAIR}*)*{QUOTE_CLOSE} {
yylval.sval = &yytext[1];
yylval.sval[strlen(yylval.sval) - 1] = '\0';
return TOK_QUOTED_STRING;
}
{DIGIT}+ {
yylval.lval = atoi(yytext);
return TOK_LONG;
}
"true"|"false" {
yylval.ival = ((0 == strcmp(yytext, "true")) ? 1 : 0 );
return TOK_BOOL;
}
^"function1" { return TOK_FUNC1; }
^"function2" { return TOK_FUNC2; }
^"function3" { return TOK_FUNC3; }
^{CRLF} { return TOK_EMPTY_LINE; }
{CRLF} {}
. {}/* ignore unknown chars */
文件:yacc.y
%{
#include <iostream>
#include <stdio.h>
using namespace std;
extern "C" int yylex();
extern "C" FILE *yyin;
int yyerror(const char *s);
%}
// Symbols.
%union
{
char *sval;
long lval;
int ival;
};
%token TOK_FUNC1
%token TOK_FUNC2
%token TOK_FUNC3
%token <sval> TOK_QUOTED_STRING
%token <lval> TOK_LONG
%token <ival> TOK_BOOL
%token TOK_SEMICOLON
%token TOK_OPENBRACE
%token TOK_CLOSEBRACE
%token TOK_COMMA
%token TOK_EMPTY_LINE
%start program
%%
program : func1
| func2
| func3
| empty_line
;
func1 : TOK_FUNC1 TOK_OPENBRACE TOK_QUOTED_STRING TOK_COMMA TOK_LONG TOK_COMMA TOK_BOOL TOK_CLOSEBRACE TOK_SEMICOLON
{
cout << "function1:" << $3 << " " << $5 << " " << $7;
}
func2 : TOK_FUNC2 TOK_OPENBRACE TOK_QUOTED_STRING TOK_COMMA TOK_LONG TOK_COMMA TOK_BOOL TOK_CLOSEBRACE TOK_SEMICOLON
{
cout << "function2:" << $3 << " " << $5 << " " << $7;
}
func3 : TOK_FUNC3 TOK_OPENBRACE TOK_QUOTED_STRING TOK_COMMA TOK_LONG TOK_COMMA TOK_BOOL TOK_CLOSEBRACE TOK_SEMICOLON
{
cout << "function3:" << $3 << " " << $5 << " " << $7;
}
empty_line : TOK_EMPTY_LINE
{
}
%%
int yyerror(const char *s) {
cout << "yyerror : " << s << endl;
}
int main(void) {
FILE * pt = fopen("script.txt", "r" );
yyin = pt;
yyparse();
}
文件:脚本.txt
function1("scanner1", 1234, true );
function2("scanner2", 4321, false );
function3("scanner3", 0123, true );
输出:
function1:scanner1 1234 1
yyerror : syntax error
预期输出:
function1:scanner1 1234 1
function2:scanner2 4321 0
function3:scanner3 0123 1