Skip to content

Commit 068e4d6

Browse files
inteoningydotnet
authored andcommitted
Simplify simple key tracking
Signed-off-by: Tim Ramlot <[email protected]>
1 parent 866cff5 commit 068e4d6

3 files changed

Lines changed: 70 additions & 82 deletions

File tree

internal/libyaml/scanner.go

Lines changed: 62 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -662,12 +662,25 @@ func (parser *Parser) fetchMoreTokens() error {
662662
if parser.tokens_head < len(parser.tokens)-2 {
663663
// If a potential simple key is at the head position, we need to fetch
664664
// the next token to disambiguate it.
665-
head_tok_idx, ok := parser.simple_keys_by_tok[parser.tokens_parsed]
666-
if !ok {
665+
666+
var first_key int
667+
found_potential_key := false
668+
669+
if len(parser.simple_key_stack) > 0 {
670+
// Found a simple key on the stack
671+
first_key = parser.simple_key_stack[0].token_number
672+
found_potential_key = true
673+
} else if parser.simple_key_possible {
674+
// Found a 'current' simple key (which was not pushed to the stack yet)
675+
first_key = parser.simple_key.token_number
676+
found_potential_key = true
677+
}
678+
679+
if !found_potential_key {
680+
// We don't have any potential simple keys
667681
break
668-
} else if valid, err := parser.simpleKeyIsValid(&parser.simple_keys[head_tok_idx]); err != nil {
669-
return err
670-
} else if !valid {
682+
} else if parser.tokens_parsed != first_key {
683+
// We have not reached the potential simple key yet.
671684
break
672685
}
673686
}
@@ -886,32 +899,6 @@ func (parser *Parser) isFlowSequence() bool {
886899
return previousToken.Type == FLOW_ENTRY_TOKEN || previousToken.Type == FLOW_SEQUENCE_START_TOKEN
887900
}
888901

889-
func (parser *Parser) simpleKeyIsValid(simple_key *SimpleKey) (valid bool, err error) {
890-
if !simple_key.possible {
891-
return false, nil
892-
}
893-
894-
// The 1.2 specification says:
895-
//
896-
// "If the ? indicator is omitted, parsing needs to see past the
897-
// implicit key to recognize it as such. To limit the amount of
898-
// lookahead required, the “:” indicator must appear at most 1024
899-
// Unicode characters beyond the start of the key. In addition, the key
900-
// is restricted to a single line."
901-
//
902-
if simple_key.mark.Line < parser.mark.Line || simple_key.mark.Index+1024 < parser.mark.Index {
903-
// Check if the potential simple key to be removed is required.
904-
if simple_key.required {
905-
return false, formatScannerErrorContext(
906-
"while scanning a simple key", simple_key.mark,
907-
"could not find expected ':'", parser.mark)
908-
}
909-
simple_key.possible = false
910-
return false, nil
911-
}
912-
return true, nil
913-
}
914-
915902
// Check if a simple key may start at the current position and add it if
916903
// needed.
917904
func (parser *Parser) saveSimpleKey() error {
@@ -925,36 +912,31 @@ func (parser *Parser) saveSimpleKey() error {
925912
// If the current position may start a simple key, save it.
926913
//
927914
if parser.simple_key_allowed {
928-
simple_key := SimpleKey{
929-
possible: true,
915+
if err := parser.removeSimpleKey(); err != nil {
916+
return err
917+
}
918+
919+
parser.simple_key_possible = true
920+
parser.simple_key = SimpleKey{
930921
required: required,
922+
flow_level: parser.flow_level,
931923
token_number: parser.tokens_parsed + (len(parser.tokens) - parser.tokens_head),
932924
mark: parser.mark,
933925
}
934-
935-
if err := parser.removeSimpleKey(); err != nil {
936-
return err
937-
}
938-
parser.simple_keys[len(parser.simple_keys)-1] = simple_key
939-
parser.simple_keys_by_tok[simple_key.token_number] = len(parser.simple_keys) - 1
940926
}
941927
return nil
942928
}
943929

944930
// Remove a potential simple key at the current flow level.
945931
func (parser *Parser) removeSimpleKey() error {
946-
i := len(parser.simple_keys) - 1
947-
if parser.simple_keys[i].possible {
948-
// If the key is required, it is an error.
949-
if parser.simple_keys[i].required {
950-
return formatScannerErrorContext(
951-
"while scanning a simple key", parser.simple_keys[i].mark,
952-
"could not find expected ':'", parser.mark)
953-
}
954-
// Remove the key from the stack.
955-
parser.simple_keys[i].possible = false
956-
delete(parser.simple_keys_by_tok, parser.simple_keys[i].token_number)
932+
// If the key is required, it is an error.
933+
if parser.simple_key.required {
934+
return formatScannerErrorContext(
935+
"while scanning a simple key", parser.simple_key.mark,
936+
"could not find expected ':'", parser.mark)
957937
}
938+
939+
parser.simple_key_possible = false // disable the key
958940
return nil
959941
}
960942

@@ -963,31 +945,40 @@ const max_flow_level = 10000
963945

964946
// Increase the flow level and resize the simple key list if needed.
965947
func (parser *Parser) increaseFlowLevel() error {
966-
// Reset the simple key on the next level.
967-
parser.simple_keys = append(parser.simple_keys, SimpleKey{
968-
possible: false,
969-
required: false,
970-
token_number: parser.tokens_parsed + (len(parser.tokens) - parser.tokens_head),
971-
mark: parser.mark,
972-
})
973-
974948
// Increase the flow level.
975949
parser.flow_level++
976950
if parser.flow_level > max_flow_level {
977951
return formatScannerErrorContext(
978-
"while increasing flow level", parser.simple_keys[len(parser.simple_keys)-1].mark,
952+
"while increasing flow level", parser.simple_key.mark,
979953
fmt.Sprintf("exceeded max depth of %d", max_flow_level), parser.mark)
980954
}
955+
956+
// If a simple key was possible, push it to the stack before resetting the key.
957+
if parser.simple_key_possible {
958+
parser.simple_key_stack = append(parser.simple_key_stack, parser.simple_key)
959+
}
960+
961+
// Reset the simple key for the new flow level.
962+
parser.simple_key = SimpleKey{}
963+
981964
return nil
982965
}
983966

984967
// Decrease the flow level.
985968
func (parser *Parser) decreaseFlowLevel() error {
986969
if parser.flow_level > 0 {
987970
parser.flow_level--
988-
last := len(parser.simple_keys) - 1
989-
delete(parser.simple_keys_by_tok, parser.simple_keys[last].token_number)
990-
parser.simple_keys = parser.simple_keys[:last]
971+
972+
if len(parser.simple_key_stack) == 0 {
973+
return nil
974+
}
975+
976+
last := len(parser.simple_key_stack) - 1
977+
if parser.simple_key_stack[last].flow_level == parser.flow_level {
978+
parser.simple_key = parser.simple_key_stack[last] // use last item
979+
parser.simple_key_stack = parser.simple_key_stack[:last] // remove last item
980+
parser.simple_key_possible = true // enable the key
981+
}
991982
}
992983
return nil
993984
}
@@ -1011,7 +1002,7 @@ func (parser *Parser) rollIndent(column, number int, typ TokenType, mark Mark) e
10111002
parser.indent = column
10121003
if len(parser.indents) > max_indents {
10131004
return formatScannerErrorContext(
1014-
"while increasing indent level", parser.simple_keys[len(parser.simple_keys)-1].mark,
1005+
"while increasing indent level", parser.simple_key.mark,
10151006
fmt.Sprintf("exceeded max depth of %d", max_indents), parser.mark)
10161007
}
10171008

@@ -1091,9 +1082,8 @@ func (parser *Parser) fetchStreamStart() error {
10911082
parser.indent = -1
10921083

10931084
// Initialize the simple key stack.
1094-
parser.simple_keys = append(parser.simple_keys, SimpleKey{})
1095-
1096-
parser.simple_keys_by_tok = make(map[int]int)
1085+
parser.simple_key = SimpleKey{}
1086+
parser.simple_key_stack = []SimpleKey{}
10971087

10981088
// A simple key is allowed at the beginning of the stream.
10991089
parser.simple_key_allowed = true
@@ -1129,7 +1119,8 @@ func (parser *Parser) fetchStreamEnd() error {
11291119
if err := parser.removeSimpleKey(); err != nil {
11301120
return err
11311121
}
1132-
1122+
parser.simple_key = SimpleKey{}
1123+
parser.simple_key_stack = []SimpleKey{}
11331124
parser.simple_key_allowed = false
11341125

11351126
// Create the STREAM-END token and append it to the queue.
@@ -1369,13 +1360,10 @@ func (parser *Parser) fetchKey() error {
13691360

13701361
// Produce the VALUE token.
13711362
func (parser *Parser) fetchValue() error {
1372-
simple_key := &parser.simple_keys[len(parser.simple_keys)-1]
1363+
simple_key := &parser.simple_key
13731364

13741365
// Have we found a simple key?
1375-
if valid, err := parser.simpleKeyIsValid(simple_key); err != nil {
1376-
return err
1377-
} else if valid {
1378-
1366+
if parser.simple_key_possible && simple_key.mark.Line == parser.mark.Line {
13791367
// Create the KEY token and insert it into the queue.
13801368
token := Token{
13811369
Type: KEY_TOKEN,
@@ -1392,8 +1380,8 @@ func (parser *Parser) fetchValue() error {
13921380
}
13931381

13941382
// Remove the simple key.
1395-
simple_key.possible = false
1396-
delete(parser.simple_keys_by_tok, simple_key.token_number)
1383+
parser.simple_key_possible = false
1384+
simple_key.required = false
13971385

13981386
// A simple key cannot follow another simple key.
13991387
parser.simple_key_allowed = false

internal/libyaml/yaml.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -510,7 +510,7 @@ type ReadHandler func(parser *Parser, buffer []byte) (n int, err error)
510510

511511
// SimpleKey holds information about a potential simple key.
512512
type SimpleKey struct {
513-
possible bool // Is a simple key possible?
513+
flow_level int // What flow level is the key at?
514514
required bool // Is a simple key required?
515515
token_number int // The number of the token.
516516
mark Mark // The position mark.
@@ -657,9 +657,10 @@ type Parser struct {
657657
indent int // The current indentation level.
658658
indents []int // The indentation levels stack.
659659

660-
simple_key_allowed bool // May a simple key occur at the current position?
661-
simple_keys []SimpleKey // The stack of simple keys.
662-
simple_keys_by_tok map[int]int // possible simple_key indexes indexed by token_number
660+
simple_key_allowed bool // May a simple key occur at the current position?
661+
simple_key_possible bool // Is the current simple key possible?
662+
simple_key SimpleKey // The current simple key.
663+
simple_key_stack []SimpleKey // The stack of simple keys.
663664

664665
// Parser stuff
665666

testdata/unmarshal_errors.yaml

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -110,8 +110,7 @@
110110
1:
111111
b
112112
2:
113-
want: "yaml: while scanning a simple key at line 3: line 4, column 4:
114-
could not find expected ':'"
113+
want: "yaml: line 4, column 4: mapping values are not allowed in this context"
115114

116115
- unmarshal-error:
117116
name: Missing colon in mapping (inline)
@@ -129,8 +128,8 @@
129128
#
130129
-
131130
{
132-
want: "yaml: while scanning a simple key at line 3: line 4:
133-
could not find expected ':'"
131+
want: "yaml: while parsing a flow node at line 3:
132+
did not find expected node content"
134133

135134
- unmarshal-error:
136135
name: Incomplete UTF-8 sequence (Issue 666)

0 commit comments

Comments
 (0)