如何解决无法识别的规则和致命的解析错误

问题描述 投票:0回答:1

我对 lex 很陌生,并尝试制作扫描仪。这是我的代码:

定义与规则部分

identifier              ([A-Za-z][0-9A-Za-z]*)
digit                   ([0-9])
integer                 ({digit}+)
float           ({integer}"."[0-9]+)
delimiter               ([.,:;()\[\]{}])
arithmetic              ([+-*/])
relational              ([<>=])
string                  (\"(\"\"|[^"\n])*\")
commentLine     (\%[^\n]*)
commentLeft     ({%)
commentRight        (%})

%x COMMENT

%option noyywrap

%%

 {delimiter;}       {tokenChar(yytext[0]);}
 {arithmetic;}      {tokenChar(yytext[0]);}
 {relational;}      {tokenChar(yytext[0]);}

"<="                    { token('<='); }
">="                    { token('>='); }
"not="                  { token('not='); }
":="            { token(':='); }

"not"                   { token('not'); }
"and"                   { token('and'); }
"or"                    { token('or'); }

"array"                 { token(ARRAY); }
"begin"                 { token(BEGIN); }
"bool"                  { token(BOOL); }
"char"                  { token(CHAR); }
"const"                 { token(CONST); }
"decreasing"            { token(DECREASING); }
"default"               { token(DEFAULT); }
"do"                    { token(DO); }
"else"                  { token(ELSE); }
"end"                   { token(END); }
"exit"                  { token(EXIT); }
"false"                 { token(FALSE); }
"for"                   { token(FOR); }
"function"              { token(FUNCTION); }
"get"                   { token(GET); }
"if"                    { token(IF); }
"int"                   { token(INT); }
"loop"                  { token(LOOP); }
"of"                    { token(OF); }
"put"                   { token(PUT); }
"procedure"             { token(PROCEDURE); }
"real"                  { token(REAL); }
"result"                { token(RESULT); }
"return"                { token(RETURN); }
"skip"                  { token(SKIP); }
"string"                { token(STRING); }
"then"                  { token(THEN); }
"true"                  { token(TRUE); }
"var"                   { token(VAR); }
"when"                  { token(WHEN); }

 {integer}  {
    tokenInteger("integer", atoi(yytext));
}

 {identifier} {
    tokenString("identifier", yytext);
    table -> insert(yytext);
}

 {float}    {
    tokenFloat("float", yytext);
 }

 {string}    {
    char s[MAX_LINE_LENG] = {0};
    int idx = 0;
    for (int i = 1; i < yyleng - 1; ++i){
        if (yytext[i] == '"')
            ++i;
        s[idx++] = yytext[i];
    }
    tokenString("string", s);
}

 {commentLine}  {
    LIST;
}

 {% { 
    LIST;
    BEGIN(COMMENT);
}

<COMMENT>[^\n]  {
    LIST;
}

<COMMENT>\n {   
    LIST;
    printf("%d: %s", linenum, buf);
    linenum++;
    buf[0] = '\0';
}

<COMMENT> {commentRight}    {
        LIST;
        BEGIN(INITIAL);
    }

\n  {
    LIST;
    printf("%d: %s", linenum++, buf);
    buf[0] = '\0';
}

[ \t]*  {
    LIST;
}

.   {
    LIST;
    printf("%d:%s\n", linenum+1, buf);
    printf("bad character:'%s'\n",yytext);
    exit(-1);
}
%%

主要功能:

int main(int argc, char **argv){
    FILE *yyin;
    if (argc > 0){
        yyin = fopen(argv[1], "r");
        if (!yyin){
            printf("Failed to open file %s\n", argv[1]);
            return 1;
        }
    }
    yylex();
    fclose(yyin);
    return 0;
}

既然还在尝试,应该会有不少失误。然而,当我输入

lex scanner.l
时,它只会说:

scanner.l:209: 无法识别的规则
scanner.l:209: 致命解析错误

第 209 行是规则部分之后的

%%
。我的定义不正确吗?不知道错在哪里。

cygwin lex
1个回答
2
投票

你的文件中出现了不少新手错误,都是错别字。调试此类问题的最佳方法是从代码中删除行,直到错误消失(可能使用二进制斩波方法)。这样做你会很快准确地找到哪些线路导致了问题。我不会列出你犯的每一个错误,但我可以在几分钟内很容易地在 lex/flex 中完成这项工作。

我发现的错误是:

  • lex 模式必须从第一列开始。你们中的一些人在他们之前有一个空间。
  • lex 动作规则不能在第一列。你们中的一些人确实在第一列中有字符(特别是当它是结束语时 })。
  • } 是 lex 元字符(意味着它是 lex 语法的一部分)。这意味着在您的模式中使用它时必须小心。当 } 应该与自身匹配时,您应该使用 \ 转义。在几个地方你没有。
  • 减号-也是字符集中的lex元字符。如果集合要匹配实际的 - 并且不表示字符范围,那么它也必须通过 \.
  • 进行转义
  • 你把分号;放在一个模式的名字里,这是不正确的。例如
    {delimiter;}
    .
  • Lex 认为您有两个可能的匹配换行符 .仔细检查。

然而,你犯的最大错误,也是很多学生犯的最大错误,就是试图一次完成所有事情。很差。有经验的软件工程师知道一次只做一件事情。从你的语言的一小部分开始,让它工作,然后添加更多的语句并继续,直到它全部工作。也许从运算符或关键字开始,然后逐步添加其他部分。然后你就知道错误在哪里了。这就是为什么 Stack Overflow 喜欢可重现的小例子而不是整个代码库。

© www.soinside.com 2019 - 2024. All rights reserved.