fix(stageb): ParserStmtBox skip_ws静的呼び出し化 - Phase 25.1

**変更内容**:
- ctx.skip_ws(src, j) → ParserStringUtilsBox.skip_ws(src, j) (20箇所)
  - ParserStmtBox.parse: 13箇所
  - ParserStmtBox.parse_using: 7箇所

**理由**:
- MIRレベルでctx(ParserBox instance)がString化する問題を根本回避
- 箱理論的に正しい設計: scan utility = static box統一
- Region+next_iパターンと一貫性維持(LoopForm v2設計準拠)

**影響範囲**:
- lang/src/compiler/parser/stmt/parser_stmt_box.hako のみ
- using追加: ParserStringUtilsBox

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
nyash-codex
2025-11-21 12:27:24 +09:00
parent b00cc8d579
commit 227ce61de8

View File

@ -6,6 +6,7 @@
using sh_core as StringHelpers // Required: using chain resolution not implemented using sh_core as StringHelpers // Required: using chain resolution not implemented
using lang.compiler.parser.stmt.parser_control_box using lang.compiler.parser.stmt.parser_control_box
using lang.compiler.parser.stmt.parser_exception_box using lang.compiler.parser.stmt.parser_exception_box
using lang.compiler.parser.scan.parser_string_utils_box as ParserStringUtilsBox
static box ParserStmtBox { static box ParserStmtBox {
parse(src, i, ctx) { parse(src, i, ctx) {
@ -21,7 +22,7 @@ static box ParserStmtBox {
env.set("HAKO_STAGEB_STMT_DEPTH", "1") env.set("HAKO_STAGEB_STMT_DEPTH", "1")
} }
} }
local j = ctx.skip_ws(src, i) local j = ParserStringUtilsBox.skip_ws(src, i)
// VM 差分で skip_ws が前進しないパスがあったため、手動で最小限の空白スキップをフォローする。 // VM 差分で skip_ws が前進しないパスがあったため、手動で最小限の空白スキップをフォローする。
{ {
local n = src.length() local n = src.length()
@ -50,19 +51,19 @@ static box ParserStmtBox {
print("[parser/stmt] kind=extern_c j=" + ("" + j)) print("[parser/stmt] kind=extern_c j=" + ("" + j))
} }
} }
j = j + 9 // len("@extern_c") j = j + 9 // len(\"@extern_c\")
j = ctx.skip_ws(src, j) j = ParserStringUtilsBox.skip_ws(src, j)
if j < src.length() && src.substring(j, j+1) == "(" { j = j + 1 } if j < src.length() && src.substring(j, j+1) == "(" { j = j + 1 }
j = ctx.skip_ws(src, j) j = ParserStringUtilsBox.skip_ws(src, j)
// First string literal: symbol // First string literal: symbol
local sym = "" local sym = ""
if j < src.length() && src.substring(j, j+1) == "\"" { if j < src.length() && src.substring(j, j+1) == "\"" {
sym = ctx.read_string_lit(src, j) sym = ctx.read_string_lit(src, j)
j = ctx.gpos_get() j = ctx.gpos_get()
} }
j = ctx.skip_ws(src, j) j = ParserStringUtilsBox.skip_ws(src, j)
if j < src.length() && src.substring(j, j+1) == "," { j = j + 1 } if j < src.length() && src.substring(j, j+1) == "," { j = j + 1 }
j = ctx.skip_ws(src, j) j = ParserStringUtilsBox.skip_ws(src, j)
// Second string literal: func // Second string literal: func
local func_name = "" local func_name = ""
if j < src.length() && src.substring(j, j+1) == "\"" { if j < src.length() && src.substring(j, j+1) == "\"" {
@ -70,10 +71,10 @@ static box ParserStmtBox {
j = ctx.gpos_get() j = ctx.gpos_get()
} }
// Skip to ')' if present // Skip to ')' if present
j = ctx.skip_ws(src, j) j = ParserStringUtilsBox.skip_ws(src, j)
if j < src.length() && src.substring(j, j+1) == ")" { j = j + 1 } if j < src.length() && src.substring(j, j+1) == ")" { j = j + 1 }
// Optional semicolon is consumed by caller; still advance if present // Optional semicolon is consumed by caller; still advance if present
j = ctx.skip_ws(src, j) j = ParserStringUtilsBox.skip_ws(src, j)
if j < src.length() && src.substring(j, j+1) == ";" { j = j + 1 } if j < src.length() && src.substring(j, j+1) == ";" { j = j + 1 }
ctx.gpos_set(j) ctx.gpos_set(j)
// Record annotation in parser context and emit no statement // Record annotation in parser context and emit no statement
@ -106,7 +107,7 @@ static box ParserStmtBox {
} }
} }
j = j + 6 j = j + 6
j = ctx.skip_ws(src, j) j = ParserStringUtilsBox.skip_ws(src, j)
local default_ret = "{\"type\":\"Int\",\"value\":0}" local default_ret = "{\"type\":\"Int\",\"value\":0}"
local expr_json_ret = default_ret local expr_json_ret = default_ret
local end_pos_ret = j local end_pos_ret = j
@ -149,14 +150,14 @@ static box ParserStmtBox {
} }
} }
j = j + kw_len j = j + kw_len
j = ctx.skip_ws(src, j) j = ParserStringUtilsBox.skip_ws(src, j)
local idp = ctx.read_ident2(src, j) local idp = ctx.read_ident2(src, j)
local at = idp.lastIndexOf("@") local at = idp.lastIndexOf("@")
local name = idp.substring(0, at) local name = idp.substring(0, at)
j = ctx.to_int(idp.substring(at+1, idp.length())) j = ctx.to_int(idp.substring(at+1, idp.length()))
j = ctx.skip_ws(src, j) j = ParserStringUtilsBox.skip_ws(src, j)
if j < src.length() && src.substring(j, j+1) == "=" { j = j + 1 } if j < src.length() && src.substring(j, j+1) == "=" { j = j + 1 }
j = ctx.skip_ws(src, j) j = ParserStringUtilsBox.skip_ws(src, j)
local default_local = "{\"type\":\"Int\",\"value\":0}" local default_local = "{\"type\":\"Int\",\"value\":0}"
local expr_json_local = default_local local expr_json_local = default_local
local end_pos_local = j local end_pos_local = j
@ -269,13 +270,13 @@ static box ParserStmtBox {
if at0 > 0 { if at0 > 0 {
local name0 = idp0.substring(0, at0) local name0 = idp0.substring(0, at0)
local k0 = ctx.to_int(idp0.substring(at0+1, idp0.length())) local k0 = ctx.to_int(idp0.substring(at0+1, idp0.length()))
k0 = ctx.skip_ws(src, k0) k0 = ParserStringUtilsBox.skip_ws(src, k0)
if k0 < src.length() && src.substring(k0, k0+1) == "=" { if k0 < src.length() && src.substring(k0, k0+1) == "=" {
local eq_two = "=" local eq_two = "="
if k0 + 1 < src.length() { eq_two = src.substring(k0, k0+2) } if k0 + 1 < src.length() { eq_two = src.substring(k0, k0+2) }
if eq_two != "==" { if eq_two != "==" {
k0 = k0 + 1 k0 = k0 + 1
k0 = ctx.skip_ws(src, k0) k0 = ParserStringUtilsBox.skip_ws(src, k0)
local default_local = "{\"type\":\"Int\",\"value\":0}" local default_local = "{\"type\":\"Int\",\"value\":0}"
local expr_json0 = default_local local expr_json0 = default_local
local end_pos0 = k0 local end_pos0 = k0
@ -321,16 +322,16 @@ static box ParserStmtBox {
// Parse using statement // Parse using statement
parse_using(src, i, stmt_start, ctx) { parse_using(src, i, stmt_start, ctx) {
local j = i + 5 // skip "using" local j = i + 5 // skip "using"
j = ctx.skip_ws(src, j) j = ParserStringUtilsBox.skip_ws(src, j)
if src.substring(j, j+1) == "\"" { if src.substring(j, j+1) == "\"" {
local p = ctx.read_string_lit(src, j) local p = ctx.read_string_lit(src, j)
j = ctx.gpos_get() j = ctx.gpos_get()
j = ctx.skip_ws(src, j) j = ParserStringUtilsBox.skip_ws(src, j)
local alias = null local alias = null
if ctx.starts_with_kw(src, j, "as") == 1 { if ctx.starts_with_kw(src, j, "as") == 1 {
j = j + 2 j = j + 2
j = ctx.skip_ws(src, j) j = ParserStringUtilsBox.skip_ws(src, j)
local idp = ctx.read_ident2(src, j) local idp = ctx.read_ident2(src, j)
local at = idp.lastIndexOf("@") local at = idp.lastIndexOf("@")
alias = idp.substring(0, at) alias = idp.substring(0, at)
@ -345,10 +346,10 @@ static box ParserStmtBox {
j = ctx.to_int(idp.substring(at+1, idp.length())) j = ctx.to_int(idp.substring(at+1, idp.length()))
local cont = 1 local cont = 1
loop(cont == 1) { loop(cont == 1) {
j = ctx.skip_ws(src, j) j = ParserStringUtilsBox.skip_ws(src, j)
if src.substring(j, j+1) == "." { if src.substring(j, j+1) == "." {
j = j + 1 j = j + 1
j = ctx.skip_ws(src, j) j = ParserStringUtilsBox.skip_ws(src, j)
idp = ctx.read_ident2(src, j) idp = ctx.read_ident2(src, j)
at = idp.lastIndexOf("@") at = idp.lastIndexOf("@")
name = name + "." + idp.substring(0, at) name = name + "." + idp.substring(0, at)
@ -357,11 +358,11 @@ static box ParserStmtBox {
cont = 0 cont = 0
} }
} }
j = ctx.skip_ws(src, j) j = ParserStringUtilsBox.skip_ws(src, j)
local alias2 = null local alias2 = null
if ctx.starts_with_kw(src, j, "as") == 1 { if ctx.starts_with_kw(src, j, "as") == 1 {
j = j + 2 j = j + 2
j = ctx.skip_ws(src, j) j = ParserStringUtilsBox.skip_ws(src, j)
idp = ctx.read_ident2(src, j) idp = ctx.read_ident2(src, j)
at = idp.lastIndexOf("@") at = idp.lastIndexOf("@")
alias2 = idp.substring(0, at) alias2 = idp.substring(0, at)