代码之家  ›  专栏  ›  技术社区  ›  nlucaroni

解析器/词法分析器忽略不完整的语法规则

  •  4
  • nlucaroni  · 技术社区  · 15 年前

    我有一个用ocamlyacc和ocamlex编写的解析器和lexer。如果要分析的文件过早结束(如我忘记了行末尾的分号),则应用程序不会引发语法错误。我意识到这是因为我正在提高和捕捉EOF,这使得lexer忽略了未完成的规则,但是如何做到呢 应该 我这样做是为了引起语法错误?

    这是我当前的解析器(简化),

    %{
        let parse_error s = Printf.ksprinf failwith "ERROR: %s" s
    %}
    
    %token COLON
    %token SEPARATOR
    %token SEMICOLON
    %token <string> FLOAT
    %token <string> INT
    %token <string> LABEL
    
    %type <Conf.config> command
    %start command
    %%
      command:
          | label SEPARATOR data SEMICOLON    { Conf.Pair ($1,$3)     }
          | label SEPARATOR data_list         { Conf.List ($1,$3)     }
          | label SEMICOLON                   { Conf.Single ($1)      }
      label :
          | LABEL                             { Conf.Label $1         }
      data :
          | label                             { $1                    }
          | INT                               { Conf.Integer $1       }
          | FLOAT                             { Conf.Float $1         }
      data_list :
          | star_data COMMA star_data data_list_ending
                                              { $1 :: $3 :: $4        }
      data_list_ending:
          | COMMA star_data data_list_ending  { $2 :: $3              }
          | SEMICOLON                         { []                    }
    

    和lexer(简化),,

    {
        open ConfParser
        exception Eof
    }
    
    rule token = parse
        | ['\t' ' ' '\n' '\010' '\013' '\012']
                            { token lexbuf   }
        | ['0'-'9']+ ['.'] ['0'-'9']* ('e' ['-' '+']? ['0'-'9']+)? as n
                            { FLOAT n        }
        | ['0'-'9']+ as n   { INT n          }
        | '#'               { comment lexbuf }
        | ';'               { SEMICOLON      }
        | ['=' ':']         { SEPARATOR      }
        | ','               { COMMA          }
        | ['_' 'a'-'z' 'A'-'Z']([' ']?['a'-'z' 'A'-'Z' '0'-'9' '_' '-' '.'])* as w
                            { LABEL w        }
        | eof               { raise Eof      }
    
    and comment = parse
        | ['#' '\n']        { token lexbuf   }
        | _                 { comment lexbuf }
    

    示例输入文件,

    one = two, three, one-hundred;
    single label;
    list : command, missing, a, semicolon
    

    1 回复  |  直到 15 年前
        1
  •  5
  •   Charles Duffy    15 年前

    ocamlyacc EOF Eof 在lexer中,添加一个令牌 EOF 改变你的想法 start 象征

    %type <Conf.config list> main
    
    main:
        EOF { [] }
      | command main { $1::$2 }