Ich bin ein kompletter Neuling, wenn es um OCaml geht. Ich habe erst vor kurzem mit der Sprache angefangen (vor ungefähr 2 Wochen), aber leider wurde ich damit beauftragt, einen Syntaxanalysator (Parser + Lexer, dessen Funktion es ist, einen Satz zu akzeptieren oder nicht) für eine erfundene Sprache zu machen Menhir verwenden. Nun habe ich im Internet einige Materialien zu OCaml und Menhir gefunden:OCaml + Menhir Kompilieren/Schreiben
Das Menhir Manual.
This webpage for some French University course.
Ein kurzer Menhir Tutorial auf Toss der Homepage bei Source.
Ein Menhir-Beispiel auf GitHub von DerDon.
A book on OCaml (with a few things about ocamllex+ocamlyacc
Eine zufällige ocamllex Tutorial von SooHyoung Oh.
Und die Beispiele, die mit Menhirs Quellcode kommen.
(Ich kann nicht mehr als zwei Hyperlinks setzen, so kann ich Ihnen nicht direkt verlinkt auf einige der Websites ich hier zu erwähnen. Es tut uns Leid!)
So, wie Sie sehen können, ich Ich habe verzweifelt nach mehr und mehr Material gesucht, um mir bei der Erstellung dieses Programms zu helfen. Leider kann ich immer noch nicht viele Konzepte erfassen, und als solche habe ich viele, viele Schwierigkeiten.
Für den Anfang habe ich keine Ahnung, wie ich mein Programm richtig kompiliere. Ich habe den folgenden Befehl unter Verwendung von:
ocamlbuild -use-menhir -menhir "menhir --external-tokens Tokens" main.native
Mein Programm in vier verschiedenen Dateien aufgeteilt: main.ml; lexer.mll; parser.mly; Token. main.ml ist der Teil, der Eingaben von einer Datei im Dateisystem erhält, die als Argument angegeben ist.
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)
Die zweite Datei ist 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))) }
Die dritte Datei ist parser.mly.
%start <bool> main
%%
main:
| WRITEINT INT { true }
Der vierte ist 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
%}
%%
Nun, ich weiß, es gibt eine Menge von nicht verwendeten Symbole ist hier, aber ich beabsichtige, sie in meinem Parser zu verwenden. Egal wie viele Änderungen ich an den Dateien mache, der Compiler bläht sich immer wieder auf meinem Gesicht auf. Ich habe alles versucht, was mir einfällt, und nichts scheint zu funktionieren. Was macht ocamlbuild in einer Fülle von Fehlern von ungebundenen Konstruktoren und nicht definierten Startsymbolen explodieren? Welchen Befehl sollte ich verwenden, um das Programm richtig zu kompilieren? Wo kann ich aussagekräftige Materialien über Menhir finden?
In der Tat ist es einfacher, nur einen 'mly' zu haben. Ich habe diese Lösung in meiner Antwort nicht vorgeschlagen, weil ich annahm, dass @Lopson die Funktion "separate Compilation of Parsing Units" von Menhir verwenden wollte. – Thomas
Danke für all die Hilfe, Leute, du hast keine Ahnung, wie wertvoll deine Beiträge für mich waren! Schließlich fangen die Dinge an, einen Sinn zu ergeben. –