gpt4 book ai didi

bison - Flex/bison 语法错误

转载 作者:行者123 更新时间:2023-12-01 03:53:29 29 4
gpt4 key购买 nike

我正在尝试编写一个能够使用以下输入的语法:

begin #this is a example
x = 56;

while x > 0 do
begin
point 15.6 78.96;
end;
end;

这是 lexer.l 文件:
%option noyywrap

%{
#include "parser.h"
#include <stdlib.h>
#include <stdio.h>
const char * const unrecognizedToken = "Unrecognized token";

%}


NewLine \n
WhiteSpaces [\r\t\f\v ]+
Semicolon ;

digit [0-9]
number1 {digit}+\.?([eE][-+]?{digit}+)?
number2 {digit}*\.{digit}+([eE][-+]?{digit}+)?
double_number {number1}|{number2}

BEGIN "begin"
END "end"
WHILE "while"
DO "do"
POINT "point"

%x POINT_DEFINITIONS

%%

{WhiteSpaces} {
printf("WhiteSpaces");
printf("\n");
}

{NewLine} {
printf("NewLine");
printf("\n");
}


{WHILE} {
printf("While");
printf("\n");
return TOKEN_WHILE;
}

{BEGIN} {
printf("TOKEN_BEGIN");
printf("\n");
return TOKEN_BEGIN;
}

{END} {
printf("TOKEN_END");
printf("\n");
return TOKEN_END;
}

{DO} {
printf("DO");
printf("\n");
return TOKEN_DO;
}

{POINT} {
printf("POINT_START");
printf("\n");
BEGIN POINT_DEFINITIONS;
return TOKEN_POINT;
}

<POINT_DEFINITIONS>{double_number} {
printf("POINT_DEFINITIONS %s", yytext);
printf("\n");
yylval.dval = atof(yytext);
return TOKEN_DOUBLE;
}

<POINT_DEFINITIONS>{WhiteSpaces} {
printf("WhiteSpaces");
printf("\n");
}

[a-zA-Z_][a-zA-Z0-9_]* {
printf("TOKEN_IDENTIFIER");
printf("\n");
yylval.name = strdup(yytext);
return TOKEN_IDENTIFIER;
}

[()=;] {
printf("yytext = %s", yytext);
printf("\n");
return *yytext;
}

[*/+\-<>] {
printf("TOKEN_OPERATOR");
printf("\n");
yylval.op = *yytext;
return TOKEN_OPERATOR;
}

[-]?[0-9]+ {
printf("TOKEN_VALUE");
printf("\n");
yylval.val = atoi(yytext);
return TOKEN_VALUE;
}

#.* {
printf("COMMENT");
printf("\n");
/*comment*/
}

. { printf("%s", unrecognizedToken); }

这是 parser.y 文件:
%error-verbose
%{
#define YYDEBUG 1
%}

%union {
int val;
double dval;
char op;
char* name;
}

%token TOKEN_BEGIN TOKEN_END TOKEN_WHILE TOKEN_DO TOKEN_POINT TOKEN_OPERATOR TOKEN_VALUE TOKEN_IDENTIFIER TOKEN_DOUBLE
%start program

%{
void yyerror(const char* const message);

%}

%%

program: statement';';

block: TOKEN_BEGIN statements TOKEN_END { printf("rule block\n"); };

statements:
statement';' statements { printf("rule statements\n"); }
|;

statement:
| assignment
| command
| whileStmt
| block;

assignment: TOKEN_IDENTIFIER '=' TOKEN_VALUE {
printf("rule Assignment\n");
} ;

whileStmt: TOKEN_WHILE condition TOKEN_DO block {printf("rule While\n");};

condition: TOKEN_IDENTIFIER { printf("rule token_identifier\n"); }
| TOKEN_VALUE { printf("rule token_value\n"); }
| condition TOKEN_OPERATOR condition { printf("rule condition TOKEN_OPERATOR condition\n"); };

command: TOKEN_POINT TOKEN_DOUBLE TOKEN_DOUBLE { printf("rule Command\n"); };

%%

#include <stdlib.h>

void yyerror(const char* const message)
{
printf("Parse error:%s\n", message);
exit(1);
}

int main()
{
yyparse();
}

但是我收到以下错误消息:
Parse error:syntax error, unexpected $end, expecting ';'

编译成这样:
 flex -o lexer.c lexer.l
bison -v -d -o parser.c parser.y
gcc parser.c lexer.c -o parser -g -DYYDEBUG=1

运行解析器:
./parser < example

你能帮我找出问题所在吗?
为什么语法不能接受上面的例子作为输入?

最佳答案

你的问题出在你的词法分析器上(与你的语法是否有问题无关——我没有分析过语法,因为我首先在词法分析器中找到了问题,这足以阻止语法工作)。

我添加了一个测试 main()lexer.l :

%%

YYSTYPE yylval;

int main(void)
{
int token;
while ((token = yylex()) != 0)
printf("Token: %d (%s)\n", token, yytext);
return 0;
}

然后我在您的示例代码上运行它以查看 token 流是否正确生成。我得到的输出是:
TOKEN_BEGIN
Token: 258 (begin)
WhiteSpaces
COMMENT
NewLine
WhiteSpaces
TOKEN_IDENTIFIER
Token: 265 (x)
WhiteSpaces
yytext = =
Token: 61 (=)
WhiteSpaces
TOKEN_VALUE
Token: 264 (56)
yytext = ;
Token: 59 (;)
NewLine
NewLine
WhiteSpaces
While
Token: 260 (while)
WhiteSpaces
TOKEN_IDENTIFIER
Token: 265 (x)
WhiteSpaces
TOKEN_OPERATOR
Token: 263 (>)
WhiteSpaces
TOKEN_VALUE
Token: 264 (0)
WhiteSpaces
DO
Token: 261 (do)
NewLine
WhiteSpaces
TOKEN_BEGIN
Token: 258 (begin)
NewLine
WhiteSpaces
POINT_START
Token: 262 (point)
WhiteSpaces
POINT_DEFINITIONS 15.6
Token: 266 (15.6)
WhiteSpaces
POINT_DEFINITIONS 78.96
Token: 266 (78.96)
;
WhiteSpaces
end;
end;

如您所见,返回给主程序的最后一个 token 是 78.96。

当您识别出一个 POINT 时,您将启动 POINT_DEFINITIONS 状态。然而,一旦进入那个状态,你就永远处于那个状态;你永远不会回到初始状态。您可能需要向 POINT_DEFINITIONS 启动状态添加一条规则,以识别分号并执行 BEGIN INITIAL; :
<POINT_DEFINITIONS>{Semicolon} {
printf("Semicolon in POINT_DEFINITION state\n");
BEGIN INITIAL;
return *yytext;
}

有了这个,输出的尾端是:
...
TOKEN_BEGIN
Token: 258 (begin)
NewLine
WhiteSpaces
POINT_START
Token: 262 (point)
WhiteSpaces
POINT_DEFINITIONS 15.6
Token: 266 (15.6)
WhiteSpaces
POINT_DEFINITIONS 78.96
Token: 266 (78.96)
Semicolon in POINT_DEFINITION state
Token: 59 (;)
NewLine
WhiteSpaces
TOKEN_END
Token: 259 (end)
punctuation: yytext = ;
Token: 59 (;)
NewLine
TOKEN_END
Token: 259 (end)
punctuation: yytext = ;
Token: 59 (;)
NewLine

关于bison - Flex/bison 语法错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19743313/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com