首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在Ocamlyacc中定义不可识别的规则

如何在Ocamlyacc中定义不可识别的规则
EN

Stack Overflow用户
提问于 2015-08-04 12:52:34
回答 2查看 197关注 0票数 0

我正在开发公司项目,在这里我必须使用Ocamlyacc和Ocamllex为语言创建一个编译器。我想知道是否有可能在我的Ocamlyacc解析器中定义一个规则,它可以告诉我语法中没有任何规则与输入的语法匹配。

我必须坚持我是Ocamllex/Ocamlyacc的初学者

非常感谢你的帮助。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-08-04 14:47:08

如果语法中没有任何规则与输入匹配,则会引发Parsing.Parse_error异常。通常,这就是你想要的。

还有一个特殊的令牌名为error,它允许您重新同步解析器状态。您可以在规则中使用它,因为它是由lexer,cf.,eof令牌生成的真正的令牌。

另外,我建议使用menhir,而不是更受尊敬的ocamlyacc。它更容易使用和调试,它还附带了一个好的预定义语法库。

票数 3
EN

Stack Overflow用户

发布于 2015-08-04 14:21:52

当您为一种语言编写编译器时,第一步是运行您的lexer,并从词法角度检查您的程序是否良好。

见下面的示例:

代码语言:javascript
复制
{
  open Parser        (* The type token is defined in parser.mli *)
  exception Eof
}
  rule token = parse
            [' ' '\t']     { token lexbuf }     (* skip blanks *)
          | ['\n' ]        { EOL }
          | ['0'-'9']+ as lxm { INT(int_of_string lxm) }
          | '+'            { PLUS }
          | '-'            { MINUS }
          | '*'            { TIMES }
          | '/'            { DIV }
          | '('            { LPAREN }
          | ')'            { RPAREN }
          | eof            { raise Eof }

识别一些算术表达式是一种词汇。

如果您的lexer接受输入,那么您将向解析器提供词汇序列,解析器将试图找出一个AST是否可以用指定的语法构建。见:

代码语言:javascript
复制
%token <int> INT
        %token PLUS MINUS TIMES DIV
        %token LPAREN RPAREN
        %token EOL
        %left PLUS MINUS        /* lowest precedence */
        %left TIMES DIV         /* medium precedence */
        %nonassoc UMINUS        /* highest precedence */
        %start main             /* the entry point */
        %type <int> main
        %%
        main:
            expr EOL                { $1 }
        ;
        expr:
            INT                     { $1 }
          | LPAREN expr RPAREN      { $2 }
          | expr PLUS expr          { $1 + $3 }
          | expr MINUS expr         { $1 - $3 }
          | expr TIMES expr         { $1 * $3 }
          | expr DIV expr           { $1 / $3 }
          | MINUS expr %prec UMINUS { - $2 }
        ;

这是一个解析算术表达式的小程序。程序可以在这一步被拒绝,因为没有语法规则可应用,以便在结尾处有AST。没有办法定义未被识别的规则,但是您需要编写一种语法来定义程序如何被接受或拒绝。

代码语言:javascript
复制
let _ =
  try
    let lexbuf = Lexing.from_channel stdin in
    while true do
      let result = Parser.main Lexer.token lexbuf in
      print_int result; print_newline(); flush stdout
    done
  with Lexer.Eof ->
    exit 0

如果您编译了lexer、解析器和最后一个程序,那么您可以:

  1. 接受1 + 2是因为没有错误词法错误,并且可以构建对应于该表达式的AST。
  2. 1 ++ 2被拒绝:没有词汇错误,但是没有规则来构建这样的AST。

您可以在这里找到更多的文档:http://caml.inria.fr/pub/docs/manual-ocaml-4.00/manual026.html

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/31809868

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档