Added some syntax
This commit is contained in:
parent
840c75f891
commit
47d44dcd04
|
@ -1,2 +1,3 @@
|
|||
enum_discrim_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 utils;
|
||||
|
||||
use bumpalo::Bump;
|
||||
use std::io::{stdin, Read};
|
||||
use utils::default;
|
||||
use {
|
||||
bumpalo::Bump,
|
||||
std::io::{stdin, Read},
|
||||
utils::default,
|
||||
};
|
||||
|
||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let mut buf = default();
|
||||
stdin().read_to_string(&mut buf)?;
|
||||
|
||||
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(())
|
||||
}
|
||||
|
|
|
@ -59,6 +59,7 @@ pub enum Expr<'a> {
|
|||
},
|
||||
Break(Option<ExprRef<'a>>),
|
||||
Return(Option<ExprRef<'a>>),
|
||||
Uninit,
|
||||
Continue,
|
||||
}
|
||||
|
||||
|
@ -68,10 +69,10 @@ pub enum Definition<'a> {
|
|||
kind: DefKind,
|
||||
ident: Spanned<Ident>,
|
||||
ty: Option<Spanned<Type>>,
|
||||
init: Option<ExprRef<'a>>,
|
||||
init: ExprRef<'a>,
|
||||
},
|
||||
Func {
|
||||
ident: Spanned<Ident>,
|
||||
name: Spanned<Ident>,
|
||||
params: &'a [(Spanned<Ident>, Spanned<Type>)],
|
||||
ret: Spanned<Type>,
|
||||
body: ExprList<'a>,
|
||||
|
|
|
@ -1,19 +1,43 @@
|
|||
use bumpalo::Bump;
|
||||
use logos::Logos;
|
||||
|
||||
use super::{
|
||||
ast::{Definition, Spanned},
|
||||
use {
|
||||
super::{
|
||||
ast::{DefKind, Definition, Expr, ExprList, Ident, Spanned, Type},
|
||||
token::Token,
|
||||
},
|
||||
crate::syntax::token::T,
|
||||
bumpalo::{vec, Bump},
|
||||
logos::Logos,
|
||||
};
|
||||
|
||||
type Lexer<'a> = logos::Lexer<'a, Token>;
|
||||
|
||||
macro_rules! extract {
|
||||
($self:expr, $pat:pat) => {
|
||||
let $pat = $self.next()? else {
|
||||
return Err($self.error(ErrorKind::UnexpectedToken));
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! let_until {
|
||||
(
|
||||
$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())
|
||||
}
|
||||
|
||||
/// 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!
|
||||
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(&[]))
|
||||
}
|
||||
|
||||
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)]
|
||||
pub enum ErrorKind {
|
||||
InvalidToken,
|
||||
UnexpectedEnd,
|
||||
UnexpectedToken,
|
||||
}
|
||||
|
||||
pub type Error = Spanned<ErrorKind>;
|
||||
|
|
|
@ -12,7 +12,7 @@ macro_rules! token_def {
|
|||
keyword { $($kw:tt),* $(,)* }
|
||||
else { $($e_tt:tt)* }
|
||||
) => {
|
||||
literify::literify! (paste::paste! {
|
||||
literify::literify!(paste::paste! {
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Logos)]
|
||||
#[logos(extras = Extras)]
|
||||
#[logos(skip r"[ \t\n\f]+")]
|
||||
|
@ -35,6 +35,8 @@ macro_rules! token_def {
|
|||
$($(
|
||||
($u_tok) => { $crate::syntax::token::Token::$u_name };
|
||||
)*)*
|
||||
|
||||
$((~($kw)) => { $crate::syntax::token::Token::[<$kw:camel>] };)*
|
||||
}
|
||||
});
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue