(* 토큰 정의. 위치는 진단 품질이 헌법급이므로 모든 토큰이 들고 다닌다. *) type pos = { line : int; col : int } type kind = (* 리터럴과 이름 *) | Ident of string | Int of string | Str of string (* 키워드 *) | Kw_pub | Kw_fn | Kw_struct | Kw_enum | Kw_capability | Kw_const | Kw_import | Kw_as | Kw_reexport | Kw_let | Kw_mut | Kw_own | Kw_affine | Kw_copyable | Kw_effects | Kw_return | Kw_if | Kw_else | Kw_match | Kw_scope | Kw_true | Kw_false (* 구두점 *) | LParen | RParen | LBrace | RBrace | LBracket | RBracket | Comma | Colon | Dot | Arrow | FatArrow | Question | Underscore | Eq | EqEq | Bang | BangEq | Lt | Le | Gt | Ge | Plus | Minus | Star | Slash | Percent | AmpAmp | PipePipe | Pipe (* 렉서가 삽입하는 문 구분자 *) | Newline | Eof type t = { kind : kind; pos : pos } let keyword = function | "pub" -> Some Kw_pub | "fn" -> Some Kw_fn | "struct" -> Some Kw_struct | "enum" -> Some Kw_enum | "capability" -> Some Kw_capability | "const" -> Some Kw_const | "import" -> Some Kw_import | "as" -> Some Kw_as | "reexport" -> Some Kw_reexport | "let" -> Some Kw_let | "mut" -> Some Kw_mut | "own" -> Some Kw_own | "affine" -> Some Kw_affine | "copyable" -> Some Kw_copyable | "effects" -> Some Kw_effects | "return" -> Some Kw_return | "if" -> Some Kw_if | "else" -> Some Kw_else | "match" -> Some Kw_match | "scope" -> Some Kw_scope | "true" -> Some Kw_true | "false" -> Some Kw_false | _ -> None let show_kind = function | Ident s -> Printf.sprintf "이름 %s" s | Int s -> Printf.sprintf "정수 %s" s | Str _ -> "문자열" | Kw_pub -> "pub" | Kw_fn -> "fn" | Kw_struct -> "struct" | Kw_enum -> "enum" | Kw_capability -> "capability" | Kw_const -> "const" | Kw_import -> "import" | Kw_as -> "as" | Kw_reexport -> "reexport" | Kw_let -> "let" | Kw_mut -> "mut" | Kw_own -> "own" | Kw_affine -> "affine" | Kw_copyable -> "copyable" | Kw_effects -> "effects" | Kw_return -> "return" | Kw_if -> "if" | Kw_else -> "else" | Kw_match -> "match" | Kw_scope -> "scope" | Kw_true -> "true" | Kw_false -> "false" | LParen -> "(" | RParen -> ")" | LBrace -> "{" | RBrace -> "}" | LBracket -> "[" | RBracket -> "]" | Comma -> "," | Colon -> ":" | Dot -> "." | Arrow -> "->" | FatArrow -> "=>" | Question -> "?" | Underscore -> "_" | Eq -> "=" | EqEq -> "==" | Bang -> "!" | BangEq -> "!=" | Lt -> "<" | Le -> "<=" | Gt -> ">" | Ge -> ">=" | Plus -> "+" | Minus -> "-" | Star -> "*" | Slash -> "/" | Percent -> "%" | AmpAmp -> "&&" | PipePipe -> "||" | Pipe -> "|" | Newline -> "줄바꿈" | Eof -> "파일 끝" let show { kind; pos } = Printf.sprintf "%d:%d %s" pos.line pos.col (show_kind kind) (* 줄 끝에서 문 구분자를 삽입할지 결정한다 (grammar.ebnf 어휘 절). 값으로 끝날 수 있는 토큰 뒤에서만 삽입하므로, 연산자나 여는 괄호로 끝나는 줄은 다음 줄로 이어진다. *) let can_end_statement = function | Ident _ | Int _ | Str _ | RParen | RBracket | RBrace | Question | Kw_return | Kw_true | Kw_false -> true | _ -> false