Commit Graph
2 Commits
Author SHA1 Message Date
coolguyandClaude Opus 5 91f3840d19 lint: 파서 오류 복구와 두 lint — 남은 부채를 턴다
파서 오류 복구:
항목 단위로만 회복한다. 문 단위로 더 잘게 회복하려 하면 파서가 추측을
하게 되고, 틀린 추측은 없는 오류를 지어낸다. 한 항목에 오류 하나가
상한이라는 것은 정직한 한계다. 동기화 지점은 중괄호 깊이 0 + 줄 첫머리
+ 선언 시작 토큰 — 셋 다 필요하다. 본문 안의 fn을 새 항목으로 오인하면
그 뒤가 전부 어긋난다. 샘플 08이 이제 오류 넷을 한 번에 보고한다.

두 lint (취향이 아니라 비용이다):
- 미사용 import는 재검사 범위를 넓힌다. 쓰지 않는 모듈의 시그니처가
  바뀌면 이 모듈이 재검사된다.
- effect 과잉 선언은 호출자에게 없는 의무를 지운다. 시그니처는 실제보다
  좁아도 안 되고 넓어도 안 된다.

과잉 선언은 effect 변수가 있거나 본문에 모르는 이름이 있으면 판정하지
않는다. 첫 구현이 샘플 03/06을 오탐으로 잡았는데, 원인이 외부 타입이었다
— 외부 capability의 메서드는 effect를 모르므로 "수행하지 않았다"고 말할
근거가 없다. saw_unknown으로 판정을 보류한다.

Resolve.error에 blocking을 나눴다. 이름 해소 실패는 뒤 단계를 막지만
lint는 막지 않는다 — lint 하나가 진짜 타입 오류를 가리면 루프가 느려진다.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019ZVDeU6KLuUVL3gs18Hm3E
2026-08-30 15:53:35 +09:00
coolguyandClaude Opus 5 1bd88fc4d7 parser: 재귀 하강 구문 분석기와 AST
grammar.ebnf의 프로덕션 하나에 함수 하나로 대응한다. LL(1)이므로 선읽기는
항상 한 토큰이고 backtracking이 없다. 모든 노드가 위치를 들고 다닌다.

문법과 얽히는 두 자리를 원칙대로 처리했다:
- NEWLINE 흡수는 문법에 { NEWLINE }으로 적힌 자리에서만 한다. 파서가
  "여기선 줄바꿈 무시" 식으로 임의 판단하면 어디서 무시되는지 아무도 모르게
  된다.
- struct 리터럴은 if/match/scope 머리에서 금지하고(no_struct), 괄호·인자
  목록·블록에 들어가면 다시 허용한다.

문법에 새긴 제한이 실제로 파서에서 죽는 것을 확인했다. 파라미터 위치의
effect 합집합과 match 가드는 검사기가 아니라 파서가 거부하며, 진단이
원인을 직접 말한다. 후행 콤마 누락도 일반적인 "닫는 괄호 필요" 대신
"다중 줄 목록에는 후행 콤마가 필요합니다"로 보고한다.

샘플을 실제로 파싱해 두 가지를 잡았다:
- 02와 05가 own을 타입 위치에 쓰고 있었다. 확정한 규칙은 바인딩 수식어가
  이름 앞이므로 샘플이 틀렸다. 수정.
- 05에 구문 오류와 검사기 오류가 섞여 있었다. 파서가 첫 오류에서 멈추면
  검사기 케이스에 영영 도달하지 못하므로 08_syntax_errors.cool로 분리.

grammar.ebnf를 구현과 맞췄다: 제네릭 인자에 effect 집합 허용, 마지막 문의
구분자는 "}" 앞에서 생략, 중괄호 목록 안의 NEWLINE 흡수 위치 명시.

cool ast 추가. cool check는 이제 파서까지 돌리되 여전히 통과했다고 말하지
않는다.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019ZVDeU6KLuUVL3gs18Hm3E
2026-08-30 02:26:01 +09:00