OCaml에 관해서는 완전히 초보자입니다. 필자는 최근에 언어 사용을 시작했으나 (약 2 주 전), 유감스럽게도 구문 분석기 (parser + lexer, 함수가 문장을 수락할지 여부를 결정하는 것) Menhir 사용. 자, OCaml과 Menhir에 관한 인터넷 자료를 찾았습니다 :OCaml + Menhir 컴파일/작성
Menhir 매뉴얼.
This webpage for some French University course.
소스 포지에서 토스의 홈페이지에 짧은 선돌 튜토리얼
.github by derdon의 Menhir 예제.
A book on OCaml (with a few things about ocamllex+ocamlyacc
SooHyoung 오에 의해 임의의 ocamllex 튜토리얼.
Menhir의 소스 코드와 함께 제공되는 예제입니다.
(I 두 개 이상의 하이퍼 링크를 넣을 수 없습니다, 그래서 내가 여기에 언급하고있어 웹 사이트의 일부로 바로 링크 할 수 없습니다. 죄송합니다!)
그래서, 당신이 볼 수 있듯이, 내가 ' 이 프로그램을 만들 때 나를 돕기 위해 점점 더 많은 자료를 필사적으로 찾고있었습니다. 불행히도, 나는 아직도 많은 개념을 이해할 수 없으며, 따라서 많은 어려움을 겪고 있습니다.
처음에는 프로그램을 올바르게 컴파일하는 방법을 알지 못합니다. 나는 다음과 같은 명령을 사용하고있다 :
내 프로그램은 네 개의 서로 다른 파일에 나누어ocamlbuild -use-menhir -menhir "menhir --external-tokens Tokens" main.native
: main.ml을; lexer.mll; parser.mly; 토큰. main.ml은 인수로 주어진 파일 시스템의 파일로부터 입력을받는 부분입니다.
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)
두 번째 파일은 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))) }
세 번째 파일은 parser.mly입니다.
%start <bool> main
%%
main:
| WRITEINT INT { true }
네 번째 사람은 내가 사용하지 않는 문자를 많이 여기에있다 알아,하지만 난 내 파서에서 사용하고자하는, 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
%}
%%
입니다. 파일을 얼마나 많이 변경했는지에 상관없이 컴파일러는 계속 내 얼굴에 불어납니다. 나는 내가 생각할 수있는 모든 것을 시도했지만 아무 것도 효과가없는 것으로 보인다. 언 바운드 생성자와 정의되지 않은 시작 심볼의 과다한 오류에서 ocamlbuild를 폭발시키는 것은 무엇입니까? 프로그램을 제대로 컴파일하려면 어떤 명령을 사용해야합니까? Menhir에 관해 알아볼 수있는 의미있는 자료는 어디에서 찾을 수 있습니까?, ocamlbuild
에 전달할 그런 다음, 나는 마법의 옵션을 모르는
%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
%%
을 나는 아주 잘 menhir
를 모르는 :
사실 'mly'를 하나만 사용하면 훨씬 간단 해집니다. 필자는 @Lopson이 menhir의 "구문 분석 단위의 개별 컴파일"기능을 사용하기를 원했기 때문에이 해답을 제안하지 않았습니다. – Thomas
모든 도움을 주셔서 감사합니다, 얘들 아, 내게 얼마나 귀중한 게시물인지 모르 셨다! 마지막으로, 일들이 이해되기 시작합니다. –