Ошибка: генерирует пустой язык, используя Menhir и OCaml
В настоящее время я работаю над Pascal Parser, используя OCaml и Menhir. Когда я компилирую свой parser.mly, который содержит следующий скриптлет, Менгир просто говорит: "Предупреждение: if_cmd генерирует пустой язык". Это может произойти, когда правило "if_cmd" не может быть достигнуто из исходного (поправьте меня, если я Я ошибаюсь), но по логике вещей, это должно было быть достигнуто. Я не могу понять, почему происходит это предупреждение. Например, если я использую входной файл для грамматики, указанной в parser.mly с этими операторами:
program ex1;
x:=1
y:=(2)
это дает мне желаемый ответ. Но если я использую это в качестве ввода
program ex1;
x:=1
y:=(2)
if(x and 2) then
y:=3
Говорится Exception: Syntax.Error
вероятно из-за этого предупреждения
С этими 4 следующими файлами в одной папке, я использовал ocamlbuild -use-menhir main.byte
команда, которая генерирует только что упомянутое предупреждение
lexer.mll
{
open Lexing
open Printf
open Parser
let incr_line_number lexbuf =
let pos = lexbuf.lex_curr_p in
lexbuf.lex_curr_p <- { pos with
pos_lnum = pos.pos_lnum + 1;
pos_bol = pos.pos_cnum;
}
}
let digit = ['0' - '9']
let integer = digit+
let letter = ['a' - 'z' 'A' - 'Z']
let identifier = letter ( letter | digit | '_')*
let blank = [' ' '\t']+
let newLine = '\r' | '\n' | "\r\n"
rule token = parse
blank { token lexbuf }
| newLine { incr_line_number lexbuf; token lexbuf }
| integer as num { let number = int_of_string num in
LITINT number }
| '(' { OPENPAR }
| ')' { CLOSEPAR }
| ';' { SEMICOLON }
| "program " + identifier as id { PROGRAM (id) }
| "begin" { BEGIN }
| "end" { END }
| "if" { IF }
| "then" { THEN }
| "else" { ELSE }
| ":=" { ASSIGN }
| "and" { AND }
| "or" { OR }
| identifier as id { ID id }
| eof { EOF }
parser.mly
%{
open Ast (* Abstract Syntax Tree*)
%}
%token <int> LITINT
%token <string> PROGRAM
%token <string> ID
%token BEGIN END
%token SEMICOLON
%token ASSIGN
%token IF THEN ELSE
%token OPENPAR CLOSEPAR
%token AND OR
%token EOF
%left OR
%left AND
%start program
%type <Ast.program> program
%%
program: prog=PROGRAM SEMICOLON
c = command*
EOF
{ Program (prog, List.flatten c) }
command: c = assignment_cmd { c }
| c = if_cmd { c }
| BEGIN cs=command+ END SEMICOLON { Block cs }
assignment_cmd: id = ID ASSIGN e = expression { AssignmentCmd (id, e) }
if_cmd: IF e=expression THEN
c1=command
s=option(ELSE c2=command {c2})
{ IfCmd (e, c1, s) }
expression: id=ID { ExpVar id }
| i=LITINT { ExpInt i }
| e1=expression op=oper e2=expression { ExpOp (op, e1, e2) }
| OPENPAR e=expression CLOSEPAR { e }
%inline oper:
| AND { And }
| OR { Or }
ast.ml
type ident = string
type program = Program of ident * commands
and commands = command list
and command = AssignmentCmd of ident * expression
| IfCmd of expression * command * (command option)
| Block of commands
and expression = ExpVar of ident
| ExpInt of int
| ExpOp of oper * expression * expression
and oper =
| And
| Or
main.ml
open Ast
let parse_file name =
let ic = open_in name in
let lexbuf = Lexing.from_channel ic in
let ast = Parser.program Lexer.token lexbuf in
let _ = close_in ic in
ast