165 lines
3.7 KiB
Rust
165 lines
3.7 KiB
Rust
use nom::Parser;
|
|
use super::{
|
|
SpanRef,
|
|
PResult,
|
|
SpannedData,
|
|
Token,
|
|
SpanExt,
|
|
Identifier,
|
|
};
|
|
|
|
#[derive(Clone, Copy, Debug)]
|
|
/// Keywords / operators we tokenize as "standalone"
|
|
pub enum SimpleToken {
|
|
/// `=`
|
|
Assign,
|
|
/// `:`
|
|
Colon,
|
|
/// `;`
|
|
SemiColon,
|
|
/// `@` - lambda parameter alias
|
|
At,
|
|
/// `...` - accept unknown named parameters
|
|
Ellipsis,
|
|
/// `.` - attribute selection
|
|
Dot,
|
|
/// `?` - has attribute
|
|
QuestionMark,
|
|
/// `//` - attribute set update
|
|
DoubleSlash,
|
|
/// `++` - list concatenation
|
|
DoublePlus,
|
|
|
|
/// `*`
|
|
Multiplication,
|
|
/// `/`
|
|
Division,
|
|
/// `+`
|
|
Plus,
|
|
/// `-`
|
|
Minus,
|
|
|
|
/// `<`
|
|
LessThan,
|
|
/// `<=`
|
|
LessThanOrEqual,
|
|
/// `>`
|
|
GreaterThan,
|
|
/// `>=`
|
|
GreaterThanOrEqual,
|
|
/// `==`
|
|
Equal,
|
|
/// `!=`
|
|
NotEqual,
|
|
|
|
/// `!`
|
|
LogicNot,
|
|
/// `&&`
|
|
LogicAnd,
|
|
/// `||`
|
|
LogicOr,
|
|
/// `->` (`a -> b` == `!a || b`)
|
|
LogicImplication,
|
|
|
|
/// `or` - attribute selection fallback
|
|
KwOr,
|
|
/// `let`
|
|
KwLet,
|
|
/// `with`
|
|
KwWith,
|
|
/// `rec`
|
|
KwRec,
|
|
/// `inherit`
|
|
KwInherit,
|
|
/// `if`
|
|
KwIf,
|
|
/// `then`
|
|
KwThen,
|
|
/// `else`
|
|
KwElse,
|
|
/// `assert`
|
|
KwAssert,
|
|
}
|
|
|
|
// this also finds (some) path prefixes - path alternative should come before
|
|
fn ident_or_keyword(span: SpanRef) -> PResult<SpannedData<Token>> {
|
|
let (rem_span, ident_span) = nom::combinator::recognize(
|
|
nom::sequence::pair(
|
|
nom::branch::alt((
|
|
nom::character::complete::alpha1.map(|_| ()),
|
|
nom::bytes::complete::tag("_").map(|_| ()),
|
|
)),
|
|
nom::multi::many0_count(nom::branch::alt((
|
|
nom::character::complete::alphanumeric1.map(|_| ()),
|
|
nom::bytes::complete::tag("_").map(|_| ()),
|
|
nom::bytes::complete::tag("-").map(|_| ()),
|
|
)))
|
|
)
|
|
)(span)?;
|
|
let t = match ident_span.as_str() {
|
|
"or" => SimpleToken::KwOr,
|
|
"let" => SimpleToken::KwLet,
|
|
"with" => SimpleToken::KwWith,
|
|
"rec" => SimpleToken::KwRec,
|
|
"inherit" => SimpleToken::KwInherit,
|
|
"if" => SimpleToken::KwIf,
|
|
"then" => SimpleToken::KwThen,
|
|
"else" => SimpleToken::KwElse,
|
|
"assert" => SimpleToken::KwAssert,
|
|
ident => return Ok((
|
|
rem_span,
|
|
ident_span.data(Token::Identifier(Identifier::from_ref(ident))),
|
|
)),
|
|
};
|
|
Ok((rem_span, ident_span.data(Token::SimpleToken(t))))
|
|
}
|
|
|
|
fn simple_tagged(tag: &'static str, t: SimpleToken) -> impl Fn(SpanRef) -> PResult<SpannedData<Token>> {
|
|
move |span| {
|
|
let (rem_span, token_span) = nom::bytes::complete::tag(tag)(span)?;
|
|
Ok((rem_span, token_span.data(Token::SimpleToken(t))))
|
|
}
|
|
}
|
|
|
|
fn simple_op(span: SpanRef) -> PResult<SpannedData<Token>> {
|
|
nom::branch::alt((
|
|
nom::branch::alt((
|
|
simple_tagged(":", SimpleToken::Colon),
|
|
simple_tagged(";", SimpleToken::SemiColon),
|
|
simple_tagged("@", SimpleToken::At),
|
|
simple_tagged("...", SimpleToken::Ellipsis),
|
|
simple_tagged(".", SimpleToken::Dot),
|
|
simple_tagged("?", SimpleToken::QuestionMark),
|
|
simple_tagged("//", SimpleToken::DoubleSlash),
|
|
simple_tagged("++", SimpleToken::DoublePlus),
|
|
|
|
simple_tagged("*", SimpleToken::Multiplication),
|
|
simple_tagged("/", SimpleToken::Division),
|
|
simple_tagged("+", SimpleToken::Plus),
|
|
simple_tagged("-", SimpleToken::Minus),
|
|
)),
|
|
nom::branch::alt((
|
|
simple_tagged("<=", SimpleToken::LessThanOrEqual),
|
|
simple_tagged("<", SimpleToken::LessThan),
|
|
simple_tagged(">=", SimpleToken::GreaterThanOrEqual),
|
|
simple_tagged(">", SimpleToken::GreaterThan),
|
|
simple_tagged("==", SimpleToken::Equal),
|
|
simple_tagged("!=", SimpleToken::NotEqual),
|
|
|
|
simple_tagged("=", SimpleToken::Assign),
|
|
|
|
simple_tagged("!", SimpleToken::LogicNot),
|
|
simple_tagged("&&", SimpleToken::LogicAnd),
|
|
simple_tagged("||", SimpleToken::LogicOr),
|
|
simple_tagged("->", SimpleToken::LogicImplication),
|
|
)),
|
|
))(span)
|
|
}
|
|
|
|
pub(super) fn op_ident_or_keyword(span: SpanRef) -> PResult<SpannedData<Token>> {
|
|
nom::branch::alt((
|
|
simple_op,
|
|
ident_or_keyword,
|
|
))(span)
|
|
}
|