Files
Viper_VRTE/json/__parser.vp
T
TermiNexus 0055ab7ea7 refactor: rawptr[T] -> T* 与 t.CConst 前缀迁移(R14/R16)
R14:rawptr[X] -> X*(41 文件 / 2037 行改动),X 含模块限定名与嵌套下标(rawptr[GSList[NameEntry]] -> GSList[NameEntry]*)。保留 6 处 rawptr[t.CPtr](规范例外:存纯裸指针);# 注释与字符串里的 rawptr[...] 属元语法描述,未动。 R16(保守子集):t.CConst | str/bytes -> const str/bytes,t.CConst | char | t.CPtr -> const str;typedef 右值位置豁免(const str 在该处无法注册,与 R1 同源)。 验证:TPC 自举三重重编 SUCCESS;TransPyV.exe 全量 77/77 顺序回归通过。
2026-10-05 17:38:21 +08:00

297 lines
7.8 KiB
Plaintext

import t, c
from stdint import *
import memhub
import string
from . import (
JsonValue, JSON_NULL, JSON_BOOL, JSON_INT, JSON_FLOAT,
JSON_STRING, JSON_ARRAY, JSON_OBJECT,
null, bool_val, int_val, float_val, string_val, array, object,
)
class ParseState:
src: str
pos: sizet = 0
len: sizet = 0
pool: memhub.MemManager*
def __init__(self, src: str, pool: memhub.MemManager*):
self.src = src
self.len = string.strlen(src) if src != None else 0
self.pool = pool
def _peek(s: ParseState*) -> char:
if s.pos >= s.len: return '\0'
return s.src[s.pos]
def _advance(s: ParseState*) -> char:
if s.pos >= s.len: return '\0'
ch: char = s.src[s.pos]
s.pos += 1
return ch
def _skip_whitespace(s: ParseState*):
while s.pos < s.len:
ch: char = s.src[s.pos]
if ch == ' ' or ch == '\t' or ch == '\n' or ch == '\r':
s.pos += 1
else:
break
def _expect(s: ParseState*, ch: char) -> bool:
_skip_whitespace(s)
if s.pos >= s.len: return False
if s.src[s.pos] != ch: return False
s.pos += 1
return True
def _parse_string(s: ParseState*) -> str:
if _peek(s) != '"': return None
_advance(s)
start: sizet = s.pos
slen: sizet = 0
while s.pos < s.len:
ch: char = s.src[s.pos]
if ch == '"':
break
if ch == '\\':
s.pos += 1
slen += 1
slen += 1
s.pos += 1
buf: str = s.pool.alloc(slen + 1)
if buf == None:
return None
s.pos = start
di: sizet = 0
while s.pos < s.len:
ch: char = s.src[s.pos]
if ch == '"':
s.pos += 1
break
if ch == '\\':
s.pos += 1
if s.pos < s.len:
esc: char = s.src[s.pos]
if esc == 'n':
buf[di] = '\n'
elif esc == 't':
buf[di] = '\t'
elif esc == 'r':
buf[di] = '\r'
elif esc == '\\':
buf[di] = '\\'
elif esc == '"':
buf[di] = '"'
elif esc == '/':
buf[di] = '/'
else:
buf[di] = esc
di += 1
s.pos += 1
continue
buf[di] = ch
di += 1
s.pos += 1
buf[di] = '\0'
return buf
def _parse_number(s: ParseState*) -> JsonValue*:
_skip_whitespace(s)
is_float: bool = False
start: sizet = s.pos
if s.pos < s.len and s.src[s.pos] == '-':
s.pos += 1
while s.pos < s.len:
ch: char = s.src[s.pos]
if ch >= '0' and ch <= '9':
s.pos += 1
else:
break
if s.pos < s.len and s.src[s.pos] == '.':
is_float = True
s.pos += 1
while s.pos < s.len:
ch: char = s.src[s.pos]
if ch >= '0' and ch <= '9':
s.pos += 1
else:
break
if s.pos < s.len and (s.src[s.pos] == 'e' or s.src[s.pos] == 'E'):
is_float = True
s.pos += 1
if s.pos < s.len and (s.src[s.pos] == '+' or s.src[s.pos] == '-'):
s.pos += 1
while s.pos < s.len:
ch: char = s.src[s.pos]
if ch >= '0' and ch <= '9':
s.pos += 1
else:
break
num_len: sizet = s.pos - start
buf: str = s.pool.alloc(num_len + 1)
if buf == None:
return null(s.pool)
for i in range(num_len):
buf[i] = s.src[start + i]
buf[num_len] = '\0'
if is_float:
val: double = string.atof(buf)
return float_val(s.pool, val)
else:
ival: int64 = string.atoll(buf)
return int_val(s.pool, ival)
def _parse_value(s: ParseState*) -> JsonValue*:
_skip_whitespace(s)
if s.pos >= s.len:
return null(s.pool)
ch: char = _peek(s)
if ch == '"':
sv: str = _parse_string(s)
return string_val(s.pool, sv)
if ch == '{':
return _parse_object(s)
if ch == '[':
return _parse_array(s)
if ch == '-' or (ch >= '0' and ch <= '9'):
return _parse_number(s)
if ch == 't':
if s.pos + 3 < s.len:
if s.src[s.pos + 1] == 'r' and s.src[s.pos + 2] == 'u' and s.src[s.pos + 3] == 'e':
s.pos += 4
return bool_val(s.pool, True)
return null(s.pool)
if ch == 'f':
if s.pos + 4 < s.len:
if s.src[s.pos + 1] == 'a' and s.src[s.pos + 2] == 'l' and s.src[s.pos + 3] == 's' and s.src[s.pos + 4] == 'e':
s.pos += 5
return bool_val(s.pool, False)
return null(s.pool)
if ch == 'n':
if s.pos + 3 < s.len:
if s.src[s.pos + 1] == 'u' and s.src[s.pos + 2] == 'l' and s.src[s.pos + 3] == 'l':
s.pos += 4
return null(s.pool)
return null(s.pool)
return null(s.pool)
def _parse_array(s: ParseState*) -> JsonValue*:
if not _expect(s, '['):
return null(s.pool)
arr: JsonValue* = array(s.pool)
# Pool exhausted => array() returns None; continuing to arr._append_child(...) would deref
# a null pointer, so return None here (json.parse may return None; callers must check).
if arr == None:
return null(s.pool)
_skip_whitespace(s)
if s.pos < s.len and _peek(s) == ']':
_advance(s)
return arr
item: JsonValue* = _parse_value(s)
# item == None iff allocation failed somewhere inside _parse_value (syntax errors yield
# a valid JSON_NULL node; only pool exhaustion yields None) => return None, append nothing.
if item == None:
return null(s.pool)
arr._append_child(item)
while True:
_skip_whitespace(s)
if s.pos >= s.len:
break
if _peek(s) != ',':
break
_advance(s)
item = _parse_value(s)
if item == None:
return null(s.pool)
arr._append_child(item)
_expect(s, ']')
return arr
def _parse_object(s: ParseState*) -> JsonValue*:
if not _expect(s, '{'):
return null(s.pool)
obj: JsonValue* = object(s.pool)
# Same as _parse_array: obj is None on pool exhaustion; do not call _append_child on None.
if obj == None:
return null(s.pool)
_skip_whitespace(s)
if s.pos < s.len and _peek(s) == '}':
_advance(s)
return obj
_skip_whitespace(s)
key: str = _parse_string(s)
_expect(s, ':')
val: JsonValue* = _parse_value(s)
if key != None and val != None:
klen: sizet = string.strlen(key)
kbuf: str = s.pool.alloc(klen + 1)
if kbuf != None:
string.memcpy(kbuf, key, klen + 1)
val.key = kbuf
obj._append_child(val)
while True:
_skip_whitespace(s)
if s.pos >= s.len:
break
if _peek(s) != ',':
break
_advance(s)
_skip_whitespace(s)
key = _parse_string(s)
_expect(s, ':')
val = _parse_value(s)
if key != None and val != None:
klen2: sizet = string.strlen(key)
kbuf2: str = s.pool.alloc(klen2 + 1)
if kbuf2 != None:
string.memcpy(kbuf2, key, klen2 + 1)
val.key = kbuf2
obj._append_child(val)
_expect(s, '}')
return obj
def parse(pool: memhub.MemManager*, src: str) -> JsonValue*:
"""Parse a JSON string, returning a JsonValue tree."""
if src == None:
return null(pool)
s: ParseState* = ParseState(src, pool)
return _parse_value(s)