0

我是 ML 的新手,现在学习 ocaml 只需几个小时就可以用它构建我的编译器。Lexer 和 Parser 生成没有任何问题。但是当编译器代码由 ocamlmktop 构建时,就会出现问题。
错误信息如下所示,但二进制文件 myc.top 已完成并可以运行。

请您帮我解决错误信息,非常感谢您的支持。

$ ocamlyacc parser.mly
$ ocamllex lexer.mll
24 states, 1124 transitions, table size 4640 bytes
$ ocamlmktop syntax.ml parser.mli parser.ml lexer.ml -o myc.top
File "parser.cmo", line 1:
Error (warning 31): files parser.cmo and /usr/local/lib/ocaml/compiler-libs/ocamlcommon.cma(Parser) both define a module named Parser
File "lexer.cmo", line 1:
Error (warning 31): files lexer.cmo and /usr/local/lib/ocaml/compiler-libs/ocamlcommon.cma(Lexer) both define a module named Lexer

1.词法分析器文件lexer.mll

{
open Parser
}

let space = [' ' '\t' '\n' '\r']
let digit = ['0'-'9']
let alpha = ['A'-'Z' 'a'-'z' '_']

rule token = parse
| "while"
    { WHILE }
| "print"
    { PRINT }
| alpha (digit|alpha)*
    (* reserve key word *)
    { VAR(Lexing.lexeme lexbuf) }
| '-'? digit+
    { CONST(int_of_string (Lexing.lexeme lexbuf)) }
| space+
    (* skip spaces *)
    { token lexbuf }
| '='
    { EQUAL }
| '+'
    { PLUS }
| '('
    { LPAREN }
| ')'
    { RPAREN }
| '>'
    { GREATER }
| '{'
    { LBRACE }
| '}'
    { RBRACE }
| ';'
    { SEMICOLON }
| _
    (* other case: error heppen *)
    { failwith
        (Printf.sprintf
           "unknown token %s near characters %d-%d"
           (Lexing.lexeme lexbuf)
           (Lexing.lexeme_start lexbuf)
           (Lexing.lexeme_end lexbuf)) }

2 解析器文件 Parser.mly

%{
open Syntax
%}

%token <string> VAR /* variable */
%token <int> CONST  /* integer */
%token EQUAL        /* = */
%token PLUS         /* - */
%token WHILE        /* keyword「while」 */
%token LPAREN       /* ( */
%token RPAREN       /* ) */
%token GREATER      /* > */
%token LBRACE       /* { */
%token RBRACE       /* } */
%token SEMICOLON    /* ; */
%token PRINT        /* keyword「print」 */

%type <Syntax.statement> statement
%start statement

%%

statement: /* start */
| VAR EQUAL CONST
    { Const($1, $3) }
| VAR EQUAL VAR PLUS VAR
    { Add($1, $3, $5) }
| WHILE LPAREN VAR GREATER VAR RPAREN statement
    { While($3, $5, $7) }
| LBRACE statement_list RBRACE
    { Seq($2) }
| PRINT VAR
    { Print($2) }
| error /* other cases, error happens */
    { failwith
        (Printf.sprintf
           "parse error near characters %d-%d"
           (Parsing.symbol_start ())
           (Parsing.symbol_end ())) }

statement_list: /* start */
| statement SEMICOLON statement_list
    /* one by one */
    { $1 :: $3 }
| /* 空列 */
    { [] } /* nil return */

3. 文件语法.ml

type var = string (* variable *)

type statement = (* statement *)
  | Const of var * int
      (* x = i *)
  | Add of var * var * var
      (* x = y + z *)
  | While of var * var * statement
      (* while (x > y) *)
  | Seq of statement list
      (* { s1; s2; …; sn } *)
  | Print of var
      (* print x *)
4

1 回答 1

1

OCaml 标准库中已经有名为 Lexer 和 Parser 的模块。当您尝试构建顶级可执行文件时,这些与您的模块名称冲突。

使事情正常进行的一种方法是将模块重命名为其他名称。

$ cat parser.ml
let f x = x * 2
$ ocamlmktop -o mytop parser.ml
File "parser.cmo", line 1:
Error (warning 31): files parser.cmo and
  /Users/jeffsco/.opam/4.06.1/lib/ocaml/compiler-
  libs/ocamlcommon.cma(Parser) both define a module named Parser
$ mv parser.ml myparser.ml
$ ocamlmktop -o mytop myparser.ml
$ ./mytop
        OCaml version 4.06.1

# Myparser.f 13;;
- : int = 26
于 2019-01-03T17:53:51.503 回答