11use { super :: * , CompileErrorKind :: * , TokenKind :: * } ;
22
3+ static DEDENT_RE : LazyLock < Regex > = LazyLock :: new ( || Regex :: new ( r"^[ \t\n]*\n[^ \t\n]" ) . unwrap ( ) ) ;
4+
35/// Just language lexer
46///
57/// The lexer proceeds character-by-character, as opposed to using regular
@@ -391,6 +393,12 @@ impl<'src> Lexer<'src> {
391393
392394 match indentation {
393395 Blank => {
396+ if DEDENT_RE . is_match ( self . rest ( ) ) {
397+ while self . indented ( ) {
398+ self . lex_dedent ( ) ;
399+ }
400+ }
401+
394402 if !whitespace. is_empty ( ) {
395403 while self . next_is_whitespace ( ) {
396404 self . advance ( ) ?;
@@ -1472,8 +1480,8 @@ mod tests {
14721480 Indent : " " ,
14731481 Text : "a" ,
14741482 Eol ,
1475- Eol ,
14761483 Dedent ,
1484+ Eol ,
14771485 Identifier : "b" ,
14781486 Colon ,
14791487 Eol ,
@@ -1520,8 +1528,8 @@ mod tests {
15201528 Indent ,
15211529 Text : "@mv a b" ,
15221530 Eol ,
1523- Eol ,
15241531 Dedent ,
1532+ Eol ,
15251533 Identifier : "a" ,
15261534 Colon ,
15271535 Eol ,
@@ -1531,8 +1539,8 @@ mod tests {
15311539 Whitespace : " " ,
15321540 Text : "@touch a" ,
15331541 Eol ,
1534- Eol ,
15351542 Dedent ,
1543+ Eol ,
15361544 Identifier : "d" ,
15371545 Colon ,
15381546 Whitespace ,
@@ -1541,8 +1549,8 @@ mod tests {
15411549 Indent ,
15421550 Text : "@rm c" ,
15431551 Eol ,
1544- Eol ,
15451552 Dedent ,
1553+ Eol ,
15461554 Identifier : "c" ,
15471555 Colon ,
15481556 Whitespace ,
@@ -1820,6 +1828,34 @@ mod tests {
18201828 )
18211829 }
18221830
1831+ test ! {
1832+ name: tokenize_continued_indent,
1833+ text: "
1834+ hello:
1835+ foo
1836+
1837+ bar
1838+
1839+ baz
1840+ " ,
1841+ tokens: (
1842+ Identifier : "hello" ,
1843+ Colon ,
1844+ Eol ,
1845+ Indent ,
1846+ Text : "foo" ,
1847+ Eol ,
1848+ Eol ,
1849+ Whitespace : " " ,
1850+ Text : "bar" ,
1851+ Eol ,
1852+ Dedent ,
1853+ Eol ,
1854+ Identifier : "baz" ,
1855+ Eol ,
1856+ ) ,
1857+ }
1858+
18231859 test ! {
18241860 name: tokenize_empty_lines,
18251861 text: "
@@ -1856,8 +1892,8 @@ mod tests {
18561892 Whitespace : " " ,
18571893 Text : "dsdf # whatever" ,
18581894 Eol ,
1859- Eol ,
18601895 Dedent ,
1896+ Eol ,
18611897 Comment : "# yolo" ,
18621898 Eol ,
18631899 ) ,
@@ -1978,8 +2014,8 @@ mod tests {
19782014 Whitespace : " " ,
19792015 Text : "d" ,
19802016 Eol ,
1981- Eol ,
19822017 Dedent ,
2018+ Eol ,
19832019 Comment : "# hello" ,
19842020 Eol ,
19852021 Identifier : "bob" ,
@@ -2038,8 +2074,8 @@ mod tests {
20382074 Indent ,
20392075 Text : "@mv a b" ,
20402076 Eol ,
2041- Eol ,
20422077 Dedent ,
2078+ Eol ,
20432079 Identifier : "a" ,
20442080 Colon ,
20452081 Eol ,
@@ -2049,8 +2085,8 @@ mod tests {
20492085 Whitespace : " " ,
20502086 Text : "@touch a" ,
20512087 Eol ,
2052- Eol ,
20532088 Dedent ,
2089+ Eol ,
20542090 Identifier : "d" ,
20552091 Colon ,
20562092 Whitespace ,
@@ -2059,8 +2095,8 @@ mod tests {
20592095 Indent ,
20602096 Text : "@rm c" ,
20612097 Eol ,
2062- Eol ,
20632098 Dedent ,
2099+ Eol ,
20642100 Identifier : "c" ,
20652101 Colon ,
20662102 Whitespace ,
@@ -2227,6 +2263,23 @@ mod tests {
22272263 ) ,
22282264 }
22292265
2266+ test ! {
2267+ name: tokenize_recipe_after_body,
2268+ text: "foo:\n echo FOO\n \n foo:" ,
2269+ tokens: (
2270+ Identifier : "foo" ,
2271+ Colon ,
2272+ Eol ,
2273+ Indent : " " ,
2274+ Text : "echo FOO" ,
2275+ Eol ,
2276+ Dedent ,
2277+ Eol ,
2278+ Identifier : "foo" ,
2279+ Colon ,
2280+ ) ,
2281+ }
2282+
22302283 error ! {
22312284 name: tokenize_space_then_tab,
22322285 input: "a:
0 commit comments