Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Linux 用于生成文件的Lex analyzer不生成包含词法错误消息的程序列表_Linux_Ubuntu_Compiler Construction_Flex Lexer_Lex - Fatal编程技术网

Linux 用于生成文件的Lex analyzer不生成包含词法错误消息的程序列表

Linux 用于生成文件的Lex analyzer不生成包含词法错误消息的程序列表,linux,ubuntu,compiler-construction,flex-lexer,lex,Linux,Ubuntu,Compiler Construction,Flex Lexer,Lex,我正在尝试构建一个lex分析器,该分析器生成一个程序列表,其中的词法错误消息包含在它们出现的行之后。换句话说,如果读取的字符无法启动令牌,则将其视为错误。它还应该生成一个包含lexeme令牌对的文件,以便验证分析器是否工作。我可以得到一个输出文件,但它不能正常工作,因为当我试图运行它时,它只会给我一个命令屏幕,就像我在文件中工作一样。以下是用于读取输入文本的扫描仪文件的代码: %{ #include <stdio.h> #include <ctype.h> #inc

我正在尝试构建一个lex分析器,该分析器生成一个程序列表,其中的词法错误消息包含在它们出现的行之后。换句话说,如果读取的字符无法启动令牌,则将其视为错误。它还应该生成一个包含lexeme令牌对的文件,以便验证分析器是否工作。我可以得到一个输出文件,但它不能正常工作,因为当我试图运行它时,它只会给我一个命令屏幕,就像我在文件中工作一样。以下是用于读取输入文本的扫描仪文件的代码:

%{
#include <stdio.h> 
#include <ctype.h>  
#include "tokens.h"

void toTitle(char* yytext, int yyleng);
%}

%option noyywrap 

ws      [ \t\r\n]+
quoted      \".*\"
letter      [A-Za-z]
digit       [0-9]
word        {letter}+(\-{letter}+)?
number      {digit}+
punc        [,:;()] 
begin       { ECHO; return(begin);}  
boolean     { ECHO; return(BOOLEAN);}    
else        { ECHO; return(ELSE); }     
end     { ECHO; return(END); }      
endif       void toTitle(char* yytext, int yyleng){ ECHO; return(ENDIF); }        
function    { ECHO; return(FUNCTION); }     
if      { ECHO; return(IF); }       
is      { ECHO; return(IS); }       
integer     { ECHO; return(INTEGER); }      
real        { ECHO; return(REAL); }     
returns     { ECHO; return(RETURNS); }         
then        { ECHO; return(THEN); }
line        [\n]  

%%

"&&"                    { return(LOGOPAND); }                   
"||"                    { return(LOGOPOR); }                           
"!="                    { return(LOGOPNOT); }   
[ \t\n]                 ;
{ws}                    { ECHO; }                          
"<"                     { ECHO; return(RELOP); } 
"="                     { ECHO; return(RELOP); } 
"/="                    { ECHO; return(RELOP); } 
">"                     { ECHO; return(RELOP); } 
">="                    { ECHO; return(RELOP); } 
"<="                    { ECHO; return(RELOP); }
"*"                     { ECHO; return(MULTOP); } 
"/"                     { ECHO; return(MULTOP); }  
"+"                     { ECHO; return(ADDOP); }      
"-"                     { ECHO; return(ADDOP); }
"true"                  { ECHO; return(BOOLLITERAL); }          
"false"                 { ECHO; return(BOOLLITERAL); }  
{digit}                 { ECHO; return(I_LITERAL); } 
{digit}+"."{digit}*             { ECHO; return(R_LITERAL); } 
begins                  { ECHO; return(BEGINS); }  
{punc}                  { ECHO; return yytext[0]; }   
{quoted}            { ECHO; }
{word}              {toTitle(yytext, yyleng); }
{number}            { ECHO; }

%%

void toTitle(char* yytext, int yyleng)
{

}

void tokenCount(int token)
{
    while (token = yylex())
        fprintf(yyout, "%d %s\n", token, yytext);
}

int main() {
while (yylex());
    return 0;

}
我的输出应该是这样的:

   1  -- Simple program with one function
   2
   3  function main a: integer returns integer;
   4      b: integer is a * 2;
   5  begin
   6      if a <= 0 then
   7          b + b;
   8      else
   9    b * b;
  10      endif;
  11  end;

Compiled Successfully
1——具有一个函数的简单程序
2.
3函数主a:整数返回整数;
4b:整数是a*2;
5开始

6如果a我注意到这是您针对同一问题提出的第三个问题,并且怀疑您可能不完全理解如何完成此任务,或者您迄今为止看到的文档和答案。Stackoverflow提供了关于形成问题的最佳方式的指导和标准,以从这里的许多世界级专家那里获得最佳价值和服务,例如:。我知道你可能是这方面的初学者,就你的问题而言,学习对你是有利的。我将以您的代码为例,演示如何简化问题,从而获得对问题和最终解决方案的良好描述

代码的问题与@rici在您的“该lex文件看起来像是使用不同样式从随机片段粘贴到一起”的注释中指出的问题相同

让我们回到第页,看看flex程序的总体结构:

     definitions
     %%
     rules
     %%
     user code
%%
行的位置将代码分为三个部分,因此您在
%%
之前放置的内容和在
%%
之后放置的内容非常重要

现在@nlu在回答你最后一个问题时写道:

ECHO是一个特殊语句,只能在actions部分使用

然后你回答说:

我通过将所有保留字及其操作移到
%%
语法之前的第一部分来更正代码

不幸的是,您误读了该建议,并在声明部分留下了规则/操作部分的代码。不幸的是,这并没有导致flex向您提供任何有用的消息,因为它仍然是一个有意义的flex程序;只是不是你期待的那个

为了澄清,您不能在第一个
%%
之前执行任何操作,包括
回显
,因为这样它将位于定义部分。它们必须在第一个
%%
之后,因此位于规则/操作部分。因此,所有这些线路都位于错误的位置:

begin       { ECHO; return(begin);}  
boolean     { ECHO; return(BOOLEAN);}    
else        { ECHO; return(ELSE); }     
end     { ECHO; return(END); }      
endif       void toTitle(char* yytext, int yyleng){ ECHO; return(ENDIF); }        
function    { ECHO; return(FUNCTION); }     
if      { ECHO; return(IF); }       
is      { ECHO; return(IS); }       
integer     { ECHO; return(INTEGER); }      
real        { ECHO; return(REAL); }     
returns     { ECHO; return(RETURNS); }         
then        { ECHO; return(THEN); }
你怎么能自己调试呢?正如其在SO帮助页面中所建议的:简化。我将举例说明如何做到这一点。如果您将问题简化为只有一个关键字的语言,让我们说
begin
和一些空格,并删除所有其他关键字和符号的所有其他行,那么将有一个更简单的问题需要解决。让我们在您的代码中尝试以下操作:

%option noyywrap 

ws      [ \t\r\n]+    
begin       { ECHO; return(begin);} 
line        [\n]
%%
[ \t\n]                 ;
{ws}                    { ECHO; }  
begins                  { ECHO; return(BEGINS); } 
%%

int main() {
while (yylex());
return 0;
}
您会注意到,我刚刚删除了所有与其他关键字和符号相关的行,因为它们将图片与一堆额外的行混淆。这正是专家和专业程序员在解决日常问题时所做的。你认为我们没有找到虫子的灵媒吗?:-)这是伴随着练习而来的技能

现在,专注于这个更简单的程序,我们可以看到一些东西。顺便说一下,它确实可以编译和运行,而且它的所有代码都是您的(只是更简单)。如果我们运行它,关键字
begins
会得到
ECHO
ed,但关键字
begin
不会。这里有一个线索。如果将
开始
的行移到
%%
的下方,它将与
开始
行一样工作。但是为什么flex接受了这个糟糕的程序而没有给你一个有用的错误呢?这是因为根据flex正则表达式表示法,该行仍然是词素的有效定义。您定义的是一个名为
begin
(使用规则部分中的符号
{begin}
访问)的词素,它被定义为与字符串
“{ECHO;return(begin);}”匹配。但是,由于您从未键入该字符串,也从未使用过名称
{begin}
,因此该定义片段从未被使用

还有一个问题:你的语言真的有一个名为
begin
的关键字和另一个名为
begins
的关键字吗。我觉得很可疑。也许是另一个bug? 同样,我们可以看到同样的空白。您已尝试在三个位置匹配换行符
\n
。这会令人困惑,因为您无法确定遇到换行符时flex将执行哪些定义和操作。由于您希望在某个点对行进行编号,这可能会给您带来问题。您还告诉它忽略和
ECHO
whitespace。是哪一个?它不能两者兼而有之。从您的示例输出中,您可能希望它们得到响应。对简单的程序进行所有这些修复,我们得到以下结果:

%option noyywrap 

ws                      [ \t\r]+  
line                    [\n]    
%%
{ws}                    { ECHO; }  
begin                   { ECHO; return(BEGIN); } 
%%

int main() {
while (yylex());
return 0;
}
它适用于只包含关键字
begin
的简单语言。我们现在所要做的就是慢慢地、小心地把其他部分放回去。接下来,让我们将关键字
endif
添加到代码中,我们得到:

%option noyywrap 

ws                      [ \t\r]+  
line                    [\n]    
%%
{ws}                    { ECHO; }  
begin                   { ECHO; return(BEGIN); } 
endif       void toTitle(char* yytext, int yyleng){ ECHO; return(ENDIF); }
%%

int main() {
while (yylex());
return 0;
}
但是,此不会编译。当您从其他人的计算机上对代码进行黑客攻击时,这段代码
void-toTitle(char*yytext,int-yyleng)
看起来像是错误的粘贴
%option noyywrap 

ws                      [ \t\r]+  
line                    [\n]    
%%
{ws}                    { ECHO; }  
begin                   { ECHO; return(BEGIN); } 
endif       void toTitle(char* yytext, int yyleng){ ECHO; return(ENDIF); }
%%

int main() {
while (yylex());
return 0;
}