Je suis un débutant complet quand il s'agit de OCaml. J'ai récemment commencé à utiliser la langue (il y a environ 2 semaines), mais malheureusement, j'ai été chargé de faire un analyseur de syntaxe (parser + lexer, dont la fonction est d'accepter ou non une phrase) pour un langage inventé en utilisant Menhir. Maintenant, j'ai trouvé quelques documents sur Internet concernant OCaml et Menhir:OCaml + Menhir Compilation/écriture
Le Manuel Menhir.
This webpage for some French University course.
Un court tutoriel Menhir sur la page d'accueil de Toss à Sourceforge.
Un exemple de Menhir sur github par derdon.
A book on OCaml (with a few things about ocamllex+ocamlyacc
Un tutoriel ocamllex par hasard SooHyoung Oh.
Et les exemples fournis avec le code source de Menhir.
(je ne peux pas mettre plus de deux liens hypertexte, donc je ne peux pas vous relier directement à certains des sites Web je mentionner ici. Désolé!)
Donc, comme vous pouvez le voir, je J'ai cherché désespérément de plus en plus de matériel pour m'aider dans la réalisation de ce programme. Malheureusement, je n'arrive toujours pas à saisir de nombreux concepts et, en tant que tel, j'ai beaucoup, beaucoup de difficultés.
Pour commencer, je ne sais pas comment compiler correctement mon programme. J'ai utilisé la commande suivante:
ocamlbuild -use-menhir -menhir "menhir --external-tokens Tokens" main.native
Mon programme est divisé en quatre fichiers différents: main.ml; lexer.mll; parser.mly; tokens.mly. main.ml est la partie qui reçoit l'entrée d'un fichier dans le système de fichiers donné en argument.
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)
Le deuxième fichier est 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))) }
Le troisième fichier est parser.mly.
%start <bool> main
%%
main:
| WRITEINT INT { true }
Le quatrième est 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
%}
%%
Maintenant, je sais qu'il ya beaucoup de symboles inutilisés ici, mais je l'intention de les utiliser dans mon analyseur. Peu importe le nombre de modifications que je fais pour les fichiers, le compilateur continue à exploser sur mon visage. J'ai essayé tout ce que je peux penser, et rien ne semble fonctionner. Qu'est-ce qui fait qu'ocamlbuild explose dans une pléthore d'erreurs de constructeurs non liés et de symboles de départ non définis? Quelle commande dois-je utiliser pour compiler correctement le programme? Où puis-je trouver des documents significatifs sur Menhir?
En effet, avoir un seul 'mly' est beaucoup plus simple. Je n'ai pas proposé cette solution dans ma réponse parce que je supposais que @Lopson voulait utiliser la fonction «compilation séparée des unités d'analyse» du menhir. – Thomas
Merci pour toute l'aide, les gars, vous n'avez aucune idée de la valeur de vos messages pour moi! Finalement, les choses commencent à avoir du sens. –