C++ Flex/bison,错误:未声明

C++ Flex/bison,错误:未声明,c++,yacc,bison,lex,lexical-analysis,C++,Yacc,Bison,Lex,Lexical Analysis,你好, 我有一个问题,下面的程序返回了一个错误,error::Undeclared(函数中的首次使用),为什么会出现此错误所有令牌都已声明,但此错误出现了,有人能帮助我吗,这是lex和yac文件。谢谢 法律: %{ int yylinenu=1; int-yycolno=1; %} %x染色体 数字[0-9] α[a-zA-Z] ID{ALPHA}({ALPHA}({ALPHA}{DIGIT}))*\ux? 分组数({DIGIT}{1,3})(\.{DIGIT}{3})* 简单数{位数}+ NU

你好, 我有一个问题,下面的程序返回了一个错误,error::Undeclared(函数中的首次使用),为什么会出现此错误所有令牌都已声明,但此错误出现了,有人能帮助我吗,这是lex和yac文件。谢谢

法律:

%{
int yylinenu=1;
int-yycolno=1;
%}
%x染色体
数字[0-9]
α[a-zA-Z]
ID{ALPHA}({ALPHA}({ALPHA}{DIGIT}))*\ux?
分组数({DIGIT}{1,3})(\.{DIGIT}{3})*
简单数{位数}+
NUMMER{GROUPED_NUMBER}}{SIMPLE_NUMBER}
%%
{
[\n]{++yylinenu;yycolno=1;}
[]+{yycolno=yycolno+yyleng;}
[\t]+{yycolno=yycolno+(yyleng*8);}
“*”{return MAL;}
“+”{return PLUS;}
“-”{返回减号;}
“/”{返回斜杠;}
“({return linkammer;}
“{return rechteklamer;}”
“{return linkeeschweifteklamer;}
“}”{return rechtegescheifteklamer;}
“=”{return GLEICH;}
“==”{return GLEICHVERGLEICH;}
“!=”{返回UNGLEICH;}
“{return GROSSER;}
“=”{return GROSSERGLEICH;}
“while”{返回while;}
“if”{返回if;}
“else”{return else;}
“printf”{返回printf;}
“;”{return SEMIKOLON;}
\/\/[^\n]*{;}
{NUMMER}{返回号码;}
{ID}{返回标识符;}
\“{BEGIN(STR);}
.                         {;} 
}
{ 
\n{++yylinenu;yycolno=1;}
([^\“\\]\\\”\\t“\\”\\n“\\\”\\r“\\\”\\b“\\\”)+{return STRING;}
\“{开始(首字母);}
}
%%
yywrap()
{
}
雅克:

%{
#包括stdio.h>
#包括字符串。h>
#包括“lex.yy.c”
无效错误(字符*错误);
int error=0,linecnt=1;
%}
%令牌标识符编号字符串注释加减MAL斜杠LinkedKlammer RECHTEKLAMMER LinkedgeschweifteKlammer RECHTEGESCHEIFTEKLAMMER GLEICH GLEICH GLEICH GLEICH GLEICH GLEICH GROSSER KLEINER Grossergeich KLEINERGLEICH KLEINERGLEICH如果其他,而PRINTF SEMIKOLON
%启动STMT
%%
Stmts:Stmt
{puts(“\t\tStmts:Stmt”);}
|Stmt
{puts(“\t\tStmts:Stmt Stmts”);}
; //新雷格尔----------------------------------------------
Stmt:Linkedgeschweifteklamer Stmts RechtegeScheifteklamer
{puts(“\t\tStmt:'{'Stmts'}'”;}
|IF LinkedKlamer Cond Rechteklamer Stmt
{puts(“\t\tStmt:”(“Cond”)“Stmt”);}
|如果linkammer Cond RECHTEKLAMMER Stmt ELSE Stmt
{puts(“\t\tStmt:”(“Cond”)“Stmt”或“Stmt”);}
|而LinkedKlamer Cond rechteklamer Stmt
{puts(“\t\tStmt:'PRINTF'Expr';'”);}
|PRINTF Expr SEMIKOLON
{puts(“\t\tStmt:'PRINTF'Expr';'”);}
|标识符GLEICH Expr SEMIKOLON
{puts(“\t\tStmt:'标识符'='Expr';'”);}
|塞米科隆
{puts(“\t\tStmt:';'”);}
;//新雷格尔---------------------------------------------
条件:Expr GLEICHVERGLEICH Expr
{puts(“\t\t命令:'='Expr”);}
|Expr UNGLEICH Expr
{put(“\t\t命令:'!='Expr”);}
|克莱纳快递
{puts(“\t\t命令:'='Expr”);}
;//新雷格尔--------------------------------------------
表达式:术语
{puts(“\t\tExpr:Term”);}
|术语加表达式
{puts(“\t\tExpr:Term'+'Expr”);}
|负项表达式
{puts(“\t\tExpr:Term'-'Expr”);}
;//新雷格尔--------------------------------------------
术语:因子
{put(“\t\tTerm:Factor”);}
|因子马尔项
{puts(“\t\tTerm:Factor'*'Term”);}
|因子斜杠项
{puts(“\t\tTerm:Factor'/'Term”);}
;//新雷格尔--------------------------------------------
因子:SimpleExpr
{puts(“\t\t因素:SimpleExpr”);}
|负SimpleExpr
{puts(“\t\t因素:'-'SimpleExpr”);}
;//新雷格尔--------------------------------------------
SimpleExpr:LinkedKlamer Expr Rechteklamer
{puts(“\t\t简单表达式:'('Expr')”);}
|标识符
{puts(“\t\tSimpleExpr:'标识符'”;}
|数
{puts(“\t\tSimpleExpr:'NUMBER'”;}
|串
{puts(“\t\tSimpleExpr:'String'”;}
;//恩德-------------------------------------------------
%%
无效错误(字符*消息)
{
误差=1;
printf(“行:%d,列:%d:%s\n”,yylinenu,yycolno,yytext,msg);
}
int main(int argc,char*argv[])
{
int-val;
while(yylex())
{       
printf(“\n”,yytext);
}
返回yyparse();
}

您的主要问题是试图将lexer包含到解析器中。您(至少在正常情况下)希望使用
yacc-d
,让yacc(野牛,如果必须的话)生成一个头部(y.tab.h),并将其包含在您的lexer中

lexer的启动:

%{
#include "y.tab.h"
int yylinenu= 1;
int yycolno= 1;
%}
// ...
由于解析器引用了上面定义的变量,因此您将在解析器源文件中声明than:

extern int yylinenu;
extern int yycolno;
你的
main()
error()
也有点乱(你的
main()
看起来像是在玩弄弄弄弄弄明白到底发生了什么…)

除此之外,你的语法还有一两个小细节,我很确定这不是你真正想要的。例如:

|WHILE LINKEKLAMMER Cond RECHTEKLAMMER Stmt 
    {puts("\t\tStmt : 'PRINTF' Expr ';'");}
|PRINTF Expr SEMIKOLON  
    {puts("\t\tStmt : 'PRINTF' Expr ';'");}
假设您匹配了一个“while”,您想打印“while”,而不是“printf”:

同样,在:

|IF LINKEKLAMMER Cond RECHTEKLAMMER Stmt    
    {puts("\t\tStmt : '(' Cond ')' Stmt");}
|IF LINKEKLAMMER Cond RECHTEKLAMMER Stmt  ELSE Stmt 
    {puts("\t\tStmt : '(' Cond ')' Stmt 'ELSE' Stmt");}
我猜你可能想在每一页的开头打印一个“如果”:

|IF LINKEKLAMMER Cond RECHTEKLAMMER Stmt    
    {puts("\t\tStmt : 'IF' '(' Cond ')' Stmt");}
|IF LINKEKLAMMER Cond RECHTEKLAMMER Stmt  ELSE Stmt 
    {puts("\t\tStmt : 'IF' '(' Cond ')' Stmt 'ELSE' Stmt");}
最后,我建议您使用缩进和空行,这样您的语法规则将如下所示:

Term:Factor                 {puts("\t\tTerm : Factor");}
    | Factor MAL Term       {puts("\t\tTerm : Factor '*' Term");}
    | Factor SLASH Term     {puts("\t\tTerm : Factor '/' Term");}
    ;

Factor:SimpleExpr           {puts("\t\tFactor : SimpleExpr");}
    | MINUS SimpleExpr      {puts("\t\tFactor : '-' SimpleExpr");}
    ;
当然,您可以改变这一点,例如将操作放在单独的行上(特别是如果它们很长的话),但总体思路保持不变。你不应该真的需要注释来判断一条规则的结束和另一条规则的开始——格式化可以使这一点变得明显

编辑:我忘了提到另一点:对于自底向上的解析器(如bison/yacc/byacc-generate),左递归通常是pr
|WHILE LINKEKLAMMER Cond RECHTEKLAMMER Stmt 
    {puts("\t\tStmt : 'WHILE' Expr ';'");}
|IF LINKEKLAMMER Cond RECHTEKLAMMER Stmt    
    {puts("\t\tStmt : '(' Cond ')' Stmt");}
|IF LINKEKLAMMER Cond RECHTEKLAMMER Stmt  ELSE Stmt 
    {puts("\t\tStmt : '(' Cond ')' Stmt 'ELSE' Stmt");}
|IF LINKEKLAMMER Cond RECHTEKLAMMER Stmt    
    {puts("\t\tStmt : 'IF' '(' Cond ')' Stmt");}
|IF LINKEKLAMMER Cond RECHTEKLAMMER Stmt  ELSE Stmt 
    {puts("\t\tStmt : 'IF' '(' Cond ')' Stmt 'ELSE' Stmt");}
Term:Factor                 {puts("\t\tTerm : Factor");}
    | Factor MAL Term       {puts("\t\tTerm : Factor '*' Term");}
    | Factor SLASH Term     {puts("\t\tTerm : Factor '/' Term");}
    ;

Factor:SimpleExpr           {puts("\t\tFactor : SimpleExpr");}
    | MINUS SimpleExpr      {puts("\t\tFactor : '-' SimpleExpr");}
    ;
Stmts : Stmt                {puts("\t\tStmts : Stmt");}
    | Stmt Stmts            {puts("\t\tStmts : Stmt Stmts");}
    ;
Stmts : Stmt                {puts("\t\tStmts : Stmt");}
    | Stmts Stmt            {puts("\t\tStmts : Stmts Stmt");}
    ;
:L1
IF FLAG AND X"0001"
EVT 23;
ELSE
WAIT 500 ms;
JMP L1;
END IF;