gpt4 book ai didi

parsing - OCaml + Menhir 编译/写作

转载 作者:行者123 更新时间:2023-12-03 23:37:07 24 4
gpt4 key购买 nike

当谈到 OCaml 时,我是一个完整的新手。我最近才开始使用该语言(大约 2 周前),但不幸的是,我的任务是为一种组合语言制作一个语法分析器(解析器 + 词法分析器,其功能是接受或不接受句子)使用门希尔。现在,我在网上找到了一些关于 OCaml 和 Menhir 的资料:

Menhir手册。

This webpage for some French University course.

在 Sourceforge 的 Toss 主页上的 Menhir 简短教程。

derdon 在 github 上的 Menhir 示例。

A book on OCaml (with a few things about ocamllex+ocamlyacc

SooHyoung Oh 的随机 ocamllex 教程。

以及 Menhir 源代码附带的示例。

(我不能放两个以上的超链接,所以我不能把你直接链接到我在这里提到的一些网站。对不起!)

所以,正如你所看到的,我一直在拼命地寻找越来越多的 Material 来帮助我制作这个程序。不幸的是,我仍然无法掌握许多概念,因此我遇到了很多很多困难。

对于初学者,我不知道如何正确编译我的程序。我一直在使用以下命令:

ocamlbuild -use-menhir -menhir "menhir --external-tokens Tokens" main.native

我的程序分为四个不同的文件:main.ml;词法分析器.mll;解析器.mly; token .mly。 main.ml 是从作为参数给出的文件系统中的文件获取输入的部分。
let filename = Sys.argv.(1)

let () =
let inBuffer = open_in filename in
let lineBuffer = Lexing.from_channel inBuffer in
try
let acceptance = Parser.main Lexer.main lineBuffer in
match acceptance with
| true -> print_string "Accepted!\n"
| false -> print_string "Not accepted!\n"
with
| Lexer.Error msg -> Printf.fprintf stderr "%s%!\n" msg
| Parser.Error -> Printf.fprintf stderr "At offset %d: syntax error.\n%!" (Lexing.lexeme_start lineBuffer)

第二个文件是 lexer.mll。
{
open Tokens
exception Error of string
}

rule main = parse
| [' ' '\t']+
{ main lexbuf }
| ['0'-'9']+ as integer
{ INT (int_of_string integer) }
| "True"
{ BOOL true }
| "False"
{ BOOL false }
| '+'
{ PLUS }
| '-'
{ MINUS }
| '*'
{ TIMES }
| '/'
{ DIVIDE }
| "def"
{ DEF }
| "int"
{ INTTYPE }
| ['A'-'Z' 'a'-'z' '_']['0'-'9' 'A'-'Z' 'a'-'z' '_']* as s
{ ID (s) }
| '('
{ LPAREN }
| ')'
{ RPAREN }
| '>'
{ LARGER }
| '<'
{ SMALLER }
| ">="
{ EQLARGER }
| "<="
{ EQSMALLER }
| "="
{ EQUAL }
| "!="
{ NOTEQUAL }
| '~'
{ NOT }
| "&&"
{ AND }
| "||"
{ OR }
| '('
{ LPAREN }
| ')'
{ RPAREN }
| "writeint"
{ WRITEINT }
| '\n'
{ EOL }
| eof
{ EOF }
| _
{ raise (Error (Printf.sprintf "At offset %d: unexpected character.\n" (Lexing.lexeme_start lexbuf))) }

第三个文件是 parser.mly。
%start <bool> main
%%

main:
| WRITEINT INT { true }

第四个是tokens.mly
%token <string> ID
%token <int> INT
%token <bool> BOOL
%token EOF EOL DEF INTTYPE LPAREN RPAREN WRITEINT
%token PLUS MINUS TIMES DIVIDE
%token LARGER SMALLER EQLARGER EQSMALLER EQUAL NOTEQUAL
%token NOT AND OR

%left OR
%left AND
%nonassoc NOT
%nonassoc LARGER SMALLER EQLARGER EQSMALLER EQUAL NOTEQUAL
%left PLUS MINUS
%left TIMES DIVIDE
%nonassoc LPAREN
%nonassoc ATTRIB

%{
type token =
| ID of (string)
| INT
| BOOL
| DEF
| INTTYPE
| LPAREN
| RPAREN
| WRITEINT
| PLUS
| MINUS
| TIMES
| DIVIDE
| LARGER
| SMALLER
| EQLARGER
| EQSMALLER
| EQUAL
| NOTEQUAL
| NOT
| AND
| OR
| EOF
| EOL
%}

%%

现在,我知道这里有很多未使用的符号,但我打算在我的解析器中使用它们。不管我对文件做了多少修改,编译器总是在我脸上炸开。我已经尝试了我能想到的一切,但似乎没有任何效果。是什么让 ocamlbuild 在大量未绑定(bind)的构造函数和未定义的开始符号的错误中爆炸?我应该使用什么命令来正确编译程序?我在哪里可以找到有意义的 Material 来了解 Menhir?

最佳答案

一个更简单的方法是删除 Parser/Tokens分离。正如 Thomas 所说,不需要声明 type token = ... , 因为它是由 menhir 从 %token 自动生成的指令。

所以你可以定义parser.mly作为:

%start <bool> main

%token <string> ID
%token <int> INT
%token <bool> BOOL
%token EOF EOL DEF INTTYPE LPAREN RPAREN WRITEINT
%token PLUS MINUS TIMES DIVIDE
%token LARGER SMALLER EQLARGER EQSMALLER EQUAL NOTEQUAL
%token NOT AND OR

%left OR
%left AND
%nonassoc NOT
%nonassoc LARGER SMALLER EQLARGER EQSMALLER EQUAL NOTEQUAL
%left PLUS MINUS
%left TIMES DIVIDE
%nonassoc LPAREN
%nonassoc ATTRIB
%%

main:
| WRITEINT INT { true }

lexer.mll作为:
{
open Parser
exception Error of string
}

[...] (* rest of the code not shown here *)

然后删除 tokens.mly , 并编译
ocamlbuild -use-menhir main.native

一切都很好。

关于parsing - OCaml + Menhir 编译/写作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9897358/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com