1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

json2: small refactor (#16913)

This commit is contained in:
Hitalo Souza 2023-06-27 14:07:44 -03:00 committed by GitHub
parent d523bb0306
commit aeebb4f118
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 32 additions and 17 deletions

View File

@ -61,17 +61,17 @@ pub fn (err UnknownTokenError) msg() string {
struct Parser { struct Parser {
pub mut: pub mut:
scanner &Scanner = unsafe { nil } scanner &Scanner = unsafe { nil }
p_tok Token prev_tok Token
tok Token tok Token
n_tok Token next_tok Token
n_level int n_level int
convert_type bool = true convert_type bool = true
} }
fn (mut p Parser) next() { fn (mut p Parser) next() {
p.p_tok = p.tok p.prev_tok = p.tok
p.tok = p.n_tok p.tok = p.next_tok
p.n_tok = p.scanner.scan() p.next_tok = p.scanner.scan()
} }
fn (mut p Parser) next_with_err() ! { fn (mut p Parser) next_with_err() ! {
@ -87,6 +87,9 @@ fn (mut p Parser) next_with_err() ! {
// TODO: copied from v.util to avoid the entire module and its functions // TODO: copied from v.util to avoid the entire module and its functions
// from being imported. remove later once -skip-unused is enabled by default. // from being imported. remove later once -skip-unused is enabled by default.
// skip_bom - skip Byte Order Mark (BOM)
// The UTF-8 BOM is a sequence of Bytes at the start of a text-stream (EF BB BF or \ufeff)
// that allows the reader to reliably determine if file is being encoded in UTF-8.
fn skip_bom(file_content string) string { fn skip_bom(file_content string) string {
mut raw_text := file_content mut raw_text := file_content
// BOM check // BOM check
@ -103,6 +106,7 @@ fn skip_bom(file_content string) string {
return raw_text return raw_text
} }
// new_parser - create a instance of Parser{}
fn new_parser(srce string, convert_type bool) Parser { fn new_parser(srce string, convert_type bool) Parser {
src := skip_bom(srce) src := skip_bom(srce)
return Parser{ return Parser{
@ -113,7 +117,7 @@ fn new_parser(srce string, convert_type bool) Parser {
} }
} }
// decode decodes provided JSON // decode - decodes provided JSON
pub fn (mut p Parser) decode() !Any { pub fn (mut p Parser) decode() !Any {
p.next() p.next()
p.next_with_err()! p.next_with_err()!
@ -133,9 +137,11 @@ fn (mut p Parser) decode_value() !Any {
} }
} }
match p.tok.kind { match p.tok.kind {
// `[`
.lsbr { .lsbr {
return p.decode_array() return p.decode_array()
} }
// `{`
.lcbr { .lcbr {
return p.decode_object() return p.decode_object()
} }
@ -187,6 +193,7 @@ fn (mut p Parser) decode_array() !Any {
mut items := []Any{} mut items := []Any{}
p.next_with_err()! p.next_with_err()!
p.n_level++ p.n_level++
// `]`
for p.tok.kind != .rsbr { for p.tok.kind != .rsbr {
item := p.decode_value()! item := p.decode_value()!
items << item items << item
@ -213,7 +220,9 @@ fn (mut p Parser) decode_object() !Any {
mut fields := map[string]Any{} mut fields := map[string]Any{}
p.next_with_err()! p.next_with_err()!
p.n_level++ p.n_level++
// `}`
for p.tok.kind != .rcbr { for p.tok.kind != .rcbr {
// step 1 -> key
if p.tok.kind != .str_ { if p.tok.kind != .str_ {
return InvalidTokenError{ return InvalidTokenError{
token: p.tok token: p.tok
@ -223,6 +232,7 @@ fn (mut p Parser) decode_object() !Any {
cur_key := p.tok.lit.bytestr() cur_key := p.tok.lit.bytestr()
p.next_with_err()! p.next_with_err()!
// step 2 -> colon separator
if p.tok.kind != .colon { if p.tok.kind != .colon {
return InvalidTokenError{ return InvalidTokenError{
token: p.tok token: p.tok
@ -231,6 +241,7 @@ fn (mut p Parser) decode_object() !Any {
} }
p.next_with_err()! p.next_with_err()!
// step 3 -> value
fields[cur_key] = p.decode_value()! fields[cur_key] = p.decode_value()!
if p.tok.kind != .comma && p.tok.kind != .rcbr { if p.tok.kind != .comma && p.tok.kind != .rcbr {
return UnknownTokenError{ return UnknownTokenError{
@ -242,6 +253,7 @@ fn (mut p Parser) decode_object() !Any {
} }
} }
p.next_with_err()! p.next_with_err()!
// step 4 -> eof (end)
p.n_level-- p.n_level--
return Any(fields) return Any(fields)
} }

View File

@ -146,6 +146,8 @@ pub fn decode[T](src string) !T {
else {} else {}
} }
} }
} $else {
return error("The type `${T.name}` can't be decoded.")
} }
return typ return typ
} }

View File

@ -8,7 +8,7 @@ import strconv
struct Scanner { struct Scanner {
mut: mut:
text []u8 text []u8
pos int pos int // the position of the token in scanner text
line int line int
col int col int
} }
@ -22,19 +22,19 @@ enum TokenKind {
null null
bool_ bool_
eof eof
comma = 44 comma = 44 // ,
colon = 58 colon = 58 // :
lsbr = 91 lsbr = 91 // [
rsbr = 93 rsbr = 93 // ]
lcbr = 123 lcbr = 123 // {
rcbr = 125 rcbr = 125 // }
} }
pub struct Token { pub struct Token {
lit []u8 lit []u8 // literal representation of the token
kind TokenKind kind TokenKind // the token number/enum; for quick comparisons
line int line int // the line in the source where the token occured
col int col int // the column in the source where the token occured
} }
// full_col returns the full column information which includes the length // full_col returns the full column information which includes the length
@ -256,6 +256,7 @@ fn (s Scanner) invalid_token() Token {
} }
// scan returns a token based on the scanner's current position. // scan returns a token based on the scanner's current position.
// used to set the next token
[manualfree] [manualfree]
fn (mut s Scanner) scan() Token { fn (mut s Scanner) scan() Token {
if s.pos < s.text.len && (s.text[s.pos] == ` ` || s.text[s.pos] in json2.newlines) { if s.pos < s.text.len && (s.text[s.pos] == ` ` || s.text[s.pos] in json2.newlines) {