diff --git a/forge-script-lang/src/pratt/parser.rs b/forge-script-lang/src/pratt/parser.rs index 0ccdc4802883171f3fbee125537be6882bba26bc..93f49fee14767448ce30f1eecd9ed6a5b2d1d9c3 100644 --- a/forge-script-lang/src/pratt/parser.rs +++ b/forge-script-lang/src/pratt/parser.rs @@ -173,9 +173,7 @@ impl<'a> Scanner<'a> { }); } - let next_char = self.source.chars().nth(self.position.offset); - self.position.advance(1); - self.scan_state.advance(1); + let next_char = self.next(); match next_char { Some('=') => { @@ -205,6 +203,30 @@ impl<'a> Scanner<'a> { Some(';') => Ok(self.tokenise(ScriptTokenType::Semicolon)), Some('/') => Ok(self.tokenise(ScriptTokenType::Slash)), Some('*') => Ok(self.tokenise(ScriptTokenType::Asterisk)), + Some('&') => { + if next_match!(self, '&') { + Ok(self.tokenise(ScriptTokenType::DoubleAmpersand)) + } else { + Err(ScannerError { + kind: ScannerErrorKind::UnexpectedToken { + span: gen_token_span(self), + }, + position: self.position, + }) + } + } + Some('|') => { + if next_match!(self, '|') { + Ok(self.tokenise(ScriptTokenType::DoublePipe)) + } else { + Err(ScannerError { + kind: ScannerErrorKind::UnexpectedToken { + span: gen_token_span(self), + }, + position: self.position, + }) + } + } Some('<') => { if next_match!(self, '=') { Ok(self.tokenise(ScriptTokenType::LessEqual)) @@ -471,8 +493,7 @@ impl<'a> Scanner<'a> { fn next(&mut self) -> Option<char> { let ch = self.source.chars().nth(self.position.offset); - self.position.advance(1); - self.scan_state.advance(1); + self.increment_cursor(); ch } diff --git a/forge-script-lang/src/pratt/test_cases.rs b/forge-script-lang/src/pratt/test_cases.rs index dd1533811c89bb8b453fb413ccab8570b764379c..7959a013b476d2d0f461e848def7fe046839786b 100644 --- a/forge-script-lang/src/pratt/test_cases.rs +++ b/forge-script-lang/src/pratt/test_cases.rs @@ -22,6 +22,8 @@ use test_case::test_case; #[test_case("==", Ok(ScriptTokenType::EqualEqual) ; "Expects ScriptTokenType::EqualEqual")] #[test_case(">", Ok(ScriptTokenType::Greater) ; "Expects ScriptTokenType::Greater")] #[test_case(">=", Ok(ScriptTokenType::GreaterEqual) ; "Expects ScriptTokenType::GreaterEqual")] +#[test_case("&&", Ok(ScriptTokenType::DoubleAmpersand) ; "Expects ScriptTokenType::DoubleAmpersand")] +#[test_case("||", Ok(ScriptTokenType::DoublePipe) ; "Expects ScriptTokenType::DoublePipe")] #[test_case("<", Ok(ScriptTokenType::Less) ; "Expects ScriptTokenType::Less")] #[test_case("<=", Ok(ScriptTokenType::LessEqual) ; "Expects ScriptTokenType::LessEqual")] #[test_case("\"Foo\"", Ok(ScriptTokenType::String(String::from("Foo"))) ; "Expects ScriptTokenType::String")]