mirror of
https://github.com/Noratrieb/dilaria.git
synced 2026-01-14 17:35:03 +01:00
add parser
This commit is contained in:
parent
03fe10d7c0
commit
a0e17c6042
4 changed files with 163 additions and 38 deletions
65
src/ast.rs
65
src/ast.rs
|
|
@ -1,84 +1,102 @@
|
||||||
|
#![allow(dead_code)]
|
||||||
|
|
||||||
|
/// imagine interning or something here
|
||||||
|
pub type Symbol = String;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
pub struct Program(pub Block);
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub struct Block(pub Vec<Stmt>);
|
pub struct Block(pub Vec<Stmt>);
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub enum Stmt {
|
pub enum Stmt {
|
||||||
VariableDecl(VariableDecl),
|
Declaration(Declaration),
|
||||||
Assignment(Assignment),
|
Assignment(Assignment),
|
||||||
FnDecl(FnDecl),
|
FnDecl(FnDecl),
|
||||||
|
If(IfStmt),
|
||||||
|
Loop(Block),
|
||||||
|
While(WhileStmt),
|
||||||
Break,
|
Break,
|
||||||
Return(Option<Expr>),
|
Return(Option<Expr>),
|
||||||
Conditional(Conditional),
|
|
||||||
Loop(Block),
|
|
||||||
WhileLoop(WhileLoop),
|
|
||||||
ForLoop(Box<ForLoop>),
|
|
||||||
Expr(Expr),
|
Expr(Expr),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct VariableDecl {
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
name: String,
|
pub struct Declaration {
|
||||||
init: Option<Expr>,
|
name: Symbol,
|
||||||
|
init: Expr,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub struct Assignment {
|
pub struct Assignment {
|
||||||
pub lhs: Expr,
|
pub lhs: Symbol,
|
||||||
pub rhs: Expr,
|
pub rhs: Expr,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub struct FnDecl {
|
pub struct FnDecl {
|
||||||
pub name: String,
|
pub name: Symbol,
|
||||||
pub params: Vec<String>,
|
pub params: Vec<Symbol>,
|
||||||
pub body: Block,
|
pub body: Block,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Conditional {
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
pub struct IfStmt {
|
||||||
pub condition: Expr,
|
pub condition: Expr,
|
||||||
pub body: Block,
|
pub body: Block,
|
||||||
pub else_block: Option<Block>,
|
pub else_part: Box<ElsePart>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct WhileLoop {
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
pub enum ElsePart {
|
||||||
|
Else(Block),
|
||||||
|
ElseIf(IfStmt),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
pub struct WhileStmt {
|
||||||
pub cond: Expr,
|
pub cond: Expr,
|
||||||
pub body: Block,
|
pub body: Block,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ForLoop {
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub init: Stmt,
|
|
||||||
pub cond: Expr,
|
|
||||||
pub post: Stmt,
|
|
||||||
pub body: Block,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub enum Expr {
|
pub enum Expr {
|
||||||
Literal(Literal),
|
Literal(Literal),
|
||||||
UnaryOp,
|
UnaryOp,
|
||||||
BinaryOp,
|
BinaryOp,
|
||||||
Call,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub enum Literal {
|
pub enum Literal {
|
||||||
String(String),
|
String(String),
|
||||||
Number(f64),
|
Number(f64),
|
||||||
Array(Vec<Expr>),
|
Array(Vec<Expr>),
|
||||||
Object, // todo
|
Object,
|
||||||
Boolean(bool),
|
Boolean(bool),
|
||||||
Null,
|
Null,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub struct UnaryOp {
|
pub struct UnaryOp {
|
||||||
pub expr: Expr,
|
pub expr: Expr,
|
||||||
pub kind: UnaryOpKind,
|
pub kind: UnaryOpKind,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub enum UnaryOpKind {
|
pub enum UnaryOpKind {
|
||||||
Not,
|
Not,
|
||||||
Neg,
|
Neg,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub struct BinaryOp {
|
pub struct BinaryOp {
|
||||||
pub lhs: Expr,
|
pub lhs: Expr,
|
||||||
pub rhs: Expr,
|
pub rhs: Expr,
|
||||||
pub kind: BinaryOpKind,
|
pub kind: BinaryOpKind,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub enum BinaryOpKind {
|
pub enum BinaryOpKind {
|
||||||
And,
|
And,
|
||||||
Or,
|
Or,
|
||||||
|
|
@ -95,6 +113,7 @@ pub enum BinaryOpKind {
|
||||||
Mod,
|
Mod,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub enum Call {
|
pub enum Call {
|
||||||
Function(Expr, Vec<Expr>),
|
Function(Expr, Vec<Expr>),
|
||||||
Field(Expr, Vec<Expr>),
|
Field(Expr, Vec<Expr>),
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,8 @@ pub enum TokenType<'code> {
|
||||||
// ident
|
// ident
|
||||||
Ident(&'code str),
|
Ident(&'code str),
|
||||||
// punctuation
|
// punctuation
|
||||||
|
/// ;
|
||||||
|
Semi,
|
||||||
/// +
|
/// +
|
||||||
Plus,
|
Plus,
|
||||||
/// -
|
/// -
|
||||||
|
|
|
||||||
34
src/lib.rs
34
src/lib.rs
|
|
@ -8,19 +8,23 @@ pub fn run_program(program: &str) {
|
||||||
let lexer = lex::Lexer::lex(program);
|
let lexer = lex::Lexer::lex(program);
|
||||||
let (success, errors) = lexer.partition::<Vec<_>, _>(|result| result.is_ok());
|
let (success, errors) = lexer.partition::<Vec<_>, _>(|result| result.is_ok());
|
||||||
|
|
||||||
if errors.is_empty() {
|
// terrible, but works
|
||||||
println!(
|
let tokens = success.into_iter().collect::<Result<_, _>>();
|
||||||
"{:#?}",
|
let _ast = parse::parse(tokens.unwrap());
|
||||||
success
|
|
||||||
.into_iter()
|
// if errors.is_empty() {
|
||||||
.map(Result::unwrap)
|
// println!(
|
||||||
.map(|token| token.kind)
|
// "{:#?}",
|
||||||
.collect::<Vec<_>>()
|
// success
|
||||||
);
|
// .into_iter()
|
||||||
} else {
|
// .map(Result::unwrap)
|
||||||
errors
|
// .map(|token| token.kind)
|
||||||
.into_iter()
|
// .collect::<Vec<_>>()
|
||||||
.map(Result::unwrap_err)
|
// );
|
||||||
.for_each(|err| crate::errors::display_error(program, err));
|
// } else {
|
||||||
}
|
// errors
|
||||||
|
// .into_iter()
|
||||||
|
// .map(Result::unwrap_err)
|
||||||
|
// .for_each(|err| crate::errors::display_error(program, err));
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
|
||||||
100
src/parse.rs
100
src/parse.rs
|
|
@ -0,0 +1,100 @@
|
||||||
|
#![allow(dead_code)]
|
||||||
|
|
||||||
|
use crate::ast::*;
|
||||||
|
use crate::lex::{Token, TokenType};
|
||||||
|
use std::iter::Peekable;
|
||||||
|
|
||||||
|
pub fn parse(tokens: Vec<Token>) -> Result<Program, ParseErr> {
|
||||||
|
let mut parser = Parser {
|
||||||
|
tokens: tokens.into_iter().peekable(),
|
||||||
|
};
|
||||||
|
let program = parser.program()?;
|
||||||
|
Ok(program)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct Parser<'code> {
|
||||||
|
tokens: Peekable<std::vec::IntoIter<Token<'code>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
type ParseResult<'code, T> = Result<T, ParseErr<'code>>;
|
||||||
|
|
||||||
|
impl<'code> Parser<'code> {
|
||||||
|
fn program(&mut self) -> ParseResult<'code, Program> {
|
||||||
|
Ok(Program(self.block()?))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn block(&mut self) -> ParseResult<'code, Block> {
|
||||||
|
let mut stmts = Vec::new();
|
||||||
|
loop {
|
||||||
|
if let Some(Token {
|
||||||
|
kind: TokenType::BraceC,
|
||||||
|
..
|
||||||
|
}) = self.peek()
|
||||||
|
{
|
||||||
|
let _ = self.next();
|
||||||
|
return Ok(Block(stmts));
|
||||||
|
}
|
||||||
|
let stmt = self.statement()?;
|
||||||
|
stmts.push(stmt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn statement(&mut self) -> ParseResult<'code, Stmt> {
|
||||||
|
let expr = self.expression()?;
|
||||||
|
self.expect(TokenType::Semi);
|
||||||
|
Ok(Stmt::Expr(expr))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn declaration(&mut self) -> ParseResult<'code, Declaration> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn assignment(&mut self) -> ParseResult<'code, Assignment> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fn_decl(&mut self) -> ParseResult<'code, FnDecl> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn if_stmt(&mut self) -> ParseResult<'code, IfStmt> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn loop_stmt(&mut self) -> ParseResult<'code, Block> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn expression(&mut self) -> ParseResult<'code, Expr> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
// helpers
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Token<'code>> {
|
||||||
|
self.tokens.next()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn peek(&mut self) -> Option<&Token<'code>> {
|
||||||
|
self.tokens.peek()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn expect(&mut self, kind: TokenType<'code>) -> ParseResult<'code, ()> {
|
||||||
|
if let Some(token) = self.next() {
|
||||||
|
if token.kind == kind {
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
Err(ParseErr::MismatchedKind { expected: kind })
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Err(ParseErr::UnexpectedEOF { expected: kind })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum ParseErr<'code> {
|
||||||
|
MismatchedKind { expected: TokenType<'code> },
|
||||||
|
UnexpectedEOF { expected: TokenType<'code> },
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue