Added some syntax
This commit is contained in:
parent
840c75f891
commit
47d44dcd04
|
@ -1,2 +1,3 @@
|
||||||
enum_discrim_align_threshold = 16
|
enum_discrim_align_threshold = 16
|
||||||
struct_field_align_threshold = 16
|
struct_field_align_threshold = 16
|
||||||
|
imports_granularity = "one"
|
||||||
|
|
16
src/main.rs
16
src/main.rs
|
@ -3,15 +3,23 @@
|
||||||
mod syntax;
|
mod syntax;
|
||||||
mod utils;
|
mod utils;
|
||||||
|
|
||||||
use bumpalo::Bump;
|
use {
|
||||||
use std::io::{stdin, Read};
|
bumpalo::Bump,
|
||||||
use utils::default;
|
std::io::{stdin, Read},
|
||||||
|
utils::default,
|
||||||
|
};
|
||||||
|
|
||||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let mut buf = default();
|
let mut buf = default();
|
||||||
stdin().read_to_string(&mut buf)?;
|
stdin().read_to_string(&mut buf)?;
|
||||||
|
|
||||||
let arena = Bump::new();
|
let arena = Bump::new();
|
||||||
println!("{:?}", syntax::parser::parse(&buf, &arena));
|
match syntax::parser::parse(&buf, &arena) {
|
||||||
|
Ok(ast) => println!("{ast:?}"),
|
||||||
|
Err(e) => {
|
||||||
|
eprintln!("[ERROR] {e:?}");
|
||||||
|
eprintln!(" Caused at: `{}`", &buf[e.span.start..e.span.end])
|
||||||
|
}
|
||||||
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,6 +59,7 @@ pub enum Expr<'a> {
|
||||||
},
|
},
|
||||||
Break(Option<ExprRef<'a>>),
|
Break(Option<ExprRef<'a>>),
|
||||||
Return(Option<ExprRef<'a>>),
|
Return(Option<ExprRef<'a>>),
|
||||||
|
Uninit,
|
||||||
Continue,
|
Continue,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,10 +69,10 @@ pub enum Definition<'a> {
|
||||||
kind: DefKind,
|
kind: DefKind,
|
||||||
ident: Spanned<Ident>,
|
ident: Spanned<Ident>,
|
||||||
ty: Option<Spanned<Type>>,
|
ty: Option<Spanned<Type>>,
|
||||||
init: Option<ExprRef<'a>>,
|
init: ExprRef<'a>,
|
||||||
},
|
},
|
||||||
Func {
|
Func {
|
||||||
ident: Spanned<Ident>,
|
name: Spanned<Ident>,
|
||||||
params: &'a [(Spanned<Ident>, Spanned<Type>)],
|
params: &'a [(Spanned<Ident>, Spanned<Type>)],
|
||||||
ret: Spanned<Type>,
|
ret: Spanned<Type>,
|
||||||
body: ExprList<'a>,
|
body: ExprList<'a>,
|
||||||
|
|
|
@ -1,19 +1,43 @@
|
||||||
use bumpalo::Bump;
|
use {
|
||||||
use logos::Logos;
|
super::{
|
||||||
|
ast::{DefKind, Definition, Expr, ExprList, Ident, Spanned, Type},
|
||||||
use super::{
|
token::Token,
|
||||||
ast::{Definition, Spanned},
|
},
|
||||||
token::Token,
|
crate::syntax::token::T,
|
||||||
|
bumpalo::{vec, Bump},
|
||||||
|
logos::Logos,
|
||||||
};
|
};
|
||||||
|
|
||||||
type Lexer<'a> = logos::Lexer<'a, Token>;
|
type Lexer<'a> = logos::Lexer<'a, Token>;
|
||||||
|
|
||||||
macro_rules! extract {
|
macro_rules! extract {
|
||||||
|
($self:expr, $pat:pat) => {
|
||||||
|
let $pat = $self.next()? else {
|
||||||
|
return Err($self.error(ErrorKind::UnexpectedToken));
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! let_until {
|
||||||
(
|
(
|
||||||
$self:expr,
|
$self:expr,
|
||||||
$(pat:pat),* $(,)?
|
let $bind:pat,
|
||||||
|
until |$next:pat_param| $cond:expr,
|
||||||
|
$expr:expr
|
||||||
|
$(,)?
|
||||||
) => {
|
) => {
|
||||||
|
loop {
|
||||||
|
let $next = $self.next()?;
|
||||||
|
if $cond {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
let $bind = $self.next()? else {
|
||||||
|
return Err($self.error(ErrorKind::UnexpectedToken));
|
||||||
|
};
|
||||||
|
|
||||||
|
$expr;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,16 +63,133 @@ impl<'a, 'l> Parser<'a, 'l> {
|
||||||
Spanned::new(kind, self.lexer.span())
|
Spanned::new(kind, self.lexer.span())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Mark with current span
|
||||||
|
#[inline]
|
||||||
|
fn spanned<T>(&self, item: T) -> Spanned<T> {
|
||||||
|
Spanned::new(item, self.lexer.span())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Require a token to be
|
||||||
|
fn require(&mut self, token: Token) -> Result<()> {
|
||||||
|
if self.next()? != token {
|
||||||
|
Err(self.error(ErrorKind::UnexpectedToken))
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Parse everything or DIE!
|
/// Parse everything or DIE!
|
||||||
fn run(self) -> Result<&'a [Definition<'a>]> {
|
fn run(mut self) -> Result<&'a [Definition<'a>]> {
|
||||||
|
let mut defs = vec![in self.arena];
|
||||||
|
loop {
|
||||||
|
match self.lexer.next() {
|
||||||
|
Some(Ok(Token::Func)) => {
|
||||||
|
defs.push(self.func()?);
|
||||||
|
}
|
||||||
|
Some(Ok(Token::Const)) => defs.push(self.var_def(DefKind::Const)?),
|
||||||
|
Some(Ok(Token::Var)) => defs.push(self.var_def(DefKind::Var)?),
|
||||||
|
Some(Ok(_)) => return Err(self.error(ErrorKind::UnexpectedToken)),
|
||||||
|
Some(Err(())) => return Err(self.error(ErrorKind::InvalidToken)),
|
||||||
|
None => return Ok(defs.into_bump_slice()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ident(&mut self) -> Result<Spanned<Ident>> {
|
||||||
|
extract!(self, Token::Ident(id));
|
||||||
|
Ok(self.spanned(id))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ty(&mut self) -> Result<Spanned<Type>> {
|
||||||
|
extract!(self, Token::Ident(id));
|
||||||
|
Ok(self.spanned(Type::Ident(id)))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn block(&mut self) -> Result<ExprList<'a>> {
|
||||||
|
self.require(T!["{"])?;
|
||||||
|
// TODO
|
||||||
|
self.require(T!["}"])?;
|
||||||
|
|
||||||
Ok(self.arena.alloc_slice_copy(&[]))
|
Ok(self.arena.alloc_slice_copy(&[]))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn var_def(&mut self, kind: DefKind) -> Result<Definition<'a>> {
|
||||||
|
// <kind> <ident> [: <ty>] = <expr>;
|
||||||
|
// ^^^^^^
|
||||||
|
|
||||||
|
extract!(self, Token::Ident(id));
|
||||||
|
let ident = self.spanned(id);
|
||||||
|
|
||||||
|
let ty = match self.next()? {
|
||||||
|
Token::Colon => {
|
||||||
|
let r = Some(self.ty()?);
|
||||||
|
self.require(T!["="])?;
|
||||||
|
r
|
||||||
|
}
|
||||||
|
Token::Equ => None,
|
||||||
|
_ => return Err(self.error(ErrorKind::UnexpectedToken)),
|
||||||
|
};
|
||||||
|
|
||||||
|
self.require(T!["uninit"])?;
|
||||||
|
self.require(T![";"])?;
|
||||||
|
|
||||||
|
Ok(Definition::Binding {
|
||||||
|
kind,
|
||||||
|
ident,
|
||||||
|
ty,
|
||||||
|
init: self.arena.alloc(self.spanned(Expr::Uninit)),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn func(&mut self) -> Result<Definition<'a>> {
|
||||||
|
// func <ident> ($(<ident>: <ty>),*) → <ty> { … }
|
||||||
|
// ^^^^
|
||||||
|
|
||||||
|
let name = self.ident()?;
|
||||||
|
|
||||||
|
// Parameter list
|
||||||
|
let mut params = vec![in self.arena];
|
||||||
|
|
||||||
|
self.require(T!["("])?;
|
||||||
|
let mut next = self.next()?;
|
||||||
|
if next != T![")"] {
|
||||||
|
loop {
|
||||||
|
let Token::Ident(id) = next else {
|
||||||
|
return Err(self.error(ErrorKind::UnexpectedToken));
|
||||||
|
};
|
||||||
|
|
||||||
|
let id = self.spanned(id);
|
||||||
|
self.require(T![":"])?;
|
||||||
|
params.push((id, self.ty()?));
|
||||||
|
|
||||||
|
match self.next()? {
|
||||||
|
Token::RightParen => break,
|
||||||
|
Token::Comma => (),
|
||||||
|
_ => return Err(self.error(ErrorKind::UnexpectedToken)),
|
||||||
|
}
|
||||||
|
|
||||||
|
next = self.next()?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.require(T!["→"])?;
|
||||||
|
let ret = self.ty()?;
|
||||||
|
let body = self.block()?;
|
||||||
|
|
||||||
|
Ok(Definition::Func {
|
||||||
|
name,
|
||||||
|
params: params.into_bump_slice(),
|
||||||
|
ret,
|
||||||
|
body,
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||||
pub enum ErrorKind {
|
pub enum ErrorKind {
|
||||||
InvalidToken,
|
InvalidToken,
|
||||||
UnexpectedEnd,
|
UnexpectedEnd,
|
||||||
|
UnexpectedToken,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type Error = Spanned<ErrorKind>;
|
pub type Error = Spanned<ErrorKind>;
|
||||||
|
|
|
@ -12,7 +12,7 @@ macro_rules! token_def {
|
||||||
keyword { $($kw:tt),* $(,)* }
|
keyword { $($kw:tt),* $(,)* }
|
||||||
else { $($e_tt:tt)* }
|
else { $($e_tt:tt)* }
|
||||||
) => {
|
) => {
|
||||||
literify::literify! (paste::paste! {
|
literify::literify!(paste::paste! {
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Logos)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Logos)]
|
||||||
#[logos(extras = Extras)]
|
#[logos(extras = Extras)]
|
||||||
#[logos(skip r"[ \t\n\f]+")]
|
#[logos(skip r"[ \t\n\f]+")]
|
||||||
|
@ -35,6 +35,8 @@ macro_rules! token_def {
|
||||||
$($(
|
$($(
|
||||||
($u_tok) => { $crate::syntax::token::Token::$u_name };
|
($u_tok) => { $crate::syntax::token::Token::$u_name };
|
||||||
)*)*
|
)*)*
|
||||||
|
|
||||||
|
$((~($kw)) => { $crate::syntax::token::Token::[<$kw:camel>] };)*
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -72,23 +74,23 @@ token_def!(
|
||||||
return, break, continue, uninit, asm }
|
return, break, continue, uninit, asm }
|
||||||
|
|
||||||
else {
|
else {
|
||||||
#[regex(
|
#[regex(
|
||||||
r"\p{XID_Start}\p{XID_Continue}*",
|
r"\p{XID_Start}\p{XID_Continue}*",
|
||||||
|l| intern(l, l.slice()),
|
|l| intern(l, l.slice()),
|
||||||
)] Ident(Spur),
|
)] Ident(Spur),
|
||||||
|
|
||||||
#[regex(
|
#[regex(
|
||||||
"\"[^\"]*\"",
|
"\"[^\"]*\"",
|
||||||
|l| {
|
|l| {
|
||||||
let s = l.slice();
|
let s = l.slice();
|
||||||
intern(l, &s[1..s.len() - 1])
|
intern(l, &s[1..s.len() - 1])
|
||||||
},
|
},
|
||||||
)] String(Spur),
|
)] String(Spur),
|
||||||
|
|
||||||
#[regex(
|
#[regex(
|
||||||
"[0-9]+",
|
"[0-9]+",
|
||||||
|l| l.slice().parse::<u64>().ok()
|
|l| l.slice().parse::<u64>().ok()
|
||||||
)] Int(u64),
|
)] Int(u64),
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue