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
use logos::Lexer;
use crate::token::Token;
pub fn lex_pragma_arguments(lex: &mut Lexer<Token>) -> Option<()> {
let mut in_block_comment = false;
let mut looking_for_newline = false;
let mut ignore_newline = 0;
let mut offset = 0;
let mut iter = lex.remainder().chars().peekable();
while let Some(ch) = iter.next() {
let mut next_ch = '\0';
if let Some(ch) = iter.peek() {
next_ch = *ch;
}
if in_block_comment {
match ch {
'*' => {
if next_ch == '/' {
// Exit block comment.
in_block_comment = false;
looking_for_newline = true;
}
}
'\\' => match next_ch {
'\n' => ignore_newline += 1,
'\r' => ignore_newline += 2,
_ => {}
},
'\n' | '\r' => {
if ignore_newline > 0 {
// Line continuation.
ignore_newline -= 1;
} else {
// Newline in block comment breaks the pragma.
return Some(());
}
}
_ => {}
}
offset += 1;
} else if looking_for_newline {
// Lookahead for a newline without any non-whitespace characters.
if next_ch == '\n' || next_ch == '\r' {
// Found a newline, the block comment is not part of the pragma.
return Some(());
}
if next_ch.is_whitespace() {
offset += 1;
} else {
// Non-whitespace character found, bump the lexer and continue.
lex.bump(offset + 2);
looking_for_newline = false;
}
} else {
match ch {
'/' => {
match next_ch {
'/' => {
// Line comments break the pragma.
return Some(());
}
'*' => {
// Enter block comment.
in_block_comment = true;
continue;
}
_ => {}
}
}
'\n' | '\r' => {
if ignore_newline == 0 {
// Reached the end of the pragma.
return Some(());
}
// Line continuation.
ignore_newline -= 1;
}
'\\' => match next_ch {
'\n' => ignore_newline += 1,
'\r' => ignore_newline += 2,
_ => {}
},
_ => {}
}
lex.bump(1);
}
}
Some(())
}