diff --git a/parser/walk.go b/parser/walk.go new file mode 100644 index 0000000..2bb9ed5 --- /dev/null +++ b/parser/walk.go @@ -0,0 +1,36 @@ +package parser + +// Walk traverses an AST in depth-first order: It starts by calling fn(node); +// node must not be nil. If f returns true, Walk invokes f recursively for +// each of the non-nil children of node, followed by a call of f(nil). +func Walk(node Node, fn func(Node) bool) { + if !fn(node) { + return + } + + switch n := node.(type) { + case *ObjectList: + for _, item := range n.items { + Walk(item, fn) + } + case *ObjectKey: + // nothing to do + case *ObjectItem: + for _, k := range n.keys { + Walk(k, fn) + } + Walk(n.val, fn) + case *LiteralType: + // nothing to do + case *ListType: + for _, l := range n.list { + Walk(l, fn) + } + case *ObjectType: + for _, l := range n.list { + Walk(l, fn) + } + } + + fn(nil) +} diff --git a/scanner/scanner.go b/scanner/scanner.go index 42234a2..1d6696f 100644 --- a/scanner/scanner.go +++ b/scanner/scanner.go @@ -414,7 +414,7 @@ func (s *Scanner) scanEscape() rune { } // scanDigits scans a rune with the given base for n times. For example an -// octan notation \184 would yield in scanDigits(ch, 8, 3) +// octal notation \184 would yield in scanDigits(ch, 8, 3) func (s *Scanner) scanDigits(ch rune, base, n int) rune { for n > 0 && digitVal(ch) < base { ch = s.next() @@ -436,7 +436,10 @@ func (s *Scanner) scanIdentifier() string { for isLetter(ch) || isDigit(ch) { ch = s.next() } - s.unread() // we got identifier, put back latest char + + if ch != eof { + s.unread() // we got identifier, put back latest char + } return string(s.src[offs:s.srcPos.Offset]) }