forked from digineo/go-uci
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathitems.go
126 lines (108 loc) · 2.56 KB
/
items.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
package uci
import "fmt"
// item represents a lexeme (token)
//
// https://talks.golang.org/2011/lex.slide#8
type item struct {
typ itemType
val string
pos int
}
// itemType defines the kind of lexed item
//
// https://talks.golang.org/2011/lex.slide#9
type itemType int
// these items define the UCI language
const (
itemError itemType = iota // error occurred; item.val is text of error
itemBOF // begin of file; lexing starts here
itemEOF // end of file; lexing ends here
itemPackage // package keyword
itemConfig // config keyword
itemOption // option keyword
itemList // list keyword
itemIdent // identifier string
itemString // quoted string
)
func (t itemType) String() string {
switch t {
case itemError:
return "Error"
case itemBOF:
return "BOF"
case itemEOF:
return "EOF"
case itemPackage:
return "Package"
case itemConfig:
return "Config"
case itemOption:
return "Option"
case itemList:
return "List"
case itemIdent:
return "Ident"
case itemString:
return "String"
}
return fmt.Sprintf("%%itemType(%d)", int(t))
}
// keyword represents a special marker of the input: each (trimmed,
// non-empty) line of the input must start with a keywords
type keyword string
// these are the recognized keywords.
const (
kwPackage = keyword("package")
kwConfig = keyword("config")
kwOption = keyword("option")
kwList = keyword("list")
)
// String implements fmt.Stringer interface. Useful for debugging
//
// https://talks.golang.org/2011/lex.slide#11
func (i item) String() string {
if i.pos < 0 {
if i.typ != itemError && len(i.val) > 25 {
return fmt.Sprintf("(%s %.25q...)", i.typ, i.val)
}
return fmt.Sprintf("(%s %q)", i.typ, i.val)
}
if i.typ != itemError && len(i.val) > 25 {
return fmt.Sprintf("(%s %.25q... %d)", i.typ, i.val, i.pos)
}
return fmt.Sprintf("(%s %q %d)", i.typ, i.val, i.pos)
}
type scanFn func(*scanner) scanFn
type scanToken int
const (
tokError scanToken = iota
tokEOF
tokPackage // item-seq: (package, string)
tokSection // item-seq: (config, ident, maybe string)
tokOption // item-seq: (option, ident, string)
tokList // item-seq: (list, ident, string)
)
func (t scanToken) String() string {
switch t {
case tokEOF:
return "eof"
case tokError:
return "error"
case tokPackage:
return "package"
case tokSection:
return "config"
case tokOption:
return "option"
case tokList:
return "list"
}
return fmt.Sprintf("%%scanToken(%d)", int(t))
}
type token struct {
typ scanToken
items []item
}
func (t token) String() string {
return fmt.Sprintf("%s%s", t.typ, t.items)
}