add parser

This commit is contained in:
nora 2021-10-30 18:29:56 +02:00
parent 03fe10d7c0
commit a0e17c6042
4 changed files with 163 additions and 38 deletions

View file

@ -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>);
#[derive(Debug, Clone, PartialEq)]
pub enum Stmt {
VariableDecl(VariableDecl),
Declaration(Declaration),
Assignment(Assignment),
FnDecl(FnDecl),
If(IfStmt),
Loop(Block),
While(WhileStmt),
Break,
Return(Option<Expr>),
Conditional(Conditional),
Loop(Block),
WhileLoop(WhileLoop),
ForLoop(Box<ForLoop>),
Expr(Expr),
}
pub struct VariableDecl {
name: String,
init: Option<Expr>,
#[derive(Debug, Clone, PartialEq)]
pub struct Declaration {
name: Symbol,
init: Expr,
}
#[derive(Debug, Clone, PartialEq)]
pub struct Assignment {
pub lhs: Expr,
pub lhs: Symbol,
pub rhs: Expr,
}
#[derive(Debug, Clone, PartialEq)]
pub struct FnDecl {
pub name: String,
pub params: Vec<String>,
pub name: Symbol,
pub params: Vec<Symbol>,
pub body: Block,
}
pub struct Conditional {
#[derive(Debug, Clone, PartialEq)]
pub struct IfStmt {
pub condition: Expr,
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 body: Block,
}
pub struct ForLoop {
pub init: Stmt,
pub cond: Expr,
pub post: Stmt,
pub body: Block,
}
#[derive(Debug, Clone, PartialEq)]
pub enum Expr {
Literal(Literal),
UnaryOp,
BinaryOp,
Call,
}
#[derive(Debug, Clone, PartialEq)]
pub enum Literal {
String(String),
Number(f64),
Array(Vec<Expr>),
Object, // todo
Object,
Boolean(bool),
Null,
}
#[derive(Debug, Clone, PartialEq)]
pub struct UnaryOp {
pub expr: Expr,
pub kind: UnaryOpKind,
}
#[derive(Debug, Clone, PartialEq)]
pub enum UnaryOpKind {
Not,
Neg,
}
#[derive(Debug, Clone, PartialEq)]
pub struct BinaryOp {
pub lhs: Expr,
pub rhs: Expr,
pub kind: BinaryOpKind,
}
#[derive(Debug, Clone, PartialEq)]
pub enum BinaryOpKind {
And,
Or,
@ -95,6 +113,7 @@ pub enum BinaryOpKind {
Mod,
}
#[derive(Debug, Clone, PartialEq)]
pub enum Call {
Function(Expr, Vec<Expr>),
Field(Expr, Vec<Expr>),

View file

@ -48,6 +48,8 @@ pub enum TokenType<'code> {
// ident
Ident(&'code str),
// punctuation
/// ;
Semi,
/// +
Plus,
/// -

View file

@ -8,19 +8,23 @@ pub fn run_program(program: &str) {
let lexer = lex::Lexer::lex(program);
let (success, errors) = lexer.partition::<Vec<_>, _>(|result| result.is_ok());
if errors.is_empty() {
println!(
"{:#?}",
success
.into_iter()
.map(Result::unwrap)
.map(|token| token.kind)
.collect::<Vec<_>>()
);
} else {
errors
.into_iter()
.map(Result::unwrap_err)
.for_each(|err| crate::errors::display_error(program, err));
}
// terrible, but works
let tokens = success.into_iter().collect::<Result<_, _>>();
let _ast = parse::parse(tokens.unwrap());
// if errors.is_empty() {
// println!(
// "{:#?}",
// success
// .into_iter()
// .map(Result::unwrap)
// .map(|token| token.kind)
// .collect::<Vec<_>>()
// );
// } else {
// errors
// .into_iter()
// .map(Result::unwrap_err)
// .for_each(|err| crate::errors::display_error(program, err));
// }
}

View file

@ -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> },
}