use crate::internal::as2::lexer::Stream;
use crate::internal::as2::lexer::tokens::{Token, TokenKind};
use crate::internal::span::{FileId, Span};
use serde::Serialize;
use winnow::stream::{AsBStr, Location, Stream as _};
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Serialize)]
pub enum Operator {
Add,
Assign,
AddAssign,
Sub,
SubAssign,
Divide,
DivideAssign,
Multiply,
MultiplyAssign,
Modulo,
ModuloAssign,
Increment,
Decrement,
BitAnd,
BitAndAssign,
BitOr,
BitOrAssign,
BitXor,
BitXorAssign,
BitNot,
BitShiftLeft,
BitShiftLeftAssign,
BitShiftRight,
BitShiftRightAssign,
BitShiftRightUnsigned,
BitShiftRightUnsignedAssign,
Equal,
StrictEqual,
NotEqual,
StrictNotEqual,
LessThan,
LessThanEqual,
GreaterThan,
GreaterThanEqual,
LogicalAnd,
LogicalOr,
LogicalNot,
}
impl Operator {
pub fn text(&self) -> &'static str {
match self {
Operator::BitShiftRightUnsignedAssign => ">>>=",
Operator::BitShiftRightUnsigned => ">>>",
Operator::BitShiftRightAssign => ">>=",
Operator::BitShiftLeftAssign => "<<=",
Operator::StrictNotEqual => "!==",
Operator::StrictEqual => "===",
Operator::Increment => "++",
Operator::Decrement => "--",
Operator::AddAssign => "+=",
Operator::MultiplyAssign => "*=",
Operator::DivideAssign => "/=",
Operator::SubAssign => "-=",
Operator::ModuloAssign => "%=",
Operator::BitShiftRight => ">>",
Operator::BitShiftLeft => "<<",
Operator::BitAndAssign => "&=",
Operator::BitOrAssign => "|=",
Operator::BitXorAssign => "^=",
Operator::LessThanEqual => "<=",
Operator::GreaterThanEqual => ">=",
Operator::Equal => "==",
Operator::NotEqual => "!=",
Operator::LogicalAnd => "&&",
Operator::LogicalOr => "||",
Operator::Add => "+",
Operator::Assign => "=",
Operator::Sub => "-",
Operator::Divide => "/",
Operator::Multiply => "*",
Operator::Modulo => "%",
Operator::BitAnd => "&",
Operator::BitOr => "|",
Operator::BitNot => "~",
Operator::BitXor => "^",
Operator::LessThan => "<",
Operator::GreaterThan => ">",
Operator::LogicalNot => "!",
}
}
}
pub(crate) fn lex_operator<'a>(stream: &mut Stream<'a>, file_id: FileId) -> Token<'a> {
const OPERATORS: &[(&[u8], Operator)] = &[
(b">>>=", Operator::BitShiftRightUnsignedAssign),
(b">>>", Operator::BitShiftRightUnsigned),
(b">>=", Operator::BitShiftRightAssign),
(b"<<=", Operator::BitShiftLeftAssign),
(b"!==", Operator::StrictNotEqual),
(b"===", Operator::StrictEqual),
(b"++", Operator::Increment),
(b"--", Operator::Decrement),
(b"+=", Operator::AddAssign),
(b"*=", Operator::MultiplyAssign),
(b"/=", Operator::DivideAssign),
(b"-=", Operator::SubAssign),
(b"%=", Operator::ModuloAssign),
(b">>", Operator::BitShiftRight),
(b"<<", Operator::BitShiftLeft),
(b"&=", Operator::BitAndAssign),
(b"|=", Operator::BitOrAssign),
(b"^=", Operator::BitXorAssign),
(b"<=", Operator::LessThanEqual),
(b">=", Operator::GreaterThanEqual),
(b"==", Operator::Equal),
(b"!=", Operator::NotEqual),
(b"&&", Operator::LogicalAnd),
(b"||", Operator::LogicalOr),
(b"+", Operator::Add),
(b"=", Operator::Assign),
(b"-", Operator::Sub),
(b"/", Operator::Divide),
(b"*", Operator::Multiply),
(b"%", Operator::Modulo),
(b"&", Operator::BitAnd),
(b"|", Operator::BitOr),
(b"~", Operator::BitNot),
(b"^", Operator::BitXor),
(b"<", Operator::LessThan),
(b">", Operator::GreaterThan),
(b"!", Operator::LogicalNot),
];
let available = stream.eof_offset();
OPERATORS
.iter()
.find_map(|&(pattern, operator)| {
let len = pattern.len();
(available >= len && stream.as_bstr().peek_slice(len) == pattern)
.then(|| lex_ascii_chars(stream, TokenKind::Operator(operator), len, file_id))
})
.expect("operator must match one of the patterns")
}
fn lex_ascii_chars<'a>(
stream: &mut Stream<'a>,
kind: TokenKind,
len: usize,
file_id: FileId,
) -> Token<'a> {
let start = stream.current_token_start();
let offset = len;
let raw = stream.next_slice(offset);
let end = stream.previous_token_end();
let span = Span::new_unchecked(start, end, file_id);
Token::new(kind, span, raw)
}