You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
232 lines
6.0 KiB
Rust
232 lines
6.0 KiB
Rust
use std::fmt;
|
|
|
|
/// A single syntactic element.
|
|
#[derive(Debug, Clone)]
|
|
pub struct Token {
|
|
pub kind: Kind,
|
|
pub pos: Position,
|
|
/// raw text
|
|
pub raw: String,
|
|
}
|
|
|
|
#[derive(Debug, Clone)]
|
|
pub struct Position {
|
|
pub file: String,
|
|
pub line: usize,
|
|
pub col: usize,
|
|
}
|
|
|
|
impl fmt::Display for Token {
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
write!(f, "{}: \"{}\"", self.kind, self.raw)
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Clone, Copy, PartialEq)]
|
|
pub enum Kind {
|
|
Ident,
|
|
OBrace,
|
|
CBrace,
|
|
OBracket,
|
|
CBracket,
|
|
OParen,
|
|
CParen,
|
|
Comma,
|
|
Semi,
|
|
|
|
Eq,
|
|
EqEq,
|
|
Bang,
|
|
BangEq,
|
|
Gt,
|
|
GtGt,
|
|
GtEq,
|
|
GtGtEq,
|
|
Lt,
|
|
LtLt,
|
|
LtEq,
|
|
LtLtEq,
|
|
Amp,
|
|
AmpAmp,
|
|
AmpEq,
|
|
AmpAmpEq,
|
|
Pipe,
|
|
PipePipe,
|
|
PipeEq,
|
|
PipePipeEq,
|
|
Caret,
|
|
CaretEq,
|
|
|
|
Plus,
|
|
PlusEq,
|
|
Minus,
|
|
MinusEq,
|
|
Asterisk,
|
|
AsteriskEq,
|
|
Slash,
|
|
SlashEq,
|
|
Percent,
|
|
PercentEq,
|
|
|
|
DependKeyword,
|
|
ElseKeyword,
|
|
FalseKeyword,
|
|
IfKeyword,
|
|
IncludeKeyword,
|
|
SetKeyword,
|
|
SourceKeyword,
|
|
TargetKeyword,
|
|
TrueKeyword,
|
|
TypeKeyword,
|
|
|
|
StringLiteral,
|
|
IntLiteral,
|
|
Comment,
|
|
}
|
|
|
|
impl Kind {
|
|
pub fn is_start_of_lhs_expr(&self) -> bool {
|
|
match self {
|
|
Kind::Ident => true,
|
|
Kind::IntLiteral => true,
|
|
Kind::StringLiteral => true,
|
|
_ => false,
|
|
}
|
|
}
|
|
|
|
pub fn is_start_of_expr(&self) -> bool {
|
|
match self {
|
|
k if k.is_start_of_lhs_expr() => true,
|
|
Kind::FalseKeyword => true,
|
|
Kind::Minus => true,
|
|
Kind::OBracket => true,
|
|
Kind::OParen => true,
|
|
Kind::TrueKeyword => true,
|
|
_ => false,
|
|
}
|
|
}
|
|
|
|
pub fn is_assignment_op(&self) -> bool {
|
|
match self {
|
|
Kind::Eq => true,
|
|
Kind::PlusEq => true,
|
|
Kind::MinusEq => true,
|
|
Kind::AsteriskEq => true,
|
|
Kind::SlashEq => true,
|
|
Kind::PercentEq => true,
|
|
Kind::GtGtEq => true,
|
|
Kind::LtLtEq => true,
|
|
Kind::PipeEq => true,
|
|
Kind::AmpEq => true,
|
|
Kind::CaretEq => true,
|
|
_ => false,
|
|
}
|
|
}
|
|
|
|
/// If this token is a binary operator, return its precedence value when
|
|
/// interpreted as such. See `operator-precedence.txt` for details.
|
|
pub fn binary_op_precedence(&self) -> Option<u32> {
|
|
match self {
|
|
Kind::Eq => Some(2),
|
|
Kind::PlusEq => Some(2),
|
|
Kind::MinusEq => Some(2),
|
|
Kind::AsteriskEq => Some(2),
|
|
Kind::SlashEq => Some(2),
|
|
Kind::PercentEq => Some(2),
|
|
Kind::AmpEq => Some(2),
|
|
Kind::PipeEq => Some(2),
|
|
Kind::CaretEq => Some(2),
|
|
Kind::GtGtEq => Some(2),
|
|
Kind::LtLtEq => Some(2),
|
|
Kind::PipePipe => Some(3),
|
|
Kind::AmpAmp => Some(4),
|
|
Kind::EqEq => Some(5),
|
|
Kind::BangEq => Some(5),
|
|
Kind::Gt => Some(5),
|
|
Kind::GtEq => Some(5),
|
|
Kind::Lt => Some(5),
|
|
Kind::LtEq => Some(5),
|
|
Kind::Pipe => Some(6),
|
|
Kind::Caret => Some(7),
|
|
Kind::Amp => Some(8),
|
|
Kind::GtGt => Some(9),
|
|
Kind::LtLt => Some(9),
|
|
Kind::Plus => Some(10),
|
|
Kind::Minus => Some(10),
|
|
Kind::Asterisk => Some(11),
|
|
Kind::Slash => Some(11),
|
|
Kind::Percent => Some(11),
|
|
_ => None,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl fmt::Display for Kind {
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
write!(
|
|
f,
|
|
"{}",
|
|
match self {
|
|
Kind::Ident => "ident",
|
|
Kind::OBrace => "obrace",
|
|
Kind::CBrace => "cbrace",
|
|
Kind::OBracket => "obracket",
|
|
Kind::CBracket => "cbracket",
|
|
Kind::OParen => "oparen",
|
|
Kind::CParen => "cparen",
|
|
Kind::Comma => "comma",
|
|
Kind::Semi => "semi",
|
|
|
|
Kind::Eq => "eq",
|
|
Kind::EqEq => "eqeq",
|
|
Kind::Bang => "bang",
|
|
Kind::BangEq => "bangeq",
|
|
Kind::Gt => "gt",
|
|
Kind::GtGt => "gtgt",
|
|
Kind::GtEq => "gteq",
|
|
Kind::GtGtEq => "gtgteq",
|
|
Kind::Lt => "lt",
|
|
Kind::LtLt => "ltlt",
|
|
Kind::LtEq => "lteq",
|
|
Kind::LtLtEq => "ltlteq",
|
|
Kind::Amp => "amp",
|
|
Kind::AmpAmp => "ampamp",
|
|
Kind::AmpEq => "ampeq",
|
|
Kind::AmpAmpEq => "ampampeq",
|
|
Kind::Pipe => "pipe",
|
|
Kind::PipePipe => "pipepipe",
|
|
Kind::PipeEq => "pipeeq",
|
|
Kind::PipePipeEq => "pipepipeeq",
|
|
Kind::Caret => "caret",
|
|
Kind::CaretEq => "careteq",
|
|
|
|
Kind::Plus => "plus",
|
|
Kind::PlusEq => "pluseq",
|
|
Kind::Minus => "minus",
|
|
Kind::MinusEq => "minuseq",
|
|
Kind::Asterisk => "asterisk",
|
|
Kind::AsteriskEq => "asteriskeq",
|
|
Kind::Slash => "slash",
|
|
Kind::SlashEq => "slasheq",
|
|
Kind::Percent => "percent",
|
|
Kind::PercentEq => "percenteq",
|
|
|
|
Kind::DependKeyword => "keyword",
|
|
Kind::ElseKeyword => "keyword",
|
|
Kind::FalseKeyword => "keyword",
|
|
Kind::IfKeyword => "keyword",
|
|
Kind::IncludeKeyword => "keyword",
|
|
Kind::SetKeyword => "keyword",
|
|
Kind::SourceKeyword => "keyword",
|
|
Kind::TargetKeyword => "keyword",
|
|
Kind::TrueKeyword => "keyword",
|
|
Kind::TypeKeyword => "keyword",
|
|
|
|
Kind::StringLiteral => "string",
|
|
Kind::IntLiteral => "int",
|
|
Kind::Comment => "comment",
|
|
}
|
|
)
|
|
}
|
|
}
|