我正在开发公司项目,在这里我必须使用Ocamlyacc和Ocamllex为语言创建一个编译器。我想知道是否有可能在我的Ocamlyacc解析器中定义一个规则,它可以告诉我语法中没有任何规则与输入的语法匹配。
我必须坚持我是Ocamllex/Ocamlyacc的初学者
非常感谢你的帮助。
发布于 2015-08-04 14:47:08
如果语法中没有任何规则与输入匹配,则会引发Parsing.Parse_error异常。通常,这就是你想要的。
还有一个特殊的令牌名为error,它允许您重新同步解析器状态。您可以在规则中使用它,因为它是由lexer,cf.,eof令牌生成的真正的令牌。
另外,我建议使用menhir,而不是更受尊敬的ocamlyacc。它更容易使用和调试,它还附带了一个好的预定义语法库。
发布于 2015-08-04 14:21:52
当您为一种语言编写编译器时,第一步是运行您的lexer,并从词法角度检查您的程序是否良好。
见下面的示例:
{
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是否可以用指定的语法构建。见:
%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。没有办法定义未被识别的规则,但是您需要编写一种语法来定义程序如何被接受或拒绝。
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 + 2是因为没有错误词法错误,并且可以构建对应于该表达式的AST。1 ++ 2被拒绝:没有词汇错误,但是没有规则来构建这样的AST。您可以在这里找到更多的文档:http://caml.inria.fr/pub/docs/manual-ocaml-4.00/manual026.html
https://stackoverflow.com/questions/31809868
复制相似问题