Skip to content

Commit

Permalink
Preprocessor: fix #if parsing of tokens (#696)
Browse files Browse the repository at this point in the history
  • Loading branch information
BrettMayson authored May 14, 2024
1 parent 5bb0ca6 commit bd2a5cf
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 30 deletions.
97 changes: 70 additions & 27 deletions libs/preprocessor/src/processor/directives.rs
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,27 @@ impl Processor {
command: Rc<Token>,
stream: &mut PeekMoreIterator<impl Iterator<Item = Rc<Token>>>,
) -> Result<(), Error> {
fn value(defines: &mut Defines, token: Rc<Token>) -> Result<(Vec<Rc<Token>>, bool), Error> {
fn read_value(
stream: &mut PeekMoreIterator<impl Iterator<Item = Rc<Token>>>,
) -> Vec<Rc<Token>> {
let mut tokens = Vec::new();
while stream.peek().is_some() {
let token = stream
.peek()
.expect("peeked in the if statement, so there should be a token")
.clone();
if token.symbol().is_whitespace() || token.symbol().is_newline() {
break;
}
tokens.push(token);
stream.next();
}
tokens
}
fn resolve_value(
defines: &mut Defines,
token: Rc<Token>,
) -> Result<(Vec<Rc<Token>>, bool), Error> {
if let Some((_, definition)) = defines.get_with_gen(&token, Some(token.position())) {
if let Definition::Value(tokens) = definition {
return Ok((tokens, true));
Expand All @@ -306,8 +326,15 @@ impl Processor {
}
Ok((vec![token], false))
}
let left = self.next_value(stream, None)?;
if &Symbol::Word(String::from("__has_include")) == left.symbol() {
self.skip_whitespace(stream, None);
let left = read_value(stream);
if !left.is_empty()
&& &Symbol::Word(String::from("__has_include"))
== left
.first()
.expect("left is not empty, must exist")
.symbol()
{
if pragma.is_flagged(&Flag::Pe23IgnoreIfHasInclude) {
debug!(
"ignoring __has_include due to pragma flag, this config will not be rapified"
Expand All @@ -317,11 +344,29 @@ impl Processor {
self.skip_to_after_newline(stream, None);
return Ok(());
}
return Err(IfHasInclude::code(left.as_ref().clone()));
return Err(IfHasInclude::code(
left.first()
.expect("left is not empty, must exist")
.as_ref()
.clone(),
));
}
let (left, left_defined) = if left.len() == 1 {
resolve_value(
&mut self.defines,
left.into_iter()
.next()
.expect("length is 1, next will exist"),
)?
} else {
(left, false)
};
if left.is_empty() {
return Err(UnexpectedEOF::code(command.as_ref().clone()));
}
let (left, left_defined) = value(&mut self.defines, left)?;
self.skip_whitespace(stream, None);
let mut operators = Vec::with_capacity(2);
#[allow(unused_assignments)]
let mut operators = Vec::new();
let (right, right_defined) = if stream.peek().map(|t| t.symbol()) == Some(&Symbol::Newline)
{
let pos = stream
Expand All @@ -336,31 +381,29 @@ impl Processor {
operators = vec![equals.clone(), equals];
(vec![Rc::new(Token::new(Symbol::Digit(1), pos))], false)
} else {
loop {
let Some(token) = stream.peek() else {
return Err(UnexpectedEOF::code(
left.last()
.expect("left should exists at this point")
.as_ref()
.clone(),
));
};
if matches!(token.symbol(), Symbol::Whitespace(_)) {
stream.next();
break;
}
operators.push(token.clone());
stream.next();
}
let Some(right) = stream.next() else {
operators = read_value(stream);
self.skip_whitespace(stream, None);
let right = read_value(stream);
if right.is_empty() {
return Err(UnexpectedEOF::code(
left.last()
.expect("left should exists at this point")
operators
.last()
.expect("right should exists at this point")
.as_ref()
.clone(),
));
};
value(&mut self.defines, right)?
}
if right.len() == 1 {
resolve_value(
&mut self.defines,
right
.into_iter()
.next()
.expect("length is 1, next will exist"),
)?
} else {
(right, false)
}
};
let operator = operators
.iter()
Expand Down
1 change: 1 addition & 0 deletions libs/preprocessor/tests/bootstrap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ bootstrap!(define_use_define);
bootstrap!(define_with_dash);
bootstrap!(group_unit);
bootstrap!(hashtag_outside_macro);
bootstrap!(if_digits);
bootstrap!(if_nested);
bootstrap!(if_operators);
bootstrap!(if_pass);
Expand Down
4 changes: 4 additions & 0 deletions libs/preprocessor/tests/bootstrap/if_digits/expected.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@

val = false;

val = false;
14 changes: 14 additions & 0 deletions libs/preprocessor/tests/bootstrap/if_digits/source.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#define X 16
#define Y -18

#if X < Y
val = true;
#else
val = false;
#endif

#if 16 < -18
val = true;
#else
val = false;
#endif
6 changes: 3 additions & 3 deletions libs/preprocessor/tests/errors/pe2_unexpected_eof/stderr.ansi
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
error[PE2]: unexpected end of file
┌─ source.hpp:1:4
┌─ source.hpp:1:2
│
1 │ #if
│ ^ unexpected end of file
1 │ #if
│ ^^ unexpected end of file

0 comments on commit bd2a5cf

Please sign in to comment.