无法识别的规则错误

时间:2013-04-04 18:07:25

标签: lex flex-lexer

    %option lex-compat
    %option noyywrap
    %option yylineno
    %{
    #include<stdio.h>
    #include<conio.h>
    #include<stdlib.h>
    #include<string.h>
    %}
    %{
    int INDENT=0,DEDENT=0,line=0;
    %}
    HASH    "#"
    NEWL    [\n]
    SPACE   " "
    MULTS   """
    COMP    "e^"
    LETTER  ([a-zA-Z])
    HEXL    ([a-fA-F1-9])
    ZERO    "0"
    EXP     "10^"
    COLON   ":"
    DOT     "."
    LPAREN  "("
    RPAREN  ")"
    PLUS    "+"
    MINUS   "-"
    SIGN    ({PLUS}|{MINUS})
    MULT    "*"
    DIV     "/"
    ASSIGN  "="
    EQUAL   "=="
    MORE_THAN ">"
    LESS_THAN "<"
    OR      "or"
    AND     "and"
    NOT     "not"
    IF      "if"
    ELSE    "else"
    LAMBDA  "lambda"
    FOR     "for"
    PASS    "pass"
    H       ({"h"|"H"})
    WHITESPACE  {[\t\n]}
    NUM_NZ      [1-9]
    NUM         [0-9]
    INTEGER     ({SIGN}?({ZERO}|({ZERO}+/({NUM_NZ}+))))
    REAL        ({INTEGER}{DOT}{NUM}|{INTEGER}{DOT}{NUM}{EXP}{INTEGER})
    HEX         ({PLUS}?(ZERO}|{HEXL}+{H}))
    COMPLEX     ({PLUS}?{REAL}+{COMP}{SIGN}?(({REAL}/"i")|"i"))
    ID          ("'"{.}+/{LETTER}+"'")
    STRING      ("'"{.}+"'")
    MULTISTRING ({MULTS}({.}+)|{NEWL}+{MULTS})
    COMMENT     ({.}+/{HASH})
    %%
   {SPACE}      {INDENT++; };
   {NEWL}   
    {
     if(INDENT>DEDENT) printf("Line %d: Found token %s (lexeme:       '%s').\n",yylineno,"INDENT",yytext);  
     if(INDENT<DEDENT)  printf("Line %d: Found token %s (lexeme: '%s').\n",yylineno,"DEDENT",yytext);   
     DEDENT=INDENT; line++;};
    {INTEGER}       printf("Line %d: Found token %s (lexeme: '%s').\n",yylineno,"INTEGER",yytext);
   {REAL}           printf("Line %d: Found token %s (lexeme: '%s').\n",yylineno,"REAL",yytext);
    {HEX}           printf("Line %d: Found token %s (lexeme: '%s').\n",yylineno,"HEX",yytext);
    {COMPLEX}       printf("Line %d: Found token %s (lexeme: '%s').\n",yylineno,"COMPLEX",yytext);
    {STRING}        printf("Line %d: Found token %s (lexeme: '%s').\n",yylineno,"STRING",yytext);
    {MULTISTRING}   printf("Line %d: Found token %s (lexeme: '%s').\n",yylineno,"MULTISTRING",yytext);
    {IF}            printf("Line %d: Found token %s (lexeme: '%s').\n",yylineno,"IF",yytext);
    {ELSE}          printf("Line %d: Found token %s (lexeme: '%s').\n",yylineno,"ELSE",yytext);
    LAMBDA}     printf("Line %d: Found token %s (lexeme: '%s').\n",yylineno,"LAMBDA",yytext);
    {FOR}           printf("Line %d: Found token %s (lexeme: '%s').\n",yylineno,"FOR",yytext);
    {PASS}          printf("Line %d: Found token %s (lexeme: '%s').\n",yylineno,"PASS",yytext);
    {ID}            printf("Line %d: Found token %s (lexeme: '%s').\n",yylineno,"ID",yytext);
    {COLON}         printf("Line %d: Found token %s (lexeme: '%s').\n",yylineno,"COLON",yytext);
    {LPAREN}        printf("Line %d: Found token %s (lexeme: '%s').\n",yylineno,"LPAREN",yytext);
    {RAREN}         printf("Line %d: Found token %s (lexeme: '%s').\n",yylineno,"RPAREN",yytext);
    {ARITH_OP}      printf("Line %d: Found token %s (lexeme: '%s').\n",yylineno,"ARITH_OP",yytext);
    {REL_OP}        printf("Line %d: Found token %s (lexeme: '%s').\n",yylineno,"REL_OP",yytext);
    {LOGIC_OP}      printf("Line %d: Found token %s (lexeme: '%s').\n",yylineno,"LOGIC_OP",yytext);
    {NOT}           printf("Line %d: Found token %s (lexeme: '%s').\n",yylineno,"NOT",yytext);
    {ASSIGN}        printf("Line %d: Found token %s (lexeme: '%s').\n",yylineno,"ASSIGN",yytext);
    .       printf("Line %d: Invalid token  ('%s').\n",yylineno,yytext);
    %%
    int main(int argc,char* argv[])
    {
yylex();
    }

我在第102行中有一个无法识别的规则,其中包含yylex();。 我做错了什么,错误在哪里?我找不到了。

hw1.text , line 102: unrecognized rule

当我尝试编译它时,我收到此错误。 我正在写flex hw1.text,文件和flex位于同一个文件夹中。


根据已删除的非答案添加的评论

我做了你告诉我要做的事,因为某些原因我得到'printf'行的错误。

我添加了:

ARITH_OP   ({PLUS}|{MINUS}|{DIV}|{MULT})
REL_OP     ({MORE_THAN}|{LESS_THAN}|{EQUAL})
LOGIC_OP   ({AND}|{OR})

可能是什么问题?

1 个答案:

答案 0 :(得分:3)

我看到了很多问题:

  1. {NEWL}之后的操作应与{NEWL}在同一行开始。

    {NEWL}
    {
    if(INDENT>DEDENT) printf("Line %d: Found token %s (lexeme:       '%s').\n",yylineno,"INDENT",yytext);
    if(INDENT<DEDENT)  printf("Line %d: Found token %s (lexeme: '%s').\n",yylineno,"DEDENT",yytext);
    DEDENT=INDENT; line++;};
    

    这应该是这样的:

    {NEWL} {
              if(INDENT>DEDENT) printf("Line %d: Found token %s (lexeme:       '%s').\n",yylineno,"INDENT",yytext);
              if(INDENT<DEDENT)  printf("Line %d: Found token %s (lexeme: '%s').\n",yylineno,"DEDENT",yytext);
              DEDENT=INDENT; line++;
           };
    
  2. 另一个问题是{规则缺少{LAMBDA}

    {ELSE}          printf("Line %d: Found token %s (lexeme: '%s').\n",yylineno,"ELSE",yytext);
    LAMBDA}     printf("Line %d: Found token %s (lexeme: '%s').\n",yylineno,"LAMBDA",yytext);
    {FOR}           printf("Line %d: Found token %s (lexeme: '%s').\n",yylineno,"FOR",yytext);
    
  3. 您使用{RAREN}代替{RPAREN}

  4. 您尚未定义{ARITH_OP}{REL_OP}{LOGIC_OP}

  5. 我认为MULTS的规则应该是这样的(但我可能错了):

    MULTS "\""
    
  6. 为了获得干净的编辑,我在扫描仪的规则部分之后将以下规则移到了注释中:

    {MULTISTRING}   printf("Line %d: Found token %s (lexeme: '%s').\n",yylineno,"MULTISTRING",yytext);
    {ID}            printf("Line %d: Found token %s (lexeme: '%s').\n",yylineno,"ID",yytext);
    {STRING}        printf("Line %d: Found token %s (lexeme: '%s').\n",yylineno,"STRING",yytext);
    {HEX}           printf("Line %d: Found token %s (lexeme: '%s').\n",yylineno,"HEX",yytext);
    {COMPLEX}       printf("Line %d: Found token %s (lexeme: '%s').\n",yylineno,"COMPLEX",yytext);
    {INTEGER}       printf("Line %d: Found token %s (lexeme: '%s').\n",yylineno,"INTEGER",yytext);
    {REAL}          printf("Line %d: Found token %s (lexeme: '%s').\n",yylineno,"REAL",yytext);
    {ARITH_OP}      printf("Line %d: Found token %s (lexeme: '%s').\n",yylineno,"ARITH_OP",yytext);
    {REL_OP}        printf("Line %d: Found token %s (lexeme: '%s').\n",yylineno,"REL_OP",yytext);
    {LOGIC_OP}      printf("Line %d: Found token %s (lexeme: '%s').\n",yylineno,"LOGIC_OP",yytext);
    
  7. 显然,您还需要一个函数来代替重复的printf()语句。


    '工作'代码

    此代码编译并运行。规则仍然存在很多问题(例如,实数在小数点后只能有一个数字,标识符必须用单引号括起来)。它使用print_token()函数使扫描程序操作可读。

    %option lex-compat
    %option noyywrap
    %option yylineno
    
    %{
    #include <stdio.h>
    /*#include <conio.h>*/
    #include <stdlib.h>
    #include <string.h>
    %}
    
    %{
    int INDENT=0, DEDENT=0, line=0;
    static void print_token(const char *token);
    
    /*
    Original rules moved out of the way:
    
    MULTISTRING ({MULTS}({.}+)|{NEWL}+{MULTS})
    STRING      ("'"{.}+"'")
    INTEGER     ({SIGN}?({ZERO}|({ZERO}+/({NUM_NZ}+))))
    ID          ("'"{.}+/{LETTER}+"'")
    H           ({"h"|"H"})
    COMPLEX     ({PLUS}?{REAL}+{COMP}{SIGN}?(({REAL}/"i")|"i"))
    MULTISTRING ({MULTS}({.}+)|{NEWL}+{MULTS})
    */
    
    /*
    Examples of patterns matched:
    
    INTEGER: 1 +1 -2 0 99 999 987654321092344
    REAL:    1.2 -2.1 3.14159
    ID:      'ThisIsAnId'
    HEX:     +0 DeadBeefH
    */
    %}
    
    HASH        "#"
    NEWL        [\n]
    SPACE       " "
    MULTS       "\""
    COMP        "e^"
    LETTER      ([a-zA-Z])
    HEXL        ([a-fA-F1-9])
    ZERO        "0"
    EXP         "10^"
    COLON       ":"
    DOT         "."
    LPAREN      "("
    RPAREN      ")"
    PLUS        "+"
    MINUS       "-"
    SIGN        ({PLUS}|{MINUS})
    MULT        "*"
    DIV         "/"
    ASSIGN      "="
    EQUAL       "=="
    MORE_THAN   ">"
    LESS_THAN   "<"
    OR          "or"
    AND         "and"
    NOT         "not"
    IF          "if"
    ELSE        "else"
    LAMBDA      "lambda"
    FOR         "for"
    PASS        "pass"
    H           ("h"|"H")
    WHITESPACE  {[\t\n]}
    NUM_NZ      [1-9]
    NUM         [0-9]
    
    INTEGER     ({SIGN}?{NUM_NZ}+)
    
    REAL        ({INTEGER}{DOT}{NUM}|{INTEGER}{DOT}{NUM}{EXP}{INTEGER})
    HEX         ({PLUS}?({ZERO}|{HEXL}+{H}))
    COMPLEX     ({PLUS}?{REAL}+{COMP}{SIGN}?(({REAL}"i")|"i"))
    
    ID          ("'"{LETTER}+"'")
    STRING      ("'"[^']+"'")
    MULTISTRING ({MULTS}([^"]+)|{NEWL}+{MULTS})
    COMMENT     ({.}+/{HASH})
    ARITH_OP    ({PLUS}|{MINUS}|{DIV}|{MULT})
    REL_OP      ({MORE_THAN}|{LESS_THAN}|{EQUAL})
    LOGIC_OP    ({AND}|{OR})
    
    %%
    
    {SPACE}         { INDENT++; };
    {NEWL}          {
                        if (INDENT > DEDENT) print_token("INDENT");  
                        if (INDENT < DEDENT) print_token("DEDENT");   
                        DEDENT = INDENT;
                        line++;
                    }
    {MULTISTRING}   print_token("MULTISTRING");
    {STRING}        print_token("STRING");
    {HEX}           print_token("HEX");
    {ID}            print_token("ID");
    {INTEGER}       print_token("INTEGER");
    {COMPLEX}       print_token("COMPLEX");
    {REAL}          print_token("REAL");
    {IF}            print_token("IF");
    {ELSE}          print_token("ELSE");
    {LAMBDA}        print_token("LAMBDA");
    {FOR}           print_token("FOR");
    {PASS}          print_token("PASS");
    {COLON}         print_token("COLON");
    {LPAREN}        print_token("LPAREN");
    {RPAREN}        print_token("RPAREN");
    {ARITH_OP}      print_token("ARITH_OP");
    {REL_OP}        print_token("REL_OP");
    {LOGIC_OP}      print_token("LOGIC_OP");
    {NOT}           print_token("NOT");
    {ASSIGN}        print_token("ASSIGN");
    .               printf("Line %d: Invalid token ('%s').\n", yylineno, yytext);
    
    %%
    
    static void print_token(const char *token)
    {
        printf("Line %d: Found token %s (lexeme: '%s').\n", yylineno, token, yytext);
    }
    
    int main(void)
    {
        yylex();
    }
    

    其中一个问题是在规则中使用/。在Lex和Flex,IIRC中,它引入了尾随上下文。我不清楚它在使用它的规则中打算做什么。至少有一个ZERO}您需要{ZERO}。您似乎试图将{.}+用作[.]+.+的同义词(我通常会将其更改为[^"]+[^']+

    COMMENT的规则仍然包含斜杠。似乎哈希标记了注释的结尾(但不是注释的一部分),而不是注释的开头;这是一个不同寻常的(我认为它实际上无法使用)作为评论惯例。

    至于我是如何做这项工作的,我一次做了一次。

    我将导致编译错误的位移到了注释中。当我得到编译的东西时,我测试了它(在它自己的源代码上)。然后我收集了一条破碎的规则,保留了记录,所以我知道原件是什么,并修改它,这对我来说是有道理的。一次冲洗,重复,一步。我使用的是VCS(实际上是git),所以我知道如果我犯了一个严重的错误,我可以恢复“工作”版本。你使用VCS,不是吗?