Skip to content

Commit 3d4dd3b

Browse files
author
swilly22
committed
initial commit
1 parent fbe629d commit 3d4dd3b

File tree

4 files changed

+397
-0
lines changed

4 files changed

+397
-0
lines changed

helpers.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package json_parser
2+
3+
import (
4+
"strings"
5+
)
6+
7+
func isNumeric(r rune) bool {
8+
digits := "+-0987654321"
9+
return strings.IndexRune(digits, r) >= 0
10+
}
11+
12+
func isAlphaNumeric(r rune) bool {
13+
digits := "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
14+
return strings.IndexRune(digits, r) >= 0
15+
}

item.go

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package json_parser
2+
3+
import (
4+
"fmt"
5+
)
6+
7+
// item represents a token returned from the scanner.
8+
type item struct {
9+
typ itemType // Type, such as itemNumber.
10+
val string // Value, such as "23.2"
11+
}
12+
13+
func (i item) String() string {
14+
switch i.typ {
15+
case itemEOF:
16+
return "EOF"
17+
case itemError:
18+
return i.val
19+
}
20+
if len(i.val) > 10 {
21+
return fmt.Sprintf("%.10q...", i.val)
22+
}
23+
return fmt.Sprintf("%q", i.val)
24+
}
25+
26+
// itemType identifies the type of lex items.
27+
type itemType int
28+
29+
const (
30+
itemError itemType = iota // error occurred
31+
itemText
32+
itemLeftMeta
33+
itemRightMeta
34+
itemLeftBracket
35+
itemRightBracket
36+
itemIdentifier
37+
itemNumber
38+
itemString
39+
itemComma
40+
itemEOF
41+
)
42+
43+
const (
44+
eof = -1
45+
leftMeta = '{'
46+
rightMeta = '}'
47+
leftBracket = '['
48+
rightBracket = ']'
49+
comma = ','
50+
quotationMark = '"'
51+
)

lexer.go

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
package json_parser
2+
3+
import (
4+
"fmt"
5+
"strings"
6+
"unicode/utf8"
7+
)
8+
9+
type lexer struct {
10+
name string // used only for error reports.
11+
input string // the string being scanned.
12+
start int // start position of this item.
13+
pos int // current position in the input.
14+
width int // width of last rune read.
15+
items chan item // channel of scanned items.
16+
}
17+
18+
func Lex(name, input string) (*lexer, chan item) {
19+
l := &lexer{
20+
name: name,
21+
input: input,
22+
items: make(chan item, 2),
23+
}
24+
25+
go l.run() // Concurrently run state machine.
26+
return l, l.items
27+
}
28+
29+
// run lexes the input by executing state functions untill
30+
// the state is nil.
31+
func (l *lexer) run() {
32+
for state := initState; state != nil; {
33+
state = state(l)
34+
}
35+
close(l.items) // No more tokens will be delivered.
36+
}
37+
38+
// emit passes an item back to the client.
39+
func (l *lexer) emit(t itemType) {
40+
l.items <- item{t, l.input[l.start:l.pos]}
41+
l.start = l.pos
42+
}
43+
44+
func (l *lexer) next() rune {
45+
if l.pos >= len(l.input) {
46+
l.width = 0
47+
return eof
48+
}
49+
50+
r, width := utf8.DecodeRuneInString(l.input[l.pos:])
51+
l.width = width
52+
l.pos += l.width
53+
return r
54+
}
55+
56+
// ignore skips over the pending input before this point.
57+
func (l *lexer) ignore() {
58+
l.start = l.pos
59+
}
60+
61+
// backup steps bacl one rune.
62+
// Can be called only once per call of next.
63+
func (l *lexer) backup() {
64+
l.pos -= l.width
65+
}
66+
67+
// peek returns but does not consume
68+
// the next rune in the input.
69+
func (l *lexer) peek() rune {
70+
r := l.next()
71+
l.backup()
72+
return r
73+
}
74+
75+
// accept consumes the next rune
76+
// if it's from the valid set
77+
func (l *lexer) accept(valid string) bool {
78+
if strings.IndexRune(valid, l.next()) >= 0 {
79+
return true
80+
}
81+
l.backup()
82+
return false
83+
}
84+
85+
// acceptRun consumes a run of runes from the valid set.
86+
func (l *lexer) acceptRun(valid string) {
87+
for strings.IndexRune(valid, l.next()) >= 0 {
88+
}
89+
l.backup()
90+
}
91+
92+
// errorf returns an error token and terminates the scan
93+
// by passing back a nil pointer that will be the next
94+
// state, terminating l.run
95+
func (l *lexer) errorf(format string, args ...interface{}) stateFunc {
96+
l.items <- item{
97+
itemError,
98+
fmt.Sprintf(format, args...),
99+
}
100+
return nil
101+
}

0 commit comments

Comments
 (0)