recognize: 문법이 직접 읽는 인식기 — 파서와 판정을 대조한다
lib/recognize.ml은 docs/grammar.ebnf를 그대로 해석해 토큰 열을 받아들일지 판정한다. AST를 만들지 않는다 — 판정만 하므로 손 파서의 진단은 그대로 남는다. 문법이 LL(1)임을 이미 검증했으므로 선택이 결정적이다. 다음 토큰이 어느 대안의 FIRST에 있는지만 보고 되돌아가지 않는다. 같은 토큰 열을 손 파서와 인식기 양쪽에 주고 판정이 갈리는지 테스트가 검사한다. 저장소의 .cool 25개 전부에서 일치한다. 갈리면 빌드가 깨진다. 이제 "설명서를 잘 관리하자"에 기대지 않는다. 그 방법은 이미 실패했다 — 설명서가 어긋났고 아무도 몰랐고 나조차 안 읽었다. 확인: 문법에서 한정 이름(named_type의 "." ident)을 빼 보면 즉시 "파서는 받고 문법은 거부"가 두 파일에서 잡힌다. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019ZVDeU6KLuUVL3gs18Hm3E
This commit is contained in:
@@ -6,7 +6,52 @@ let read file =
|
||||
close_in ic;
|
||||
s
|
||||
|
||||
(* 문법과 손 파서를 같은 파일에 돌려 판정이 갈리는지 본다 *)
|
||||
let compare_files files =
|
||||
let g =
|
||||
match Coollang.Ebnf.parse_result (read "docs/grammar.ebnf") with
|
||||
| Ok g -> g
|
||||
| Error e -> failwith (Printf.sprintf "문법 %d행: %s" e.line e.msg)
|
||||
in
|
||||
let tokens =
|
||||
[ "ident"; "int_lit"; "string_lit"; "NEWLINE"; "char"; "digit"; "letter" ]
|
||||
in
|
||||
let bad = ref 0 in
|
||||
List.iter
|
||||
(fun f ->
|
||||
match Coollang.Lexer.lex_result (read f) with
|
||||
| Error e -> Printf.printf " 렉서 오류 %s:%d:%d %s\n" f e.pos.line e.pos.col e.msg
|
||||
| Ok toks ->
|
||||
let hand =
|
||||
match Coollang.Parser.parse_result toks with
|
||||
| Ok _ -> None
|
||||
| Error e -> Some (e.pos, e.msg)
|
||||
in
|
||||
let spec =
|
||||
match Coollang.Recognize.check ~tokens g toks with
|
||||
| Ok () -> None
|
||||
| Error e ->
|
||||
Some (e.pos, Printf.sprintf "%s이(가) 필요한데 %s" e.expected e.got)
|
||||
in
|
||||
(match (hand, spec) with
|
||||
| None, None -> ()
|
||||
| Some _, Some _ -> ()
|
||||
| None, Some (p, m) ->
|
||||
incr bad;
|
||||
Printf.printf "갈림 %s: 파서는 받고 문법은 거부 (%d:%d %s)\n" f
|
||||
p.Coollang.Token.line p.Coollang.Token.col m
|
||||
| Some (p, m), None ->
|
||||
incr bad;
|
||||
Printf.printf "갈림 %s: 문법은 받고 파서는 거부 (%d:%d %s)\n" f
|
||||
p.Coollang.Token.line p.Coollang.Token.col m))
|
||||
files;
|
||||
Printf.printf "\n파일 %d개 중 판정이 갈린 것 %d개\n" (List.length files) !bad;
|
||||
if !bad > 0 then exit 1
|
||||
|
||||
let () =
|
||||
if Array.length Sys.argv > 2 && Sys.argv.(1) = "--compare" then (
|
||||
compare_files (Array.to_list (Array.sub Sys.argv 2 (Array.length Sys.argv - 2)));
|
||||
exit 0);
|
||||
if Array.length Sys.argv > 1 && Sys.argv.(1) = "--lexical" then (
|
||||
print_string (Coollang.Lexical_doc.render ());
|
||||
print_newline ();
|
||||
|
||||
Reference in New Issue
Block a user