У меня совершенно нет идей. Я трачу каждую свободную минуту на этот день, но у меня совершенно нет идей.
Это моя Ocamlyacc
грамматика:
input: /* empty */ { }
| input stmt { }
stmt:
extern { print_endline "Got an extern import" }
| func { print_endline "Got function definition" }
| call { print_endline "Got function call" }
extern:
EXTERN proto { Extern $2 }
func:
DEF proto expr { Function ($2, $3) }
proto:
IDENTIFIER LPAREN id_list RPAREN { print_endline "Got prototype definition"; Prototype ($1, $3) }
id_list:
/* empty */ { [] }
| IDENTIFIER { [$1] }
| id_list COMMA IDENTIFIER { $3 :: $1 }
expr_list:
/* empty */ { [] }
| expr { [$1] }
| expr_list COMMA expr { $3 :: $1 }
expr:
call { $1 }
| expr OP expr { Binary ($2, $1, $3) }
| IDENTIFIER { Variable $1 }
| NUMBER { Number $1 }
| LPAREN expr RPAREN { $2 }
call:
IDENTIFIER LPAREN expr_list RPAREN { Call ($1, $3) }
Когда я начинаю синтаксический анализ def foo(a,b) a+b
, он должен сказать, что получил функцию и объявление прототипа, согласно сообщениям отладки. Но вместо этого я получаю сообщение только при разборе правила proto
.
Дальнейшие сообщения отладки показывают, что синтаксический анализатор доходит до a
выражения a+b
и затем останавливается. Нет сообщения об ошибке, ничего больше. Он просто останавливается, как если бы весь текст был полностью разобран без соблюдения каких-либо правил в stmt
.
Нет ошибок сдвига / уменьшения или аналогичных. Типы AST также не являются проблемой. Я понятия не имею, может быть, кто-то еще может помочь. Конечно, это что-то очевидное, но я не вижу этого.
РЕДАКТИРОВАТЬ : Lexer по многочисленным просьбам:
{
open Parser
}
rule token = parse
| [' ' '\t' '\n'] { token lexbuf }
| "def" { DEF }
| "extern" { EXTERN }
| "if" { IF }
| "then" { THEN }
| "else" { ELSE }
| ['+' '-' '*' '/'] as c { OP c }
| ['A'-'Z' 'a'-'z'] ['A'-'Z' 'a'-'z' '0'-'9' '_']* as id { IDENTIFIER id }
| ['0'-'9']*'.'['0'-'9']+ as num { NUMBER (float_of_string num) }
| '(' { LPAREN }
| ')' { RPAREN }
| ',' { COMMA }
| '#' { comment lexbuf }
| _ { raise Parsing.Parse_error }
| eof { raise End_of_file }
and comment = parse
| '\n' { token lexbuf }
| _ { comment lexbuf }