use crate::span::Span;
use alloc::string::String;
use alloc::vec::Vec;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
#[non_exhaustive]
pub enum TokenKind {
Eof,
Error,
Whitespace,
LineComment,
BlockComment,
Directive,
Ident,
IntLiteral,
FloatLiteral,
FixedLiteral,
CharLiteral,
WCharLiteral,
StringLiteral,
WStringLiteral,
Semicolon,
LBrace,
RBrace,
LParen,
RParen,
LBracket,
RBracket,
Less,
Greater,
GreaterGreater,
LessLess,
Comma,
Colon,
ColonColon,
Equals,
Plus,
Minus,
Star,
Slash,
Percent,
Tilde,
Pipe,
Caret,
Ampersand,
At,
SlashSlashAt,
Hash,
Abstract,
Any,
Alias,
Annotation,
Attribute,
Bitfield,
Bitmask,
Bitset,
Boolean,
Case,
Char,
Component,
Connector,
Const,
Consumes,
Context,
Custom,
Default,
Double,
Exception,
Emits,
Enum,
Eventtype,
Factory,
False,
Finder,
Fixed,
Float,
Getraises,
Home,
Import,
In,
Inout,
Int8,
Int16,
Int32,
Int64,
Interface,
Keylist,
Local,
Long,
Manages,
Map,
Mirrorport,
Module,
Multiple,
Native,
Object,
Octet,
Oneway,
Out,
Port,
Porttype,
Primarykey,
Private,
Provides,
Public,
Publishes,
Raises,
Readonly,
Sequence,
Setraises,
Short,
StringKw,
Struct,
Supports,
Switch,
True,
Truncatable,
Typedef,
Typeid,
Typename,
Typeprefix,
Uint8,
Uint16,
Uint32,
Uint64,
Union,
Unsigned,
Uses,
Valuebase,
Valuetype,
Void,
Wchar,
Wstring,
}
impl TokenKind {
#[must_use]
pub const fn is_keyword(self) -> bool {
KEYWORDS_START <= self as u16 as usize
}
#[must_use]
pub const fn is_trivia(self) -> bool {
matches!(
self,
Self::Whitespace | Self::LineComment | Self::BlockComment | Self::Directive
)
}
#[must_use]
pub const fn is_literal(self) -> bool {
matches!(
self,
Self::IntLiteral
| Self::FloatLiteral
| Self::FixedLiteral
| Self::CharLiteral
| Self::WCharLiteral
| Self::StringLiteral
| Self::WStringLiteral
| Self::True
| Self::False
)
}
}
const KEYWORDS_START: usize = TokenKind::Abstract as u16 as usize;
pub const KEYWORDS: &[(&str, TokenKind)] = &[
("abstract", TokenKind::Abstract),
("alias", TokenKind::Alias),
("annotation", TokenKind::Annotation),
("any", TokenKind::Any),
("attribute", TokenKind::Attribute),
("bitfield", TokenKind::Bitfield),
("bitmask", TokenKind::Bitmask),
("bitset", TokenKind::Bitset),
("boolean", TokenKind::Boolean),
("case", TokenKind::Case),
("char", TokenKind::Char),
("component", TokenKind::Component),
("connector", TokenKind::Connector),
("const", TokenKind::Const),
("consumes", TokenKind::Consumes),
("context", TokenKind::Context),
("custom", TokenKind::Custom),
("default", TokenKind::Default),
("double", TokenKind::Double),
("emits", TokenKind::Emits),
("enum", TokenKind::Enum),
("eventtype", TokenKind::Eventtype),
("exception", TokenKind::Exception),
("factory", TokenKind::Factory),
("FALSE", TokenKind::False),
("finder", TokenKind::Finder),
("fixed", TokenKind::Fixed),
("float", TokenKind::Float),
("getraises", TokenKind::Getraises),
("home", TokenKind::Home),
("import", TokenKind::Import),
("in", TokenKind::In),
("inout", TokenKind::Inout),
("int16", TokenKind::Int16),
("int32", TokenKind::Int32),
("int64", TokenKind::Int64),
("int8", TokenKind::Int8),
("interface", TokenKind::Interface),
("keylist", TokenKind::Keylist),
("local", TokenKind::Local),
("long", TokenKind::Long),
("manages", TokenKind::Manages),
("map", TokenKind::Map),
("mirrorport", TokenKind::Mirrorport),
("module", TokenKind::Module),
("multiple", TokenKind::Multiple),
("native", TokenKind::Native),
("Object", TokenKind::Object),
("octet", TokenKind::Octet),
("oneway", TokenKind::Oneway),
("out", TokenKind::Out),
("port", TokenKind::Port),
("porttype", TokenKind::Porttype),
("primarykey", TokenKind::Primarykey),
("private", TokenKind::Private),
("provides", TokenKind::Provides),
("public", TokenKind::Public),
("publishes", TokenKind::Publishes),
("raises", TokenKind::Raises),
("readonly", TokenKind::Readonly),
("sequence", TokenKind::Sequence),
("setraises", TokenKind::Setraises),
("short", TokenKind::Short),
("string", TokenKind::StringKw),
("struct", TokenKind::Struct),
("supports", TokenKind::Supports),
("switch", TokenKind::Switch),
("TRUE", TokenKind::True),
("truncatable", TokenKind::Truncatable),
("typedef", TokenKind::Typedef),
("typeid", TokenKind::Typeid),
("typename", TokenKind::Typename),
("typeprefix", TokenKind::Typeprefix),
("uint16", TokenKind::Uint16),
("uint32", TokenKind::Uint32),
("uint64", TokenKind::Uint64),
("uint8", TokenKind::Uint8),
("union", TokenKind::Union),
("unsigned", TokenKind::Unsigned),
("uses", TokenKind::Uses),
("ValueBase", TokenKind::Valuebase),
("valuetype", TokenKind::Valuetype),
("void", TokenKind::Void),
("wchar", TokenKind::Wchar),
("wstring", TokenKind::Wstring),
];
#[must_use]
pub fn keyword_collision(word: &str) -> Option<&'static str> {
KEYWORDS
.iter()
.find(|(keyword, _)| *keyword != word && keyword.eq_ignore_ascii_case(word))
.map(|(keyword, _)| *keyword)
}
#[must_use]
pub fn identifier_name(word: &str) -> &str {
word.strip_prefix('_').unwrap_or(word)
}
#[cfg(test)]
mod identifier_name_tests {
use super::identifier_name;
#[test]
fn the_escape_underscore_is_not_part_of_the_name() {
assert_eq!(identifier_name("_long"), "long");
assert_eq!(identifier_name("plain"), "plain");
assert_eq!(identifier_name("_switch"), "switch");
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Radix {
Decimal,
Octal,
Hex,
}
#[derive(Debug, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub enum TokenValue {
None,
Ident {
escaped: bool,
},
Int {
value: i128,
radix: Radix,
},
Char {
value: u32,
},
Text {
value: String,
},
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Token {
pub kind: TokenKind,
pub span: Span,
pub leading: Vec<Trivia>,
pub value: TokenValue,
}
impl Token {
#[must_use]
pub fn full_span(&self) -> Span {
match self.leading.first() {
Some(first) => Span::new(first.span.start, self.span.end),
None => self.span,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum TriviaKind {
Whitespace,
Newline,
LineComment,
BlockComment,
Directive,
}
impl TriviaKind {
#[must_use]
pub const fn is_comment(self) -> bool {
matches!(self, Self::LineComment | Self::BlockComment)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Trivia {
pub kind: TriviaKind,
pub span: Span,
}