-
Notifications
You must be signed in to change notification settings - Fork 8
/
datemath.l
157 lines (123 loc) · 2.48 KB
/
datemath.l
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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
/*
This file is used with golex to generate a lexer that has a signature compatible with goyacc.
Many constants referred to below are defined by goyacc when creating template.y.go
See https://godoc.org/modernc.org/golex for more about golex
*/
%{
package datemath
import (
"bytes"
"fmt"
"strconv"
)
const (
// 0 is expected by the goyacc generated parser to indicate EOF
eofCode = 0
)
// lexer holds the state of the lexer
type lexer struct {
src *bytes.Reader
buf []byte
current byte
pos int
errors []string
}
func newLexer(b []byte) *lexer {
l := &lexer{
src: bytes.NewReader(b),
}
// queue up a byte
l.next()
return l
}
func (l *lexer) Error(s string) {
l.errors = append(l.errors, fmt.Sprintf("%s at character %d starting with %q", s, l.pos, string(l.buf)))
}
func (l *lexer) next() {
if l.current != 0 {
l.buf = append(l.buf, l.current)
}
l.current = 0
if b, err := l.src.ReadByte(); err == nil {
l.current = b
}
l.pos++
}
func (l *lexer) Lex(lval *yySymType) int {
%}
/* give some regular expressions more semantic names for use below */
eof \0
/* tell golex how to determine the current start condition */
%yyt l.startCondition
/* tell golex how to determine the current byte */
%yyc l.current
/* tell golex how to advance to the next byte */
%yyn l.next()
%%
// runs before each token is parsed
l.buf = l.buf[:0]
[0-9]
i, err := strconv.ParseInt(string(l.buf), 10, 0)
if err != nil {
panic(fmt.Sprintf("could not parse digit as number: %s", err))
}
lval.i = int(i)
return tDIGIT
"now"
return tNOW
"+"
return tPLUS
"-"
return tMINUS
":"
return tCOLON
"||"
return tPIPES
"/"
return tBACKSLASH
[yMwdbhHmsQ]
switch l.buf[0] {
case 'y':
lval.unit = timeUnitYear
case 'Q':
lval.unit = timeUnitQuarter
case 'M':
lval.unit = timeUnitMonth
case 'w':
lval.unit = timeUnitWeek
case 'b':
lval.unit = timeUnitBusinessDay
case 'd':
lval.unit = timeUnitDay
case 'h', 'H':
lval.unit = timeUnitHour
case 'm':
lval.unit = timeUnitMinute
case 's':
lval.unit = timeUnitSecond
default:
panic(fmt.Sprintf("unknown time unit: %q", l.buf[0]))
}
return tUNIT
"fy"
lval.unit = timeUnitFiscalYear
return tUNIT
"fQ"
lval.unit = timeUnitFiscalQuarter
return tUNIT
\.
return tDOT
"T"
return tTIME_DELIMITER
"Z"
return tUTC
{eof}
return eofCode
no.
return tINVALID_TOKEN
.
return tINVALID_TOKEN
%%
// should never get here
panic("scanner internal error")
}