Ошибка Eof Ocaml
Я делаю компилятор для класса в Ocaml. Мне нужно прочитать файл с командами или выражениями типа "1", а затем он возвращает Int 1. Тот же код работал со всем классом, за исключением меня и моего друга. Все используют одну и ту же версию ocaml и Ubuntu 13.04. Ошибка: Lexico.Eof
Кто-нибудь имеет представление о том, что это может быть? Это asa.ml:
type opB =
| Soma
| Sub
| Mul
| Div
type exp =
| Int of int
| Float of float
| String of string
| Char of char
| Identificador of string
| Bin of opB * exp * exp
Это Sintatico.mly:
%{
open Asa;;
%}
%token <int> INT
%token <float> FLOAT
%token <string> STRING
%token <char> CHAR
%token <string> IDENTIFICADOR
%token APAREN FPAREN PTVIRG
%token MAIS MENOS MUL DIV
%left MAIS MENOS
%left MUL DIV
%start main
%type <Asa.exp> main
%%
main: expr { $1 }
;
expr: IDENTIFICADOR { Identificador($1) }
| INT { Int($1) }
| FLOAT { Float($1) }
| STRING { String($1) }
| CHAR { Char($1) }
| APAREN expr FPAREN { $2 }
| expr MAIS expr { Bin(Soma, $1, $3) }
| expr MENOS expr { Bin(Sub, $1, $3) }
| expr MUL expr { Bin(Mul, $1, $3) }
| expr DIV expr { Bin(Div, $1, $3) }
;
The Lexico.mll:
{
open String
open Sintatico
exception Eof
}
let digito = ['0'-'9']
let caracter = [^ '\n' '\t' '\b' '\r' '\'' '\\']
let identificador = ['a'-'z' 'A'-'Z']['a'-'z' '0'-'9']*
rule token = parse
| [' ' '\t' '\n'] { token lexbuf } (* ignora os espacos *)
| digito+ as inum { print_string " int "; INT (int_of_string inum) }
| digito+'.'digito+ as fnum { print_string " float "; FLOAT (float_of_string fnum) }
| '\"' ([^ '"']* as s) '\"' { print_string " string "; STRING (s)}
| '\'' caracter '\'' as ch { print_string " char "; CHAR (String.get ch 1) }
| identificador as id { print_string " identificador "; IDENTIFICADOR (id) }
| '(' { print_string " abreparent "; APAREN }
| ')' { print_string " fechaparent "; FPAREN }
| '+' { print_string " + "; MAIS }
| '-' { print_string " - "; MENOS }
| '*' { print_string " * "; MUL }
| '/' { print_string " / "; DIV }
| ';' { print_string " ptv "; PTVIRG }
| eof { raise Eof }
Код для вызова файла с именем carregatudo.ml:
#load "asa.cmo"
#load "sintatico.cmo"
#load "lexico.cmo"
open Asa;;
let analisa_arquivo arquivo =
let ic = open_in arquivo in
let lexbuf = Lexing.from_channel ic in
let asa = Sintatico.main Lexico.token lexbuf in
close_in ic;
asa
Извините за португальский:
Arquivo означает файл
Лексико означает Лексер
Sintatico означает Parser
Сначала я запускаю этот make-файл с помощью команды make interpretador:
CAMLC = ocamlc
CAMLLEX = ocamllex
CAMLYACC = ocamlyacc
interpretador: asa.cmo sintatico.cmi sintatico.cmo lexico.cmo
portugol: asa.cmo sintatico.cmi sintatico.cmo lexico.cmo principal.cmo
clean:
rm *.cmo *.cmi
# regras genericas
.SUFFIXES: .mll .mly .mli .ml .cmi .cmo .cmx
.mll.mli:
$(CAMLLEX) $<
.mll.ml:
$(CAMLLEX) $<
.mly.mli:
$(CAMLYACC) $<
.mly.ml:
$(CAMLYACC) $<
.mli.cmi:
$(CAMLC) -c $(FLAGS) $<
.ml.cmo:
$(CAMLC) -c $(FLAGS) $<
И затем carregatudo.ml: #use "carregatudo.ml";;
Следующая функция: analisa_arquivo("teste.pt");;
Входной файл teste.pt выглядит так:
1
и возвращение должно быть
Int 1
Но я продолжаю получать ошибку Lexico.Eof
Спасибо!
1 ответ
Парсер использует более одного токена для проверки соответствия рекурсивных правил, что вполне естественно вызывает Eof
быть воспитанным. По сути, ваш синтаксический анализатор работает за концом файла, потому что в нем отсутствуют какие-либо правила, которые бы указывали ему, когда прекратить искать другие части выражения.
Легко исправить это изменить Eof
исключение из токена END_OF_INPUT
и сопоставьте это с грамматикой:
main: expr END_OF_INPUT { $1 }
В качестве альтернативы вы можете ввести явный терминатор, такой как ;
,