struct File {}
struct FragmentId(u32);
struct Fragment {
id: FragmentId,
}
fn string_literal(lex: &mut ::logos::Lexer<Token>) -> bool {
let remainder = lex.remainder();
let mut cursor = remainder;
while let [b, rest @ ..] = cursor {
if *b == b'"' {
lex.bump((rest.as_ptr() as usize) - (remainder.as_ptr() as usize));
return true;
}
cursor = rest;
}
false
}
fn line_comment(lex: &mut ::logos::Lexer<Token>) -> bool {
let remainder = lex.remainder();
let mut cursor = remainder;
const TO_NEWLINE: u8 = b'\n' - 1;
const AFTER_NEWLINE: u8 = b'\n' + 1;
while let [0..=TO_NEWLINE | AFTER_NEWLINE..=255, rest @ ..] = cursor {
cursor = rest;
}
lex.bump(cursor.as_ptr() as usize - remainder.as_ptr() as usize);
true
}
fn reserved_word(lex: &mut ::logos::Lexer<Token>) -> bool {
macro_rules! decl_words {
($($word:ident),* $(,)?) => {
&[$(stringify!($word).as_bytes()),*]
}
}
let words: &[&[u8]] = decl_words![
__I_AM_A_RESERVED_WORD_THAT_NOBODY_WILL_EVER_USE__,
type,
prim,
intrinsic,
op,
while,
true,
false
];
words.contains(&lex.slice())
}
#[derive(::logos::Logos)]
enum Token {
#[token(b".")]
StatementTerminator,
#[token(b":")]
Colon,
#[token(b",")]
Comma,
#[token(b"(")]
OpenParen,
#[token(b")")]
CloseParen,
#[token(b"{")]
OpenCurly,
#[token(b"}")]
CloseCurly,
#[token(b"=")]
Assign,
#[token(b"@")]
At,
#[token(b"#")]
Quote,
#[token(b"%")]
Ref,
#[token(b"&&")]
And,
#[token(b"==")]
Equal,
#[token(b"->")]
Arrow,
#[token(b"=>")]
FatArrow,
#[token(b"do")]
Do,
#[token(b"fn")]
Fn,
#[token(b"if")]
If,
#[token(b"cmd")]
Cmd,
#[token(b"let")]
Let,
#[token(b"new")]
New,
#[token(b"loop")]
Loop,
#[token(b"else")]
Else,
#[token(b"meta")]
Meta,
#[token(b"break")]
Break,
#[token(b"const")]
Const,
#[token(b"builtin")]
Builtin,
#[regex("[0-9]+")]
Integer,
#[regex("[0-9]*d[0-9]+")]
DiceTerm,
#[token(b"\"", string_literal)]
StringLiteral,
#[token(b"//", line_comment)]
LineComment,
#[regex(br##"[_a-zA-Z]+"##, reserved_word, priority = 2)]
ReservedWord,
#[regex(br##"[_a-zA-Z]+"##)]
Ident,
#[regex("[\t ]+")]
Whitespace,
#[error]
Error,
}
#[cfg(test)]
mod tests {
use super::Token;
use logos::Logos;
#[test]
fn reserved_words() {
let text = "__I_AM_A_RESERVED_WORD_THAT_NOBODY_WILL_EVER_USE__";
let mut lexer = Token::lexer(text.as_bytes());
assert!(matches!(lexer.next(), Some(Token::ReservedWord)));
}
}
fn parse_fragment(input: &[u8], id: FragmentId) -> Fragment {
use ::logos::Logos;
let mut lexer = Token::lexer(input);
todo!()
}