vm/router: minimal special-method extension (equals/1); toString mapping kept
mir: add TypeCertainty to Callee::Method (diagnostic only); plumb through builder/JSON/printer; backends ignore behaviorally using: confirm unified prelude resolver entry for all runner modes docs: update Callee architecture with certainty; update call-instructions; CURRENT_TASK note tests: quick 40/40 PASS; integration (LLVM) 17/17 PASS
This commit is contained in:
@ -2,8 +2,9 @@
|
||||
// 80/20ルール適用: まず動くもの → 後で最適化
|
||||
// 美しいモジュラー設計: Utilsを活用してDRY原則を実践
|
||||
|
||||
using "apps/lib/json_native/utils/string.nyash" as StringUtils
|
||||
using "apps/lib/json_native/utils/escape.nyash" as EscapeUtils
|
||||
// NOTE: relative paths to support alias packaging (nyash.toml)
|
||||
using "../utils/string.nyash" as StringUtils
|
||||
using "../utils/escape.nyash" as EscapeUtils
|
||||
// EscapeUtils は必要時に遅延includeする(一部構文が未対応環境でも数値系は動かすため)
|
||||
|
||||
// 🌟 JSON値を表現するBox(Everything is Box原則)
|
||||
|
||||
@ -303,6 +303,10 @@ box JsonScanner {
|
||||
if ch == "\"" {
|
||||
// 終了クォート
|
||||
me.advance()
|
||||
// Safety: literal must include both quotes → length >= 2
|
||||
if me.position - start_pos < 2 {
|
||||
return null
|
||||
}
|
||||
return me.text.substring(start_pos, me.position)
|
||||
} else {
|
||||
if ch == "\\" {
|
||||
|
||||
@ -1,9 +1,10 @@
|
||||
// JsonTokenizer — 精度重視の字句解析器(yyjson相当精度)
|
||||
// 責務: 文字列をトークン列に変換、エラー検出、位置情報管理
|
||||
|
||||
using "apps/lib/json_native/lexer/scanner.nyash" as JsonScanner
|
||||
using "apps/lib/json_native/lexer/token.nyash" as JsonToken
|
||||
using "apps/lib/json_native/utils/escape.nyash" as EscapeUtils
|
||||
// NOTE: relative paths to support alias packaging (nyash.toml)
|
||||
using "./scanner.nyash" as JsonScanner
|
||||
using "./token.nyash" as JsonToken
|
||||
using "../utils/escape.nyash" as EscapeUtils
|
||||
// Removed other dependencies - using self-contained methods
|
||||
|
||||
// 🎯 高精度JSONトークナイザー(Everything is Box)
|
||||
@ -85,28 +86,40 @@ box JsonTokenizer {
|
||||
local start_col = me.scanner.get_column()
|
||||
local ch = me.scanner.current()
|
||||
|
||||
// 構造文字(単一文字)
|
||||
local structural_type = me.char_to_token_type(ch)
|
||||
if structural_type != null {
|
||||
me.scanner.advance()
|
||||
return this.create_structural_token(structural_type, start_pos).set_line_column(start_line, start_col)
|
||||
}
|
||||
|
||||
// 文字列リテラル
|
||||
// print("DBG ch=" + ch)
|
||||
if ch == "\"" {
|
||||
// print("BR string")
|
||||
return me.tokenize_string().set_line_column(start_line, start_col)
|
||||
}
|
||||
|
||||
// 数値リテラル
|
||||
if me.is_number_start_char(ch) {
|
||||
// print("BR number")
|
||||
return me.tokenize_number().set_line_column(start_line, start_col)
|
||||
}
|
||||
|
||||
// キーワード(null, true, false)
|
||||
if me.is_alpha_char(ch) {
|
||||
// print("BR alpha-t")
|
||||
return me.tokenize_keyword().set_line_column(start_line, start_col)
|
||||
}
|
||||
// Fallback(堅牢化): スキャナー側の is_alpha_char が true の場合はキーワードとして扱う
|
||||
if me.scanner.is_alpha_char != null and me.scanner.is_alpha_char(ch) {
|
||||
// print("BR alpha-fallback")
|
||||
return me.tokenize_keyword().set_line_column(start_line, start_col)
|
||||
}
|
||||
|
||||
// 構造文字(単一文字) — 最後に評価(誤検知回避)
|
||||
local structural_type = me.char_to_token_type(ch)
|
||||
if structural_type != null {
|
||||
// Dev trace (default commented): uncomment to debug structural tokens
|
||||
// print("[JsonTokenizer] structural '" + ch + "' => " + structural_type + " at pos=" + start_pos)
|
||||
me.scanner.advance()
|
||||
return this.create_structural_token(structural_type, start_pos).set_line_column(start_line, start_col)
|
||||
}
|
||||
|
||||
// print("BR error")
|
||||
// 不明な文字(エラー)
|
||||
me.scanner.advance()
|
||||
return new JsonToken("ERROR", "Unexpected character: '" + ch + "'", start_pos, me.scanner.get_position()).set_line_column(start_line, start_col)
|
||||
@ -119,7 +132,8 @@ box JsonTokenizer {
|
||||
local start_pos = me.scanner.get_position()
|
||||
local literal = me.scanner.read_string_literal()
|
||||
|
||||
if literal == null {
|
||||
// Robust guard: require quoted literal ("…")
|
||||
if literal == null or literal.length() < 2 or not (literal.substring(0, 1) == "\"") {
|
||||
return new JsonToken("ERROR", "Unterminated string literal", start_pos, me.scanner.get_position())
|
||||
}
|
||||
|
||||
@ -353,17 +367,17 @@ box JsonTokenizer {
|
||||
return str.length() >= 0 // 基本的な存在チェックのみ
|
||||
}
|
||||
|
||||
// 文字からトークンタイプを判定
|
||||
// 文字からトークンタイプを判定(環境依存の indexOf を使わず、直接比較)
|
||||
char_to_token_type(ch) {
|
||||
return match ch {
|
||||
"{" => "LBRACE",
|
||||
"}" => "RBRACE",
|
||||
"[" => "LBRACKET",
|
||||
"]" => "RBRACKET",
|
||||
"," => "COMMA",
|
||||
":" => "COLON",
|
||||
_ => null
|
||||
}
|
||||
if ch == null { return null }
|
||||
if ch.length() != 1 { return null }
|
||||
if ch == "{" { return "LBRACE" }
|
||||
if ch == "}" { return "RBRACE" }
|
||||
if ch == "[" { return "LBRACKET" }
|
||||
if ch == "]" { return "RBRACKET" }
|
||||
if ch == "," { return "COMMA" }
|
||||
if ch == ":" { return "COLON" }
|
||||
return null
|
||||
}
|
||||
|
||||
// 数値開始文字判定
|
||||
|
||||
@ -1,10 +1,11 @@
|
||||
// JsonParser — 精度重視の構文解析器(yyjson相当精度)
|
||||
// 責務: トークン列をJsonNodeに変換、構文エラー検出、ネスト構造処理
|
||||
|
||||
using "apps/lib/json_native/lexer/tokenizer.nyash" as JsonTokenizer
|
||||
using "apps/lib/json_native/lexer/token.nyash" as TokenType
|
||||
using "apps/lib/json_native/core/node.nyash" as JsonNode
|
||||
using "apps/lib/json_native/utils/string.nyash" as StringUtils
|
||||
// NOTE: use paths relative to this file to work under nyash.toml alias packaging
|
||||
using "../lexer/tokenizer.nyash" as JsonTokenizer
|
||||
using "../lexer/token.nyash" as TokenType
|
||||
using "../core/node.nyash" as JsonNode
|
||||
using "../utils/string.nyash" as StringUtils
|
||||
|
||||
// 🎯 高精度JSON構文解析器(Everything is Box)
|
||||
static box JsonParserModule {
|
||||
@ -13,6 +14,12 @@ static box JsonParserModule {
|
||||
}
|
||||
}
|
||||
|
||||
// Dev-only lightweight trace helper (default OFF)
|
||||
static box JsonParserTrace {
|
||||
// Dev logger (disabled by default; enable ad-hoc during manual probes)
|
||||
log(msg) { /* print("[JsonParser] " + msg) */ }
|
||||
}
|
||||
|
||||
box JsonParser {
|
||||
tokens: ArrayBox // トークン配列
|
||||
position: IntegerBox // 現在のトークン位置
|
||||
@ -112,7 +119,7 @@ box JsonParser {
|
||||
parse_number() {
|
||||
local token = me.current_token()
|
||||
if token == null or token.get_type() != "NUMBER" {
|
||||
me.add_error("Expected number token")
|
||||
me.add_error_expected("NUMBER")
|
||||
return null
|
||||
}
|
||||
|
||||
@ -137,7 +144,7 @@ box JsonParser {
|
||||
parse_string() {
|
||||
local token = me.current_token()
|
||||
if token == null or token.get_type() != "STRING" {
|
||||
me.add_error("Expected string token")
|
||||
me.add_error_expected("STRING")
|
||||
return null
|
||||
}
|
||||
|
||||
@ -154,12 +161,14 @@ box JsonParser {
|
||||
me.add_error("Expected '{' to start object")
|
||||
return null
|
||||
}
|
||||
JsonParserTrace.log("enter object at pos=" + me.position)
|
||||
me.advance() // '{'を消費
|
||||
|
||||
|
||||
local object_node = JsonNode.create_object()
|
||||
|
||||
|
||||
// 空オブジェクトチェック
|
||||
if me.match_token(TokenType.RBRACE()) {
|
||||
JsonParserTrace.log("empty object -> {}")
|
||||
return object_node
|
||||
}
|
||||
|
||||
@ -168,41 +177,43 @@ box JsonParser {
|
||||
// キー解析
|
||||
local key_token = me.current_token()
|
||||
if key_token == null or key_token.get_type() != "STRING" {
|
||||
me.add_error("Expected string key in object")
|
||||
me.add_error_expected("STRING (object key)")
|
||||
return null
|
||||
}
|
||||
local key = key_token.get_value()
|
||||
me.advance()
|
||||
|
||||
|
||||
// コロン
|
||||
if not me.match_token("COLON") {
|
||||
me.add_error("Expected ':' after object key")
|
||||
me.add_error_expected("COLON ':' after object key")
|
||||
return null
|
||||
}
|
||||
|
||||
|
||||
// 値解析
|
||||
local value = me.parse_value()
|
||||
if value == null {
|
||||
return null // エラーは既に記録済み
|
||||
}
|
||||
|
||||
|
||||
// オブジェクトに追加
|
||||
object_node.object_set(key, value)
|
||||
|
||||
|
||||
// 継続判定
|
||||
if me.match_token("COMMA") {
|
||||
// 次のキー・値ペアに続く
|
||||
JsonParserTrace.log("object comma → next pair")
|
||||
continue
|
||||
} else {
|
||||
if me.match_token("RBRACE") {
|
||||
JsonParserTrace.log("exit object at pos=" + me.position)
|
||||
break // オブジェクト終了
|
||||
} else {
|
||||
me.add_error("Expected ',' or '}' in object")
|
||||
me.add_error_expected("',' or '}' in object")
|
||||
return null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return object_node
|
||||
}
|
||||
|
||||
@ -213,12 +224,14 @@ box JsonParser {
|
||||
me.add_error("Expected '[' to start array")
|
||||
return null
|
||||
}
|
||||
JsonParserTrace.log("enter array at pos=" + me.position)
|
||||
me.advance() // '['を消費
|
||||
|
||||
|
||||
local array_node = JsonNode.create_array()
|
||||
|
||||
|
||||
// 空配列チェック
|
||||
if me.match_token("RBRACKET") {
|
||||
JsonParserTrace.log("empty array -> []")
|
||||
return array_node
|
||||
}
|
||||
|
||||
@ -232,21 +245,23 @@ box JsonParser {
|
||||
|
||||
// 配列に追加
|
||||
array_node.array_push(value)
|
||||
|
||||
|
||||
// 継続判定
|
||||
if me.match_token("COMMA") {
|
||||
// 次の要素に続く
|
||||
JsonParserTrace.log("array comma → next element")
|
||||
continue
|
||||
} else {
|
||||
if me.match_token("RBRACKET") {
|
||||
JsonParserTrace.log("exit array at pos=" + me.position)
|
||||
break // 配列終了
|
||||
} else {
|
||||
me.add_error("Expected ',' or ']' in array")
|
||||
me.add_error_expected("',' or ']' in array")
|
||||
return null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return array_node
|
||||
}
|
||||
|
||||
@ -292,6 +307,16 @@ box JsonParser {
|
||||
|
||||
// ===== エラー処理メソッド =====
|
||||
|
||||
// 期待/実トークンを含む詳細エラーを追加
|
||||
add_error_expected(expected) {
|
||||
local tok = me.current_token()
|
||||
local got = "EOF"
|
||||
if tok != null {
|
||||
got = tok.get_type() + "(" + tok.get_value() + ")"
|
||||
}
|
||||
me.add_error("Expected " + expected + ", got: " + got)
|
||||
}
|
||||
|
||||
// エラーを追加
|
||||
add_error(message) {
|
||||
local token = me.current_token()
|
||||
|
||||
Reference in New Issue
Block a user