词法分析器为 yylineno 给出未定义的错误
Lexical analyzer gives undefined error for yylineno
我对编译器设计还很陌生。我正在尝试迈出词法分析器的第一步,尝试 运行 以下代码。
%{
#include <stdlib.h>
#include <stdio.h>
#include "symboltable.h"
#include "tokens.h"
entry_t** symbol_table;
entry_t** constant_table;
int cmnt_strt = 0;
%}
letter [a-zA-Z]
digit [0-9]
ws [ \t\r\f\v]+
identifier (_|{letter})({letter}|{digit}|_){0,31}
hex [0-9a-f]
/* Exclusive states */
%x CMNT
%x PREPROC
%%
/* Keywords*/
"int" {printf("\t%-30s : %3d\n",yytext,INT);}
"long" {printf("\t%-30s : %3d\n",yytext,LONG);}
"long long" {printf("\t%-30s : %3d\n",yytext,LONG_LONG);}
"short" {printf("\t%-30s : %3d\n",yytext,SHORT);}
"signed" {printf("\t%-30s : %3d\n",yytext,SIGNED);}
"unsigned" {printf("\t%-30s : %3d\n",yytext,UNSIGNED);}
"for" {printf("\t%-30s : %3d\n",yytext,FOR);}
"break" {printf("\t%-30s : %3d\n",yytext,BREAK);}
"continue" {printf("\t%-30s : %3d\n",yytext,CONTINUE);}
"if" {printf("\t%-30s : %3d\n",yytext,IF);}
"else" {printf("\t%-30s : %3d\n",yytext,ELSE);}
"return" {printf("\t%-30s : %3d\n",yytext,RETURN);}
{identifier} {printf("\t%-30s : %3d\n", yytext,IDENTIFIER);
insert( symbol_table,yytext,IDENTIFIER );}
{ws} ;
[+\-]?[0][x|X]{hex}+[lLuU]? {printf("\t%-30s : %3d\n", yytext,HEX_CONSTANT);
insert( constant_table,yytext,HEX_CONSTANT);}
[+\-]?{digit}+[lLuU]? {printf("\t%-30s : %3d\n", yytext,DEC_CONSTANT);
insert( constant_table,yytext,DEC_CONSTANT);}
"/*" {cmnt_strt = yylineno; BEGIN CMNT;}
<CMNT>.|{ws} ;
<CMNT>\n {yylineno++;}
<CMNT>"*/" {BEGIN INITIAL;}
<CMNT>"/*" {printf("Line %3d: Nested comments are not valid!\n",yylineno);}
<CMNT><<EOF>> {printf("Line %3d: Unterminated comment\n", cmnt_strt); yyterminate();}
^"#include" {BEGIN PREPROC;}
<PREPROC>"<"[^<>\n]+">" {printf("\t%-30s : %3d\n",yytext,HEADER_FILE);}
<PREPROC>{ws} ;
<PREPROC>\"[^"\n]+\" {printf("\t%-30s : %3d\n",yytext,HEADER_FILE);}
<PREPROC>\n {yylineno++; BEGIN INITIAL;}
<PREPROC>. {printf("Line %3d: Illegal header file format \n",yylineno);}
"//".* ;
\"[^\"\n]*\" {
if(yytext[yyleng-2]=='\') /* check if it was an escaped quote */
{
yyless(yyleng-1); /* push the quote back if it was escaped */
yymore();
}
else
insert( constant_table,yytext,STRING);
}
\"[^\"\n]*$ {printf("Line %3d: Unterminated string %s\n",yylineno,yytext);}
{digit}+({letter}|_)+ {printf("Line %3d: Illegal identifier name %s\n",yylineno,yytext);}
\n {yylineno++;}
"--" {printf("\t%-30s : %3d\n",yytext,DECREMENT);}
"++" {printf("\t%-30s : %3d\n",yytext,INCREMENT);}
"->" {printf("\t%-30s : %3d\n",yytext,PTR_SELECT);}
"&&" {printf("\t%-30s : %3d\n",yytext,LOGICAL_AND);}
"||" {printf("\t%-30s : %3d\n",yytext,LOGICAL_OR);}
"<=" {printf("\t%-30s : %3d\n",yytext,LS_THAN_EQ);}
">=" {printf("\t%-30s : %3d\n",yytext,GR_THAN_EQ);}
"==" {printf("\t%-30s : %3d\n",yytext,EQ);}
"!=" {printf("\t%-30s : %3d\n",yytext,NOT_EQ);}
";" {printf("\t%-30s : %3d\n",yytext,DELIMITER);}
"{" {printf("\t%-30s : %3d\n",yytext,OPEN_BRACES);}
"}" {printf("\t%-30s : %3d\n",yytext,CLOSE_BRACES);}
"," {printf("\t%-30s : %3d\n",yytext,COMMA);}
"=" {printf("\t%-30s : %3d\n",yytext,ASSIGN);}
"(" {printf("\t%-30s : %3d\n",yytext,OPEN_PAR);}
")" {printf("\t%-30s : %3d\n",yytext,CLOSE_PAR);}
"[" {printf("\t%-30s : %3d\n",yytext,OPEN_SQ_BRKT);}
"]" {printf("\t%-30s : %3d\n",yytext,CLOSE_SQ_BRKT);}
"-" {printf("\t%-30s : %3d\n",yytext,MINUS);}
"+" {printf("\t%-30s : %3d\n",yytext,PLUS);}
"*" {printf("\t%-30s : %3d\n",yytext,STAR);}
"/" {printf("\t%-30s : %3d\n",yytext,FW_SLASH);}
"%" {printf("\t%-30s : %3d\n",yytext,MODULO);}
"<" {printf("\t%-30s : %3d\n",yytext,LS_THAN);}
">" {printf("\t%-30s : %3d\n",yytext,GR_THAN);}
. {printf("Line %3d: Illegal character %s\n",yylineno,yytext);}
%%
int yywrap(){ return 1;}
int main()
{
yyin=fopen("testcases/test-case-1.c","r");
symbol_table=create_table();
constant_table=create_table();
yylex();
printf("\n\tSymbol table");
display(symbol_table);
printf("\n\tConstants Table");
display(constant_table);
printf("NOTE: Please refer tokens.h for token meanings\n");
}
我尝试 运行 它使用:
flex lexer.l
gcc lex.yy.c -o lexrun
这给了我一个错误,因为
lexer.l: In function 'yylex':
lexer.l:46:14: error: 'yylineno' undeclared (first use in this function)
"/*" {cmnt_strt = yylineno; BEGIN CMNT;}
^~~~~~~~
lexer.l:46:14: note: each undeclared identifier is reported only once for each function it appears in
我在网上尝试了很多东西,比如添加
extern int yylineno;
这开始出现另一个错误
undefined reference to `yylineno'
我已经安装了 Flex 版本 2.5.4 并且 运行 在 Vscode 中安装了这个。
任何克服这一问题的澄清将不胜感激。提前致谢。
如果你想让 flex 跟踪你需要添加的行号
%option yylineno
你的 flex 序言。
我还建议如下:
-
%option noinput nounput
这将允许您在没有编译器警告的情况下编译生成的扫描器(Always 使用 -Wall
编译,甚至生成的代码,并修复报告的任何警告。)
-
%option noyywrap
这避免了定义 yywrap
的需要
-
%option nodefualt
如果您没有针对每个可能的输入的规则,它会警告您。
最后一点,extern int yylineno;
不起作用,因为 extern
表示“此变量在不同的翻译单元中定义”,并且您的代码中没有其他翻译单元。我假设您在讨论旨在与扫描仪链接在一起的不同文件时发现了这一点。 (如果您发现的地方建议将 extern
声明放在 .l
文件中,您需要将其作为信息来源丢弃。)
如果这是您第一次尝试使用多个源文件编写 C 应用程序,您可能应该花几分钟时间回顾一下如何在 C 中链接多个文件。这将为您节省很多后来的挫败感。
我对编译器设计还很陌生。我正在尝试迈出词法分析器的第一步,尝试 运行 以下代码。
%{
#include <stdlib.h>
#include <stdio.h>
#include "symboltable.h"
#include "tokens.h"
entry_t** symbol_table;
entry_t** constant_table;
int cmnt_strt = 0;
%}
letter [a-zA-Z]
digit [0-9]
ws [ \t\r\f\v]+
identifier (_|{letter})({letter}|{digit}|_){0,31}
hex [0-9a-f]
/* Exclusive states */
%x CMNT
%x PREPROC
%%
/* Keywords*/
"int" {printf("\t%-30s : %3d\n",yytext,INT);}
"long" {printf("\t%-30s : %3d\n",yytext,LONG);}
"long long" {printf("\t%-30s : %3d\n",yytext,LONG_LONG);}
"short" {printf("\t%-30s : %3d\n",yytext,SHORT);}
"signed" {printf("\t%-30s : %3d\n",yytext,SIGNED);}
"unsigned" {printf("\t%-30s : %3d\n",yytext,UNSIGNED);}
"for" {printf("\t%-30s : %3d\n",yytext,FOR);}
"break" {printf("\t%-30s : %3d\n",yytext,BREAK);}
"continue" {printf("\t%-30s : %3d\n",yytext,CONTINUE);}
"if" {printf("\t%-30s : %3d\n",yytext,IF);}
"else" {printf("\t%-30s : %3d\n",yytext,ELSE);}
"return" {printf("\t%-30s : %3d\n",yytext,RETURN);}
{identifier} {printf("\t%-30s : %3d\n", yytext,IDENTIFIER);
insert( symbol_table,yytext,IDENTIFIER );}
{ws} ;
[+\-]?[0][x|X]{hex}+[lLuU]? {printf("\t%-30s : %3d\n", yytext,HEX_CONSTANT);
insert( constant_table,yytext,HEX_CONSTANT);}
[+\-]?{digit}+[lLuU]? {printf("\t%-30s : %3d\n", yytext,DEC_CONSTANT);
insert( constant_table,yytext,DEC_CONSTANT);}
"/*" {cmnt_strt = yylineno; BEGIN CMNT;}
<CMNT>.|{ws} ;
<CMNT>\n {yylineno++;}
<CMNT>"*/" {BEGIN INITIAL;}
<CMNT>"/*" {printf("Line %3d: Nested comments are not valid!\n",yylineno);}
<CMNT><<EOF>> {printf("Line %3d: Unterminated comment\n", cmnt_strt); yyterminate();}
^"#include" {BEGIN PREPROC;}
<PREPROC>"<"[^<>\n]+">" {printf("\t%-30s : %3d\n",yytext,HEADER_FILE);}
<PREPROC>{ws} ;
<PREPROC>\"[^"\n]+\" {printf("\t%-30s : %3d\n",yytext,HEADER_FILE);}
<PREPROC>\n {yylineno++; BEGIN INITIAL;}
<PREPROC>. {printf("Line %3d: Illegal header file format \n",yylineno);}
"//".* ;
\"[^\"\n]*\" {
if(yytext[yyleng-2]=='\') /* check if it was an escaped quote */
{
yyless(yyleng-1); /* push the quote back if it was escaped */
yymore();
}
else
insert( constant_table,yytext,STRING);
}
\"[^\"\n]*$ {printf("Line %3d: Unterminated string %s\n",yylineno,yytext);}
{digit}+({letter}|_)+ {printf("Line %3d: Illegal identifier name %s\n",yylineno,yytext);}
\n {yylineno++;}
"--" {printf("\t%-30s : %3d\n",yytext,DECREMENT);}
"++" {printf("\t%-30s : %3d\n",yytext,INCREMENT);}
"->" {printf("\t%-30s : %3d\n",yytext,PTR_SELECT);}
"&&" {printf("\t%-30s : %3d\n",yytext,LOGICAL_AND);}
"||" {printf("\t%-30s : %3d\n",yytext,LOGICAL_OR);}
"<=" {printf("\t%-30s : %3d\n",yytext,LS_THAN_EQ);}
">=" {printf("\t%-30s : %3d\n",yytext,GR_THAN_EQ);}
"==" {printf("\t%-30s : %3d\n",yytext,EQ);}
"!=" {printf("\t%-30s : %3d\n",yytext,NOT_EQ);}
";" {printf("\t%-30s : %3d\n",yytext,DELIMITER);}
"{" {printf("\t%-30s : %3d\n",yytext,OPEN_BRACES);}
"}" {printf("\t%-30s : %3d\n",yytext,CLOSE_BRACES);}
"," {printf("\t%-30s : %3d\n",yytext,COMMA);}
"=" {printf("\t%-30s : %3d\n",yytext,ASSIGN);}
"(" {printf("\t%-30s : %3d\n",yytext,OPEN_PAR);}
")" {printf("\t%-30s : %3d\n",yytext,CLOSE_PAR);}
"[" {printf("\t%-30s : %3d\n",yytext,OPEN_SQ_BRKT);}
"]" {printf("\t%-30s : %3d\n",yytext,CLOSE_SQ_BRKT);}
"-" {printf("\t%-30s : %3d\n",yytext,MINUS);}
"+" {printf("\t%-30s : %3d\n",yytext,PLUS);}
"*" {printf("\t%-30s : %3d\n",yytext,STAR);}
"/" {printf("\t%-30s : %3d\n",yytext,FW_SLASH);}
"%" {printf("\t%-30s : %3d\n",yytext,MODULO);}
"<" {printf("\t%-30s : %3d\n",yytext,LS_THAN);}
">" {printf("\t%-30s : %3d\n",yytext,GR_THAN);}
. {printf("Line %3d: Illegal character %s\n",yylineno,yytext);}
%%
int yywrap(){ return 1;}
int main()
{
yyin=fopen("testcases/test-case-1.c","r");
symbol_table=create_table();
constant_table=create_table();
yylex();
printf("\n\tSymbol table");
display(symbol_table);
printf("\n\tConstants Table");
display(constant_table);
printf("NOTE: Please refer tokens.h for token meanings\n");
}
我尝试 运行 它使用:
flex lexer.l
gcc lex.yy.c -o lexrun
这给了我一个错误,因为
lexer.l: In function 'yylex':
lexer.l:46:14: error: 'yylineno' undeclared (first use in this function)
"/*" {cmnt_strt = yylineno; BEGIN CMNT;}
^~~~~~~~
lexer.l:46:14: note: each undeclared identifier is reported only once for each function it appears in
我在网上尝试了很多东西,比如添加
extern int yylineno;
这开始出现另一个错误
undefined reference to `yylineno'
我已经安装了 Flex 版本 2.5.4 并且 运行 在 Vscode 中安装了这个。 任何克服这一问题的澄清将不胜感激。提前致谢。
如果你想让 flex 跟踪你需要添加的行号
%option yylineno
你的 flex 序言。
我还建议如下:
-
%option noinput nounput
这将允许您在没有编译器警告的情况下编译生成的扫描器(Always 使用
-Wall
编译,甚至生成的代码,并修复报告的任何警告。) -
%option noyywrap
这避免了定义
的需要yywrap
-
%option nodefualt
如果您没有针对每个可能的输入的规则,它会警告您。
最后一点,extern int yylineno;
不起作用,因为 extern
表示“此变量在不同的翻译单元中定义”,并且您的代码中没有其他翻译单元。我假设您在讨论旨在与扫描仪链接在一起的不同文件时发现了这一点。 (如果您发现的地方建议将 extern
声明放在 .l
文件中,您需要将其作为信息来源丢弃。)
如果这是您第一次尝试使用多个源文件编写 C 应用程序,您可能应该花几分钟时间回顾一下如何在 C 中链接多个文件。这将为您节省很多后来的挫败感。