@@ -25,14 +25,15 @@ func Lex(input string) []Token {
2525 var tokens []Token
2626 for {
2727 tok := l .nextToken ()
28- tokens = append (tokens , tok )
2928 if tok .Type == EOF {
29+ for len (l .indentStack ) > 1 {
30+ l .indentStack = l .indentStack [:len (l .indentStack )- 1 ]
31+ tokens = append (tokens , Token {Type : DEDENT , Line : l .line , Col : l .col })
32+ }
33+ tokens = append (tokens , tok )
3034 break
3135 }
32- }
33- for len (l .indentStack ) > 1 {
34- tokens = append (tokens , Token {Type : DEDENT , Line : l .line , Col : l .col })
35- l .indentStack = l .indentStack [:len (l .indentStack )- 1 ]
36+ tokens = append (tokens , tok )
3637 }
3738 return tokens
3839}
@@ -44,38 +45,49 @@ func (l *Lexer) nextToken() Token {
4445 return tok
4546 }
4647
47- l .skipWhitespace ()
48-
49- if l .pos >= len (l .input ) {
50- return Token {Type : EOF , Literal : "" , Line : l .line , Col : l .col }
51- }
52-
53- ch := l .input [l .pos ]
54-
5548 if l .atLineStart {
5649 l .atLineStart = false
57- indent := l .countIndent ()
50+ indent := l .countAndSkipIndent ()
5851 last := l .indentStack [len (l .indentStack )- 1 ]
59- if ch == '#' || ch == '\n' || l .pos >= len (l .input ) {
52+
53+ if l .pos >= len (l .input ) {
54+ if indent < last {
55+ return l .emitDedent ()
56+ }
57+ return Token {Type : EOF , Line : l .line , Col : l .col }
58+ }
59+
60+ ch := l .input [l .pos ]
61+ if ch == '#' {
6062 l .skipLine ()
63+ l .atLineStart = true
6164 return l .nextToken ()
6265 }
66+ if ch == '\n' {
67+ l .pos ++
68+ l .line ++
69+ l .col = 0
70+ l .atLineStart = true
71+ return Token {Type : NEWLINE , Literal : "\\ n" , Line : l .line - 1 , Col : l .col }
72+ }
73+
6374 if indent > last {
6475 l .indentStack = append (l .indentStack , indent )
65- return Token {Type : INDENT , Literal : "" , Line : l .line , Col : l .col }
66- } else if indent < last {
67- for len (l .indentStack ) > 1 && l .indentStack [len (l .indentStack )- 1 ] != indent {
68- l .indentStack = l .indentStack [:len (l .indentStack )- 1 ]
69- l .pending = append (l .pending , Token {Type : DEDENT , Line : l .line , Col : l .col })
70- }
71- if len (l .indentStack ) > 1 && l .indentStack [len (l .indentStack )- 1 ] > indent {
72- l .indentStack = l .indentStack [:len (l .indentStack )- 1 ]
73- l .pending = append (l .pending , Token {Type : DEDENT , Line : l .line , Col : l .col })
74- }
75- return l .nextToken ()
76+ return Token {Type : INDENT , Line : l .line , Col : l .col }
77+ }
78+ if indent < last {
79+ return l .emitDedent ()
7680 }
81+ } else {
82+ l .skipInlineSpace ()
83+ }
84+
85+ if l .pos >= len (l .input ) {
86+ return Token {Type : EOF , Line : l .line , Col : l .col }
7787 }
7888
89+ ch := l .input [l .pos ]
90+
7991 switch {
8092 case ch == '\n' :
8193 l .pos ++
@@ -84,10 +96,6 @@ func (l *Lexer) nextToken() Token {
8496 l .atLineStart = true
8597 return Token {Type : NEWLINE , Literal : "\\ n" , Line : l .line - 1 , Col : l .col }
8698
87- case ch == '#' :
88- l .skipLine ()
89- return l .nextToken ()
90-
9199 case ch == '=' :
92100 l .pos ++
93101 l .col ++
@@ -182,42 +190,49 @@ func (l *Lexer) nextToken() Token {
182190 }
183191}
184192
185- func (l * Lexer ) skipWhitespace () {
186- for l .pos < len (l .input ) {
187- ch := l .input [l .pos ]
188- if ch == ' ' || ch == '\t' || ch == '\r' {
189- l .pos ++
190- l .col ++
191- } else {
192- break
193- }
193+ func (l * Lexer ) emitDedent () Token {
194+ for len (l .indentStack ) > 1 {
195+ l .indentStack = l .indentStack [:len (l .indentStack )- 1 ]
196+ l .pending = append (l .pending , Token {Type : DEDENT , Line : l .line , Col : l .col })
194197 }
195- }
196-
197- func (l * Lexer ) skipLine () {
198- for l .pos < len (l .input ) && l .input [l .pos ] != '\n' {
199- l .pos ++
198+ if len (l .pending ) > 0 {
199+ tok := l .pending [0 ]
200+ l .pending = l .pending [1 :]
201+ return tok
200202 }
203+ return Token {Type : DEDENT , Line : l .line , Col : l .col }
201204}
202205
203- func (l * Lexer ) countIndent () int {
204- pos := l .pos
206+ func (l * Lexer ) countAndSkipIndent () int {
205207 count := 0
206- for pos < len (l .input ) {
207- ch := l .input [pos ]
208+ for l . pos < len (l .input ) {
209+ ch := l .input [l . pos ]
208210 if ch == ' ' {
209211 count ++
210- pos ++
212+ l . pos ++
211213 } else if ch == '\t' {
212214 count += 4
213- pos ++
215+ l . pos ++
214216 } else {
215217 break
216218 }
217219 }
218220 return count
219221}
220222
223+ func (l * Lexer ) skipInlineSpace () {
224+ for l .pos < len (l .input ) && (l .input [l .pos ] == ' ' || l .input [l .pos ] == '\t' ) {
225+ l .pos ++
226+ l .col ++
227+ }
228+ }
229+
230+ func (l * Lexer ) skipLine () {
231+ for l .pos < len (l .input ) && l .input [l .pos ] != '\n' {
232+ l .pos ++
233+ }
234+ }
235+
221236func (l * Lexer ) readString (quote rune ) Token {
222237 start := l .pos
223238 l .pos ++
@@ -245,14 +260,9 @@ func (l *Lexer) readString(quote rune) Token {
245260
246261func (l * Lexer ) readNumber () Token {
247262 start := l .pos
248- hasDot := false
249263 for l .pos < len (l .input ) {
250264 ch := l .input [l .pos ]
251- if ch == '.' && ! hasDot {
252- hasDot = true
253- l .pos ++
254- l .col ++
255- } else if unicode .IsDigit (ch ) {
265+ if unicode .IsDigit (ch ) || ch == '.' {
256266 l .pos ++
257267 l .col ++
258268 } else {
0 commit comments