summaryrefslogtreecommitdiff
path: root/internal/parse.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/parse.go')
-rw-r--r--internal/parse.go82
1 files changed, 49 insertions, 33 deletions
diff --git a/internal/parse.go b/internal/parse.go
index 895c930..bb849e7 100644
--- a/internal/parse.go
+++ b/internal/parse.go
@@ -70,9 +70,14 @@ const (
RuneTypeNullL2
RuneTypeEOF
+
+ // Not a real rune type, but used as a stack state.
+ runeTypeAny
)
// GoString implements fmt.GoStringer.
+//
+//nolint:dupl // False positive due to similarly shaped AST.
func (t RuneType) GoString() string {
str, ok := map[RuneType]string{
RuneTypeError: "RuneTypeError",
@@ -125,6 +130,8 @@ func (t RuneType) GoString() string {
RuneTypeNullL2: "RuneTypeNullL2",
RuneTypeEOF: "RuneTypeEOF",
+
+ runeTypeAny: "runeTypeAny",
}[t]
if ok {
return str
@@ -133,6 +140,8 @@ func (t RuneType) GoString() string {
}
// String implements fmt.Stringer.
+//
+//nolint:dupl // False positive due to similarly shaped AST.
func (t RuneType) String() string {
str, ok := map[RuneType]string{
RuneTypeError: "x",
@@ -148,7 +157,7 @@ func (t RuneType) String() string {
RuneTypeArrayComma: "a",
RuneTypeArrayEnd: "]",
- RuneTypeStringBeg: "“",
+ RuneTypeStringBeg: "\"",
RuneTypeStringChar: "c",
RuneTypeStringEsc: "\\",
RuneTypeStringEsc1: "b",
@@ -157,7 +166,7 @@ func (t RuneType) String() string {
RuneTypeStringEscUB: "B",
RuneTypeStringEscUC: "C",
RuneTypeStringEscUD: "D",
- RuneTypeStringEnd: "”",
+ RuneTypeStringEnd: "»",
RuneTypeNumberIntNeg: "-",
RuneTypeNumberIntZero: "0",
@@ -185,6 +194,8 @@ func (t RuneType) String() string {
RuneTypeNullL2: "Ⓛ", // +uppercase
RuneTypeEOF: "$",
+
+ runeTypeAny: "?",
}[t]
if ok {
return str
@@ -226,15 +237,19 @@ type Parser struct {
err error
closed bool
- // We reuse RuneTypes to store the stack. The base idea is
- // that, stack items are "the most recently read
- // stack-relevant RuneType".
+ // We reuse RuneTypes to store the stack. The base idea is:
+ // stack items are "the most recently read stack-relevant
+ // RuneType".
//
- // We treat RuneTypeError as a wildcard.
+ // The stack starts out with the special pseudo-RuneType
+ // `runeTypeAny` that means we're willing to accept any
+ // element type; an empty stack means that we have reached the
+ // end of the top-level element and should accept no more
+ // input except for whitespace.
//
- // The "normal"stack-relevant RuneTypes are:
+ // The "normal" stack-relevant RuneTypes are:
//
- // “\uABC for strings
+ // "\uABC for strings
// -01.2e+3 for numbers
// 𝕥𝕣𝕦 for "true"
// 𝔣𝔞𝔩𝔰 for "false"
@@ -244,8 +259,7 @@ type Parser struct {
// rule; they need some special assignments:
//
// { object: waiting for key to start or '}'
- // ” object: reading key / waiting for colon
- // : object: waiting for value to start
+ // » object: reading key / waiting for colon
// o object: reading value / waiting for ',' or '}'
//
// [ array: waiting for item to start or ']'
@@ -261,22 +275,22 @@ type Parser struct {
// The stack would be
//
// stack processed
- // x
+ // ?
// { {
- // ”“ {"
- // ”“ {"x
- // ” {"x"
- // : {"x":
- // o“ {"x":"
- // o“ {"x":"y
+ // »" {"
+ // »" {"x
+ // » {"x"
+ // o? {"x":
+ // o" {"x":"
+ // o" {"x":"y
// o {"x":"y"
// { {"x":"y",
- // ”“ {"x":"y","
- // ”“ {"x":"y","a
- // ” {"x":"y","a"
- // : {"x":"y","a":
- // o“ {"x":"y","a":"
- // o“ {"x":"y","a":"b
+ // »" {"x":"y","
+ // »" {"x":"y","a
+ // » {"x":"y","a"
+ // o? {"x":"y","a":
+ // o" {"x":"y","a":"
+ // o" {"x":"y","a":"b
// o {"x":"y","a":"b"
// {"x":"y","a":"b"}
stack []RuneType
@@ -286,10 +300,12 @@ func (par *Parser) pushState(state RuneType) RuneType {
par.stack = append(par.stack, state)
return state
}
+
func (par *Parser) replaceState(state RuneType) RuneType {
par.stack[len(par.stack)-1] = state
return state
}
+
func (par *Parser) popState() {
par.stack = par.stack[:len(par.stack)-1]
}
@@ -303,7 +319,7 @@ func (par *Parser) stackString() string {
}
func (par *Parser) StackIsEmpty() bool {
- return len(par.stack) == 0 || (len(par.stack) == 1 && par.stack[0] == RuneTypeError)
+ return len(par.stack) == 0 || (len(par.stack) == 1 && par.stack[0] == runeTypeAny)
}
// Reset all Parser state.
@@ -337,7 +353,7 @@ func (par *Parser) HandleEOF() (RuneType, error) {
}
if !par.initialized {
par.initialized = true
- par.pushState(RuneTypeError)
+ par.pushState(runeTypeAny)
}
switch len(par.stack) {
case 0:
@@ -348,7 +364,7 @@ func (par *Parser) HandleEOF() (RuneType, error) {
if _, err := par.HandleRune('\n'); err == nil {
return RuneTypeEOF, nil
}
- case par.stack[0] == RuneTypeError:
+ case par.stack[0] == runeTypeAny:
par.err = io.EOF
return RuneTypeError, par.err
}
@@ -381,7 +397,7 @@ func (par *Parser) HandleRune(c rune) (RuneType, error) {
}
if !par.initialized {
par.initialized = true
- par.pushState(RuneTypeError)
+ par.pushState(runeTypeAny)
}
if len(par.stack) == 0 {
switch c {
@@ -393,7 +409,7 @@ func (par *Parser) HandleRune(c rune) (RuneType, error) {
}
switch par.stack[len(par.stack)-1] {
// any /////////////////////////////////////////////////////////////////////////////////////
- case RuneTypeError:
+ case runeTypeAny:
switch c {
case 0x0020, 0x000A, 0x000D, 0x0009:
return RuneTypeSpace, nil
@@ -444,7 +460,7 @@ func (par *Parser) HandleRune(c rune) (RuneType, error) {
return RuneTypeSpace, nil
case ':':
par.replaceState(RuneTypeObjectComma)
- par.pushState(RuneTypeError)
+ par.pushState(runeTypeAny)
return RuneTypeObjectColon, nil
default:
return RuneTypeError, fmt.Errorf("invalid character %q after object key", c)
@@ -472,7 +488,7 @@ func (par *Parser) HandleRune(c rune) (RuneType, error) {
return RuneTypeArrayEnd, nil
default:
par.replaceState(RuneTypeArrayComma)
- par.pushState(RuneTypeError)
+ par.pushState(runeTypeAny)
return par.HandleRune(c)
}
case RuneTypeArrayEnd: // waiting for item
@@ -481,7 +497,7 @@ func (par *Parser) HandleRune(c rune) (RuneType, error) {
return RuneTypeSpace, nil
default:
par.replaceState(RuneTypeArrayComma)
- par.pushState(RuneTypeError)
+ par.pushState(runeTypeAny)
return par.HandleRune(c)
}
case RuneTypeArrayComma: // waiting for ',' or ']'
@@ -583,8 +599,8 @@ func (par *Parser) HandleRune(c rune) (RuneType, error) {
// H = ExpSign
// I = ExpDig
//
- // The 'A' state is part of the RuneTypeError "any" case
- // above, and the remainder follow:
+ // The 'A' state is part of the runeTypeAny case above, and
+ // the remainder follow:
case RuneTypeNumberIntNeg: // B
switch c {
case '0':