使用flex和bison的计算器
我是flex和bison的新手,我正在尝试使用flex和bison制作一个计算器。我的flex正在编译,但我的bison文件中出现了错误 下面是我的flex文件:使用flex和bison的计算器,bison,flex-lexer,Bison,Flex Lexer,我是flex和bison的新手,我正在尝试使用flex和bison制作一个计算器。我的flex正在编译,但我的bison文件中出现了错误 下面是我的flex文件: %{ #include <stdio.h> #include <stdlib.h> #include "calc.tab.h" %} digit ([0-9]) characters ([a-z]) smallcasedigit ([a-z0-9]) identifier
%{
#include <stdio.h>
#include <stdlib.h>
#include "calc.tab.h"
%}
digit ([0-9])
characters ([a-z])
smallcasedigit ([a-z0-9])
identifier ([a-z])(a-z0-9])*
%option yylineno
%%
"main()" { return(TOK_MAIN);}
"{" { return(TOK_OPEN_CURLY);}
"}" { return(TOK_CLOSE_CURLY);}
"printvar" { return(TOK_PRINTVAR);}
"println" { return(TOK_PRINTLN);}
"int" { return(TOK_INT_KEYWORD);}
"float" { return(TOK_FLOAT_KEYWORD);}
{digit}+ { yylval.int_val=atoi(yytext);
printf(" TOK_NUM_INT \n");
return TOK_NUM_INT;}
{digit}+[.]{digit}+ { yylval.float_val=atof(yytext);
printf(" TOK_NUM_FLOAT \n");
return TOK_NUM_FLOAT;}
{identifier} { yylval.string=strdup(yytext);
printf(" TOK_IDENTIFIER %s\n",yytext);
return(TOK_IDENTIFIER); }
";" { return(TOK_SEMICOLON);}
"+" { return(TOK_ADD);}
"-" { return(TOK_SUB);}
"*" { return(TOK_MUL);}
"/" { return(TOK_DIV);}
"=" { reurn(TOK_EQUAL);}
[ \n] { }
. { printf("Invalid character '%c', ignored\n", yytext[0]); }
%%
/*int main(){ yylex();
printf(" lexical Analysisfinished ");return 0;}*/
%{
#包括
#包括
#包括“计算表h”
%}
数字([0-9])
字符([a-z])
小案例数字([a-z0-9])
标识符([a-z])(a-z0-9])*
%选项yylineno
%%
“main()”{return(TOK_main);}
{{return(TOK_OPEN_CURLY)}
“}{return(TOK_CLOSE_CURLY);}
“printvar”{return(TOK_printvar);}
“println”{return(TOK_println);}
“int”{return(TOK_int_关键字);}
“float”{return(TOK_float_关键字);}
{digit}+{yylval.int_val=atoi(yytext);
printf(“TOK_NUM_INT\n”);
返回TOK_NUM_INT;}
{digit}+[.]{digit}+{yylval.float_val=atof(yytext);
printf(“TOK_NUM_FLOAT\n”);
返回TOK_NUM_FLOAT;}
{identifier}{yylval.string=strdup(yytext);
printf(“TOK_标识符%s\n”,yytext);
返回(TOK_标识符);}
“;”{返回(TOK_分号);}
“+”{return(TOK_ADD);}
“-”{return(TOK_SUB);}
“*”{return(TOK_MUL);}
“/”{return(TOK_DIV);}
“=”{reurn(TOK_EQUAL);}
[\n]{}
. {printf(“无效字符“%c”,已忽略,\n”,yytext[0]);}
%%
/*int main(){yylex();
printf(“词法分析完成”);返回0;}*/
这是我的野牛档案:
%{
#include <stdio.h>
extern int yylineno;
typedef struct sym_node * smt;
typedef struct sym_node
{
smt *smt;
int type;
char *id_name;
/* data */
}sm_node;
%}
%token TOK_MAIN_BRACKET TOK_OPEN_CURLY TOK_CLOSE_CURLY TOK_PRINTVAR TOK_PRINTLN TOK_INT_KEYWORD TOK_FLOAT_KEYWORD TOK_NUM_INT TOK_NUM_FLOAT TOK_IDENTIFIER TOK_SEMICOLON TOK_ADD
TOK_SUB TOK_MUL TOK_DIV TOK_NUM TOK_EQUAL
%union{
int int_val;
float float_val;
char *string;
struct s_expr
{
int type;
int ival;
float fval;
}struct_expr;
}
%type <int_val> TOK_NUM_INT
%type <float_val> TOK_NUM_FLOAT
%type <string> TOK_IDENTIFIER
%type <struct_expr> expr
%left TOK_ADD TOK_SUB
%left TOK_MUL TOK_DIV
%%
prog: TOK_MAIN TOK_OPEN_CURLY stmts TOK_CLOSE_CURLY
;
stmts:
| stmt TOK_SEMICOLON stmts
;
stmt:
TOK_INT_KEYWORD TOK_IDENTIFIER
| TOK_FLOAT_KEYWORD TOK_IDENTIFIER
| TOK_IDENTIFIER TOK_EQUAL expr
| TOK_PRINTVAR TOK_IDENTIFIER
;
expr:
expr TOK_ADD expr
{
// $$ = $1 + $3;
}
| expr TOK_MUL expr
{
// $$ = $1 * $3;
}
| TOK_NUM_INT
{
// $$ = $1;
}
| TOK_NUM_FLOAT
{
// $$ = $1;
}
;
%%
int yyerror(char *s)
{
printf("\nsyntax error on line no %d\n",yylineno);
return 0;
}
int main()
{
yyparse();
return 0;
}
%{
#包括
外部内部yylineno;
类型定义结构符号节点*smt;
类型定义结构符号节点
{
smt*smt;
int型;
字符*id\u名称;
/*资料*/
}sm_节点;
%}
%token TOK_MAIN TOK_括号TOK_OPEN TOK_CURLY TOK_CLOSE TOK_CURLY TOK_PRINTVAR TOK_PRINTLN TOK_INT TOK_关键字TOK_FLOAT_关键字TOK_NUM_INT TOK_NUM_FLOAT TOK_标识符TOK_分号TOK_ADD
TOK_SUB TOK_MUL TOK_DIV TOK_NUM TOK_EQUAL
%联合{
国际价值;
浮动值;
字符*字符串;
结构s_expr
{
int型;
国际竞争力;
浮动fval;
}结构表达式;
}
%输入TOK_NUM_INT
%类型TOK_NUM_FLOAT
%类型TOK_标识符
%类型表达式
%左TOK_添加TOK_接头
%左托库木尔托库分区
%%
程序:TOK_主TOK_打开_卷曲stmts TOK_关闭_卷曲
;
STMT:
|stmt TOK_分号stmts
;
stmt:
TOK_INT_关键字TOK_标识符
|TOK_FLOAT_关键字TOK_标识符
|TOK_标识符TOK_相等表达式
|TOK_打印变量TOK_标识符
;
表达式:
expr TOK_添加expr
{
// $$ = $1 + $3;
}
|expr TOK_MUL expr
{
// $$ = $1 * $3;
}
|TOK_NUM_INT
{
// $$ = $1;
}
|浮点数
{
// $$ = $1;
}
;
%%
int yyerror(字符*s)
{
printf(“\n第%d行出现语法错误”,yylineno);
返回0;
}
int main()
{
yyparse();
返回0;
}
现在我得到一个错误:
使用符号TOK_MAIN,但未定义为令牌,且没有
规则程序:TOK_MAIN TOK_OPEN_CURLY stmts TOK_CLOSE_CURLY
错误消息告诉您正在使用名为
TOK_MAIN
的令牌,但您从未使用该名称定义令牌。当然,如果您查看%token
行,它包含一个名为TOK_MAIN_BRACKET
,但不是TOK_MAIN
因此,您应该在您的%TOK_MAIN
定义中将其重命名为TOK_MAIN
,或者将TOK_MAIN
替换为TOK_MAIN_括号
(在这种情况下,您也应该相应地更改lexer)
PS:将lex
main()
作为一个令牌有点不寻常。将main
、(
和)
作为各自的代币会更常见。谢谢,这很有效。我已将main,(and)作为单独的标记写入。但在执行时,它仍然显示错误消息:意外标记附近的语法错误“(@shubham)您是否已调整语法,以在main
标记之后使用(
和)
?是的。这就是我所做的:“main”{return(TOK_main);}({return return(TOK_main_OPEN)}”){return(TOK_main_CLOSE)}”@shubham不,我的意思是在解析器中。括号需要在prog
中的TOK_MAIN
之后提到。顺便说一句:您可以使用字符文本来表示单字符标记。然后您可以在lexer中使用return'(';
和return');
和在解析器中使用prog:TOK_MAIN'('''stmnts'
(假设您对卷曲进行相同的更改)。是的,我确实在解析器中提到了括号。prog:TOK_MAIN TOK_MAIN TOK_OPEN TOK_MAIN TOK_CLOSE TOK_OPEN_CURLY stmts TOK_CLOSE_CURLY但我仍然收到相同的错误消息