use nom::branch::alt;
use nom::bytes::complete::tag;
use nom::combinator::map;
use nom::combinator::value;
use nom::IResult;
use crate::preprocessor::parser::ident;
use crate::NumberUnsigned;
use super::parser::{number, string};
use super::Span;
#[derive(Debug, Clone)]
pub struct Token {
pub location: Span,
pub token_type: TokenType,
}
impl Token {
pub(crate) fn new(location: Span, token_type: TokenType) -> Self {
Self {
location,
token_type,
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum TokenType {
OpNotequal,
OpBoolAnd,
OpLeft,
OpLessequal,
OpEqual,
OpGreatequal,
OpRight,
OpBoolXor,
OpBoolOr,
OpAbs,
OpBorrow,
CallKey,
OpCarry,
OpCeil,
OpFnotequal,
OpFmult,
OpFadd,
OpFsub,
OpFdiv,
OpFless,
OpFlessequal,
OpFequal,
OpFgreat,
OpFgreatequal,
OpFloat2float,
OpFloatSqrt,
OpFloor,
GotoKey,
IfKey,
OpInt2float,
LocalKey,
OpNan,
ReturnKey,
OpPopcount,
OpLzcount,
OpRound,
OpSrem,
OpSdiv,
OpSless,
OpSlessequal,
OpSgreat,
OpSgreatequal,
OpSright,
OpSborrow,
OpScarry,
OpSext,
OpTrunc,
OpZext,
OpGreat,
OpLess,
OpXor,
OpAnd,
OpOr,
OpNeg,
OpBitNeg,
OpAdd,
OpSub,
OpMul,
OpDiv,
OpRem,
OpAssign,
DeliOpenParenteses,
DeliCloseParenteses,
DeliOpenBrackets,
DeliCloseBrackets,
DeliOpenCurly,
DeliCloseCurly,
Comma,
DubleDot,
StatementEnd,
Ellipsis,
Unimpl,
SpaceConst,
SpaceUnique,
Underline,
Number(NumberUnsigned),
String(String),
Ident(String),
}
impl TokenType {
pub fn parse(data: &str) -> IResult<&str, Self> {
alt((
map(number, Self::Number),
alt((
value(Self::OpBoolAnd, tag("$and")),
value(Self::OpBoolXor, tag("$xor")),
value(Self::OpBoolOr, tag("$or")),
)),
alt((
value(Self::OpFnotequal, tag("f!=")),
value(Self::OpFlessequal, tag("f<=")),
value(Self::OpFequal, tag("f==")),
value(Self::OpFgreatequal, tag("f>=")),
value(Self::OpFmult, tag("f*")),
value(Self::OpFadd, tag("f+")),
value(Self::OpFsub, tag("f-")),
value(Self::OpFdiv, tag("f/")),
value(Self::OpFless, tag("f<")),
value(Self::OpFgreat, tag("f>")),
)),
alt((
value(Self::OpSlessequal, tag("s<=")),
value(Self::OpSgreatequal, tag("s>=")),
value(Self::OpSright, tag("s>>")),
value(Self::OpSrem, tag("s%")),
value(Self::OpSdiv, tag("s/")),
value(Self::OpSless, tag("s<")),
value(Self::OpSgreat, tag("s>")),
)),
alt((
value(Self::OpNotequal, tag("!=")),
value(Self::OpLeft, tag("<<")),
value(Self::OpLessequal, tag("<=")),
value(Self::OpEqual, tag("==")),
value(Self::OpGreatequal, tag(">=")),
value(Self::OpRight, tag(">>")),
value(Self::OpBoolAnd, tag("&&")),
value(Self::OpBoolXor, tag("^^")),
value(Self::OpBoolOr, tag("||")),
)),
alt((
value(Self::OpGreat, tag(">")),
value(Self::OpLess, tag("<")),
value(Self::OpXor, tag("^")),
value(Self::OpAnd, tag("&")),
value(Self::OpOr, tag("|")),
value(Self::OpNeg, tag("~")),
value(Self::OpBitNeg, tag("!")),
value(Self::OpAdd, tag("+")),
value(Self::OpSub, tag("-")),
value(Self::OpMul, tag("*")),
value(Self::OpDiv, tag("/")),
value(Self::OpRem, tag("%")),
value(Self::OpAssign, tag("=")),
)),
alt((
value(Self::DeliOpenParenteses, tag("(")),
value(Self::DeliCloseParenteses, tag(")")),
value(Self::DeliOpenBrackets, tag("[")),
value(Self::DeliCloseBrackets, tag("]")),
value(Self::DeliOpenCurly, tag("{")),
value(Self::DeliCloseCurly, tag("}")),
value(Self::Comma, tag(",")),
value(Self::DubleDot, tag(":")),
value(Self::StatementEnd, tag(";")),
value(Self::Ellipsis, tag("...")),
)),
map(string, Self::String),
Self::parse_words,
))(data)
}
fn parse_words(input: &str) -> IResult<&str, Self> {
use TokenType::*;
let (rest, name) = alt((ident, tag("_")))(input)?;
#[rustfmt::skip]
let token = match name {
"_" => Underline,
"if" => IfKey,
"abs" => OpAbs,
"nan" => OpNan,
"call" => CallKey,
"ceil" => OpCeil,
"goto" => GotoKey,
"sqrt" => OpFloatSqrt,
"sext" => OpSext,
"zext" => OpZext,
"const" => SpaceConst,
"trunc" => OpTrunc,
"carry" => OpCarry,
"floor" => OpFloor,
"local" => LocalKey,
"round" => OpRound,
"unimpl" => Unimpl,
"unique" => SpaceUnique,
"return" => ReturnKey,
"scarry" => OpScarry,
"borrow" => OpBorrow,
"sborrow" => OpSborrow,
"popcount" => OpPopcount,
"lzcount" => OpLzcount,
"int2float" => OpInt2float,
"float2float" => OpFloat2float,
other => Ident(other.to_owned()),
};
Ok((rest, token))
}
}