Soy un completo novato en lo que respecta a OCaml. Recientemente comencé a usar el lenguaje (hace aproximadamente 2 semanas), pero desafortunadamente me han encargado hacer un analizador de sintaxis (analizador + lector, cuya función es aceptar o no una oración) para un lenguaje compuesto usando Menhir. Ahora, he encontrado algunos materiales en Internet sobre OCaml y Menhir:OCaml + Menhir Compilación/Escritura
The Menhir Manual.
This webpage for some French University course.
Un breve tutorial Menhir en la página de Toss en Sourceforge.
Un ejemplo de Menhir en github por derdon.
A book on OCaml (with a few things about ocamllex+ocamlyacc
Un tutorial ocamllex azar por SooHyoung Oh.
Y los ejemplos que vienen con el código fuente de Menhir.
(no puedo poner más de dos enlaces, por lo que no se puede vincular directamente a algunos de los sitios web que estoy mencionar aquí. Lo siento!)
Por lo tanto, como se puede ver, estoy he estado buscando desesperadamente más y más material para ayudarme en la realización de este programa. Desafortunadamente, todavía no puedo comprender muchos conceptos, y como tal, tengo muchas, muchas dificultades.
Para empezar, no tengo idea de cómo compilar correctamente mi programa. He estado usando el siguiente comando:
ocamlbuild -use-menhir -menhir "menhir --external-tokens Tokens" main.native
Mi programa se divide en cuatro archivos diferentes: main.ml; lexer.mll; parser.mly; tokens.mly. main.ml es la parte que obtiene entrada de un archivo en el sistema de archivos dado como argumento.
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)
El segundo archivo es 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))) }
El tercer archivo es parser.mly.
%start <bool> main
%%
main:
| WRITEINT INT { true }
El cuarto es 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
%}
%%
Ahora, sé que hay una gran cantidad de símbolos utilizados aquí, pero tengo la intención de utilizarlos en mi analizador. No importa cuántos cambios haga en los archivos, el compilador sigue explotando en mi cara. He intentado todo lo que puedo pensar, y nada parece funcionar. ¿Qué es lo que está haciendo explotar ocamlbuild en una plétora de errores de constructores independientes y símbolos de inicio no definidos? ¿Qué comando debería usar para compilar el programa correctamente? ¿Dónde puedo encontrar materiales significativos para aprender sobre Menhir?
De hecho, tener solo un 'mly' es mucho más simple. No he propuesto esa solución en mi respuesta porque suponía que @Lopson quería utilizar la función "compilación separada de unidades de análisis" de menhir. – Thomas
Gracias por toda la ayuda, muchachos, ¡no tienen idea de lo valiosos que fueron sus mensajes para mí! Finalmente, las cosas están empezando a tener algún sentido. –