首页 > 解决方案 > 从 y.output 文件解析的解码步骤

问题描述

1.如果我输入int a;float b;语法使用LR解析来解析它。我已经阅读了 LR 如何工作的规则,但想知道它的分步说明。

2.为什么会出现语法错误?我怎么知道它发生在哪条线上?

编辑问题 2:%error-verbose 给出了更详细的错误原因,我用 id 替换了 flex 文件中的 NAME 令牌,它可以工作。

y.输出

Terminals unused in grammar

     LCURL
     RCURL
     LPAREN
     RPAREN
     NAME
     DOUBLE
     THEN
     ELSE
     "<"
     ">"
     "<="
     ">="
     "="
     "!="
     "+"
     "-"
     "*"
     "/"
     UMINUS


  Grammar

      0 $accept: start $end

      1 start: program

      2 program: program unit
      3        | unit

      4 unit: var_dec

      5 var_dec: type_specifier declaration_list SEMICOLON

      6 type_specifier: "int"
      7               | FLOAT
      8               | VOID

      9 declaration_list: declaration_list COMMA ID
     10                 | declaration_list COMMA ID LTHIRD CONST_INT RTHIRD
     11                 | ID
     12                 | ID LTHIRD CONST_INT RTHIRD


  Terminals, with rules where they appear

  $end (0) 0
  error (256)
  "int" (258) 6
  COMMA (259) 9 10
  SEMICOLON (260) 5
  ID (261) 9 10 11 12
  FLOAT (262) 7
  VOID (263) 8
  LCURL (264)
  RCURL (265)
  LPAREN (266)
  RPAREN (267)
  CONST_INT (268) 10 12
  LTHIRD (269) 10 12
  RTHIRD (270) 10 12
  NAME (271)
  DOUBLE (272)
  THEN (273)
  ELSE (274)
  "<" (275)
  ">" (276)
  "<=" (277)
  ">=" (278)
  "=" (279)
  "!=" (280)
  "+" (281)
  "-" (282)
  "*" (283)
  "/" (284)
  UMINUS (285)


  Nonterminals, with rules where they appear

  $accept (31)
      on left: 0
  start (32)
      on left: 1, on right: 0
  program (33)
      on left: 2 3, on right: 1 2
  unit (34)
      on left: 4, on right: 2 3
  var_dec (35)
      on left: 5, on right: 4
  type_specifier (36)
      on left: 6 7 8, on right: 5
  declaration_list (37)
      on left: 9 10 11 12, on right: 5 9 10


  State 0

      0 $accept: . start $end

      "int"  shift, and go to state 1
      FLOAT  shift, and go to state 2
      VOID   shift, and go to state 3

      start           go to state 4
      program         go to state 5
      unit            go to state 6
      var_dec         go to state 7
      type_specifier  go to state 8


  State 1

      6 type_specifier: "int" .

      $default  reduce using rule 6 (type_specifier)


  State 2

      7 type_specifier: FLOAT .

      $default  reduce using rule 7 (type_specifier)


  State 3

      8 type_specifier: VOID .

      $default  reduce using rule 8 (type_specifier)


  State 4

      0 $accept: start . $end

      $end  shift, and go to state 9


  State 5

      1 start: program .
      2 program: program . unit

      "int"  shift, and go to state 1
      FLOAT  shift, and go to state 2
      VOID   shift, and go to state 3

      $default  reduce using rule 1 (start)

      unit            go to state 10
      var_dec         go to state 7
      type_specifier  go to state 8


  State 6

      3 program: unit .

      $default  reduce using rule 3 (program)


  State 7

      4 unit: var_dec .

      $default  reduce using rule 4 (unit)


  State 8

      5 var_dec: type_specifier . declaration_list SEMICOLON

      ID  shift, and go to state 11

      declaration_list  go to state 12


  State 9

      0 $accept: start $end .

      $default  accept


  State 10

      2 program: program unit .

      $default  reduce using rule 2 (program)


  State 11

     11 declaration_list: ID .
     12                 | ID . LTHIRD CONST_INT RTHIRD

      LTHIRD  shift, and go to state 13

      $default  reduce using rule 11 (declaration_list)


  State 12

      5 var_dec: type_specifier declaration_list . SEMICOLON
      9 declaration_list: declaration_list . COMMA ID
     10                 | declaration_list . COMMA ID LTHIRD CONST_INT RTHIRD

      COMMA      shift, and go to state 14
      SEMICOLON  shift, and go to state 15


  State 13

     12 declaration_list: ID LTHIRD . CONST_INT RTHIRD

      CONST_INT  shift, and go to state 16


  State 14

      9 declaration_list: declaration_list COMMA . ID
     10                 | declaration_list COMMA . ID LTHIRD CONST_INT RTHIRD

      ID  shift, and go to state 17


  State 15

      5 var_dec: type_specifier declaration_list SEMICOLON .

      $default  reduce using rule 5 (var_dec)


  State 16

     12 declaration_list: ID LTHIRD CONST_INT . RTHIRD

      RTHIRD  shift, and go to state 18


  State 17

      9 declaration_list: declaration_list COMMA ID .
     10                 | declaration_list COMMA ID . LTHIRD CONST_INT RTHIRD

      LTHIRD  shift, and go to state 19

      $default  reduce using rule 9 (declaration_list)


  State 18

     12 declaration_list: ID LTHIRD CONST_INT RTHIRD .

      $default  reduce using rule 12 (declaration_list)


  State 19

     10 declaration_list: declaration_list COMMA ID LTHIRD . CONST_INT RTHIRD

      CONST_INT  shift, and go to state 20


  State 20

     10 declaration_list: declaration_list COMMA ID LTHIRD CONST_INT . RTHIRD

      RTHIRD  shift, and go to state 21


  State 21

     10 declaration_list: declaration_list COMMA ID LTHIRD CONST_INT RTHIRD .

      $default  reduce using rule 10 (declaration_list)

我的输出是这个

type_specifier -> INT
syntax error

我正在添加 flex 和 bison 文件以防万一。Flex 文件:scanner.l

%option noyywrap

    %{

    #include<stdlib.h>
    #include<stdio.h>
    #include "y.tab.h"
    #include "SymbolTable.h"
    #include "SymbolInfo.h"
    #include "ScopeTable.h"

    void yyerror (char *);
    extern YYSTYPE yylval;  
    extern SymbolTable *table;

    int line_count = 1;

    %}


    NAME [a-z]*
    DOUBLE (([0-9]+(\.[0-9]*)?)|([0-9]*\.[0-9]+)) 
    id NAME
    newline \n

    %%

    {newline} {line_count++;}

    [ \t]+  {}
    (([0-9]+(\.[0-9]*)?)|([0-9]*\.[0-9]+))  {
                            yylval.f = atof(yytext);
                            return DOUBLE;
                        }

    "int" {return INT;}
    "float" {return FLOAT;}
    "void"  {return VOID;}  

    [a-z]+  {
            yylval.s = *yytext;
            return NAME;
            }

    ";" {return SEMICOLON;}
    "," {return COMMA;}
    "(" {return LPAREN;}
    ")" {return RPAREN;}
    "{" {return LCURL;}
    "}" {return RCURL;}

    {id}    {

                SymbolInfo *s;
                std::string str;
                for(int i = 0;yytext[i] != '\0';i++)
                {
                    str = yytext[i];
                }

                s = table -> scope_lookup(str);

                if(s == NULL)
                {
                     s->setName(str);
                }
                yylval.sym = s; 
                return ID;

            }

    %%                          

和 yacc 文件:parser.y

%{
    #include<stdio.h>
    #include<stdlib.h>  
    #include<string.h>
    #include "SymbolTable.h"
    #include "SymbolInfo.h"
    #include "ScopeTable.h"

    int yyparse(void);
    int yylex(void);
    extern char* yytext;
    extern FILE * yyin;
    extern int tableSize;

    FILE *logout;
    extern int line_count;


    SymbolTable *table;

    void yyerror (char *s)
    {
        fprintf(stderr,"%s\n",s);
        return;
    }

    %}

    %union {
        class SymbolInfo* sym;
        char *s;
        float f;
    }


    %verbose
    %token INT "int"
    %token COMMA SEMICOLON ID FLOAT VOID LCURL RCURL LPAREN RPAREN 
    %token CONST_INT LTHIRD RTHIRD 

    %token <s> NAME
    %token <f> DOUBLE
    %type <s> INT
    //%expect 1

    %precedence THEN
    %precedence ELSE

    %left "<" ">" "<=" ">=" "=" "!="
    %left "+" "-"
    %left "*" "/"
    %left UMINUS 


    %%

    start : program     {   printf("start -> program\n");
                            fprintf(logout,"%d : start ->  program\n",line_count);
                        }
          ;

    program : program unit {
                                printf("program -> program unit\n");
                                fprintf(logout,"%d : program -> program unit\n",line_count);
                            }
            | unit          {
                                printf("program -> unit\n");
                                fprintf(logout,"%d : program -> unit\n",line_count);
                            }
            ;

    unit : var_dec  {
                                printf("unit -> var_dec\n");
                                fprintf(logout,"%d : unit -> var_dec\n",line_count);
                    }

         ;


    var_dec: type_specifier declaration_list SEMICOLON {

                        printf("var_dec -> type_specifier declaration_list SEMICOLON \n");
                        fprintf(logout,"%d -> var_dec: type_specifier declaration_list SEMICOLON \n", line_count);

                }
            ;            

    type_specifier : INT    {printf("type_specifier -> INT\n");
                                fprintf(logout,"%d : type_specifier-> INT\n", line_count);
                            }
                   | FLOAT  {printf("type_specifier ->FLOAT\n");
                                fprintf(logout,"%d : type_specifier-> FLOAT\n",line_count);

                            }
                   | VOID   {printf("type_specifier -> VOID\n");
                                fprintf(logout,"%d : type_specifier-> VOID\n",line_count);

                             }
                   ;        

    declaration_list : declaration_list COMMA ID {

                            printf("declaration_list -> declaration_list COMMA ID\n");  
                            fprintf(logout,"%d : declaration_list -> declaration_list COMMA ID\n",line_count);
                           }
                     | declaration_list COMMA ID LTHIRD CONST_INT RTHIRD {

                            printf("declaration_list -> declaration_list COMMA ID LTHIRD CONST_INT RTHIRD\n");      
                            fprintf(logout,"%d : declaration_list -> declaration_list COMMA ID LTHIRD CONST_INT RTHIRD\n",line_count);

                            }
                     |ID    {
                            printf("declaration_list -> ID\n");
                            fprintf(logout,"%d : declaration_list -> ID\n",line_count);
                            }
                     |ID LTHIRD CONST_INT RTHIRD {

                            printf("declaration_list -> ID LTHIRD CONST_INT RTHIRD\n"); 
                            fprintf(logout,"%d : declaration_list -> ID LTHIRD CONST_INT RTHIRD\n",line_count);

                            }
                     ;         


    %%

    int main(int argc, char *argv[])
    {

        FILE *fp  ;
        int token = 0;
        if((fp = fopen(argv[1],"r")) == NULL)
        {
            fprintf(logout,"cannot open file");
            exit(1);
        }


        logout = fopen("log.txt","w");

        yyin = fp;
        yyparse();

        fclose(fp);
        fclose(logout);
        return 0;

    }

标签: syntax-errorbison

解决方案


如果您想详细了解解析器的工作原理,最好使用 bison 自己的跟踪工具。请注意,您必须做两件事:

  • 告诉 bison 生成跟踪代码,使用-t生成解析器时的选项;
  • 将全局变量设置yydebug为 1 以开始跟踪。

还有其他有用的选项,都在Debugging Your Parser中描述。

如果您添加,Flex 将自动跟踪输入的行号

%option yylineno

到你的 flex 序言。一旦你这样做了,你就可以yylineno在你的yyerror函数中使用全局变量。请注意,由于yylineno在扫描仪中定义,您必须在解析器中显式声明它:

void yyerror (const char *msg)
{
    extern int yylineno;
    fprintf(stderr, "At %d: %s\n", yylineno, msg);
}

推荐阅读