Skip to content

Commit

Permalink
add 2020 operators
Browse files Browse the repository at this point in the history
  • Loading branch information
FreeMasen committed Feb 13, 2024
1 parent 31d1faa commit ea32cf0
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 4 deletions.
38 changes: 35 additions & 3 deletions src/tokenizer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -418,7 +418,7 @@ impl<'a> Tokenizer<'a> {
'[' => self.gen_punct(Punct::OpenBracket),
']' => self.gen_punct(Punct::CloseBracket),
':' => self.gen_punct(Punct::Colon),
'?' => self.gen_punct(Punct::QuestionMark),
'?' => self.question_mark(),
'#' => self.hash(),
'~' => self.gen_punct(Punct::Tilde),
'{' => self.open_curly(OpenCurlyKind::Block, Punct::OpenBrace),
Expand Down Expand Up @@ -583,6 +583,10 @@ impl<'a> Tokenizer<'a> {
trace!("ampersand ({}, {})", self.current_start, self.stream.idx);
if self.look_ahead_byte_matches('&') {
self.stream.skip_bytes(1);
if self.look_ahead_byte_matches('=') {
self.stream.skip_bytes(1);
return self.gen_punct(Punct::DoubleAmpersandEqual);
}
self.gen_punct(Punct::DoubleAmpersand)
} else if self.look_ahead_byte_matches('=') {
self.stream.skip_bytes(1);
Expand All @@ -597,6 +601,10 @@ impl<'a> Tokenizer<'a> {
trace!("pipe ({}, {})", self.current_start, self.stream.idx);
if self.look_ahead_byte_matches('|') {
self.stream.skip_bytes(1);
if self.look_ahead_byte_matches('=') {
self.stream.skip_bytes(1);
return self.gen_punct(Punct::DoublePipeEqual);
}
self.gen_punct(Punct::DoublePipe)
} else if self.look_ahead_byte_matches('=') {
self.stream.skip_bytes(1);
Expand Down Expand Up @@ -680,6 +688,7 @@ impl<'a> Tokenizer<'a> {
self.gen_punct(Punct::Caret)
}
}

/// a `#` could also be the start of a hash bang comment `#!`
#[inline]
fn hash(&mut self) -> Res<RawItem> {
Expand All @@ -696,6 +705,29 @@ impl<'a> Tokenizer<'a> {
self.gen_punct(Punct::Hash)
}
}
/// a `?` could also be the start of a ??. ??=, ?. operator
#[inline]
fn question_mark(&mut self) -> Res<RawItem> {
trace!(
"question_mark ({}, {})",
self.current_start,
self.stream.idx
);
// hashbang comment can only appear at the start
if self.look_ahead_byte_matches('?') {
self.stream.skip_bytes(1);
if self.look_ahead_byte_matches('=') {
self.stream.skip_bytes(1);
return self.gen_punct(Punct::DoubleQuestionMarkEqual);
}
self.gen_punct(Punct::DoubleQuestionMark)
} else if self.look_ahead_byte_matches('.') {
self.stream.skip_bytes(1);
self.gen_punct(Punct::QuestionMarkDot)
} else {
self.gen_punct(Punct::QuestionMark)
}
}
/// parse a number, this can include decimal or float literals
/// like `0.01e1` or `10` as well as binary, octal or hex
/// literals like `0b1`, `0o7`, or `0xf` and BigInt literals
Expand Down Expand Up @@ -1405,13 +1437,13 @@ mod test {
"-", "/", "*", "%", "&", "|", "^", ">>>=", //3 char
"...", "===", "!==", ">>>", "<<=", ">>=", "**=", //2 char
"&&", "||", "==", "!=", "+=", "-=", "*=", "/=", "++", "--", "<<", ">>", "&=", "|=",
"^=", "%=", "<=", ">=", "=>", "**", "@",
"^=", "%=", "<=", ">=", "=>", "**", "@", "??", "??=", "?.", "&&=", "||=",
];
for p in PUNCTS {
let mut t = Tokenizer::new(p);
let item = t.next(true).unwrap();
assert!(item.ty.is_punct());
assert!(t.stream.at_end());
assert!(t.stream.at_end(), "'{}' was not at the end", p);
}
}
#[test]
Expand Down
15 changes: 15 additions & 0 deletions src/tokens/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,7 @@ pub enum Punct {
DoubleDash,
DashEqual,
DoubleAmpersand,
DoubleAmpersandEqual,
DoubleAsterisk,
DoubleAsteriskEqual,
DoubleEqual,
Expand All @@ -361,7 +362,10 @@ pub enum Punct {
DoubleLessThan,
DoubleLessThanEqual,
DoublePipe,
DoublePipeEqual,
DoublePlus,
DoubleQuestionMark,
DoubleQuestionMarkEqual,
Ellipsis,
Equal,
EqualGreaterThan,
Expand All @@ -383,6 +387,7 @@ pub enum Punct {
Plus,
PlusEqual,
QuestionMark,
QuestionMarkDot,
SemiColon,
Tilde,
TripleEqual,
Expand Down Expand Up @@ -453,6 +458,11 @@ impl Punct {
Punct::DoubleAsterisk => "**" == s,
Punct::Hash => "#" == s,
Punct::AtMark => "@" == s,
Punct::DoubleAmpersandEqual => s == "&&=",
Punct::DoublePipeEqual => s == "||=",
Punct::DoubleQuestionMark => s == "??",
Punct::DoubleQuestionMarkEqual => s == "??=",
Punct::QuestionMarkDot => s == "?.",
}
}
}
Expand Down Expand Up @@ -514,6 +524,11 @@ impl ToString for Punct {
Punct::DoubleAsterisk => "**",
Punct::Hash => "#",
Punct::AtMark => "@",
Punct::DoubleAmpersandEqual => "&&=",
Punct::DoublePipeEqual => "||=",
Punct::DoubleQuestionMark => "??",
Punct::DoubleQuestionMarkEqual => "??=",
Punct::QuestionMarkDot => "?.",
}
.into()
}
Expand Down
3 changes: 2 additions & 1 deletion tests/snippets/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -363,7 +363,8 @@ fn regex_pattern() {
location,
token: Token::RegEx(re2),
..
} = scanner.next().unwrap().unwrap() else {
} = scanner.next().unwrap().unwrap()
else {
panic!("Expected regex");
};
assert_eq!(location.start.line, 1);
Expand Down

0 comments on commit ea32cf0

Please sign in to comment.