Sono un novizio completo quando si tratta di OCaml. Recentemente ho iniziato a usare il linguaggio (circa 2 settimane fa), ma sfortunatamente, sono stato incaricato di creare un analizzatore di sintassi (parser + lexer, la cui funzione è accettare o meno una frase) per un linguaggio inventato usando Menhir. Ora, ho trovato alcuni materiali su Internet relativi a OCaml e Menhir:OCaml + Menhir Compiling/Writing
Il manuale di Menhir.
This webpage for some French University course.
Un breve tutorial Menhir sulla homepage di Toss a Sourceforge.
Un esempio di menhir su github by derdon.
A book on OCaml (with a few things about ocamllex+ocamlyacc
Un tutorial ocamllex casuale da SooHyoung Oh.
E gli esempi forniti con il codice sorgente di Menhir.
(non riesco a mettere più di due collegamenti ipertestuali, quindi non è possibile collegare direttamente ad alcuni dei siti web che sto citano qui. Spiacente!)
Quindi, come potete vedere, I' Ho cercato disperatamente sempre più materiale per aiutarmi nella realizzazione di questo programma. Sfortunatamente, non riesco ancora a cogliere molti concetti e, come tale, sto avendo molte, molte difficoltà.
Per i principianti, non ho idea di come compilare correttamente il mio programma. Sto usando il seguente comando:
ocamlbuild -use-menhir -menhir "menhir --external-tokens Tokens" main.native
Il mio programma è diviso in quattro file diversi: main.ml; lexer.mll; parser.mly; tokens.mly. main.ml è la parte che riceve un input da un file nel file system dato come argomento.
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)
Il secondo file è 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))) }
Il terzo file è parser.mly.
%start <bool> main
%%
main:
| WRITEINT INT { true }
Il quarto è 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
%}
%%
Ora, so che c'è un sacco di simboli inutilizzati qui, ma ho intenzione di usarli nel mio parser. Indipendentemente dal numero di modifiche apportate ai file, il compilatore continua a saltare in faccia. Ho provato tutto quello che riesco a pensare e niente sembra funzionare. Che cosa sta facendo esplodere ocamlbuild in una pletora di errori di costruttori non associati e simboli di inizio non definiti? Quale comando dovrei usare per compilare correttamente il programma? Dove posso trovare materiali significativi per conoscere Menhir?
Infatti, avere solo un 'mly' è molto più semplice. Non ho proposto questa soluzione nella mia risposta perché stavo partendo dal presupposto che @Lopson volesse utilizzare la funzione "compilazione separata delle unità di analisi" di menhir. – Thomas
Grazie per tutto l'aiuto, ragazzi, non avete idea di quanto siano preziosi i vostri post per me! Finalmente le cose cominciano a dare un senso. –