Partial refactoring of parser
This commit is contained in:
parent
9e3a642810
commit
e28b3c4f37
28
README.md
28
README.md
@ -27,3 +27,31 @@
|
||||
- [ ] IO Intrinsics
|
||||
- [x] Print
|
||||
- [ ] ReadLine
|
||||
|
||||
## Grammar
|
||||
### Expressions
|
||||
```
|
||||
LITERAL = I64 | Str
|
||||
expr_primary = LITERAL | IDENT | "(" expr ")" | "-" expr_primary
|
||||
expr_mul = expr_primary (("*" | "/" | "%") expr_primary)*
|
||||
expr_add = expr_mul (("+" | "-") expr_mul)*
|
||||
expr_shift = expr_add ((">>" | "<<") expr_add)*
|
||||
expr_rel = expr_shift ((">" | ">=" | "<" | "<=") expr_shift)*
|
||||
expr_equ = expr_rel (("==" | "!=") expr_rel)*
|
||||
expr_band = expr_equ ("&" expr_equ)*
|
||||
expr_bxor = expr_band ("^" expr_band)*
|
||||
expr_bor = expr_bxor ("|" expr_bxor)*
|
||||
expr = expr_bor
|
||||
```
|
||||
|
||||
## Statements
|
||||
```
|
||||
stmt_expr = expr
|
||||
stmt_let = "let" IDENT "=" expr
|
||||
stmt_while = "while" expr "{" (stmt)* "}"
|
||||
stmt_for = "for" stmt_let ";" expr ";" expr "{" (stmt)* "}"
|
||||
stmt_if = "if" expr "{" (stmt)* "}" ( "else" "{" (stmt)* "}" )
|
||||
stmt_dbgprint = "$$" expr
|
||||
stmt_print = "$" expr
|
||||
stmt = stmt_expr | stmt_let | stmt_while | stmt_for | stmt_if | stmt_dbgprint | stmt_print
|
||||
```
|
||||
|
||||
104
src/ast.rs
Normal file
104
src/ast.rs
Normal file
@ -0,0 +1,104 @@
|
||||
use std::rc::Rc;
|
||||
|
||||
/// Types for binary operators
|
||||
#[derive(Debug, PartialEq, Eq, Clone)]
|
||||
pub enum BinOpType {
|
||||
/// Addition
|
||||
Add,
|
||||
|
||||
/// Subtraction
|
||||
Sub,
|
||||
|
||||
/// Multiplication
|
||||
Mul,
|
||||
|
||||
/// Divide
|
||||
Div,
|
||||
|
||||
/// Modulo
|
||||
Mod,
|
||||
|
||||
/// Bitwise OR (inclusive or)
|
||||
BOr,
|
||||
|
||||
/// Bitwise And
|
||||
BAnd,
|
||||
|
||||
/// Bitwise Xor (exclusive or)
|
||||
BXor,
|
||||
|
||||
/// Shift Left
|
||||
Shl,
|
||||
|
||||
/// Shift Right
|
||||
Shr,
|
||||
|
||||
/// Check equality
|
||||
Equ,
|
||||
|
||||
/// Check unequality
|
||||
Neq,
|
||||
|
||||
/// Check greater than
|
||||
Gt,
|
||||
|
||||
/// Check greater or equal
|
||||
Ge,
|
||||
|
||||
/// Check less than
|
||||
Lt,
|
||||
|
||||
/// Check less or equal
|
||||
Le,
|
||||
|
||||
/// Assign to a variable
|
||||
Assign,
|
||||
}
|
||||
|
||||
/// Types for unary operators
|
||||
#[derive(Debug, PartialEq, Eq, Clone)]
|
||||
pub enum UnOpType {
|
||||
/// Negation
|
||||
Neg,
|
||||
}
|
||||
|
||||
/// A full program abstract syntax tree. This consists of zero or more statements that represents
|
||||
/// a program.
|
||||
#[derive(Debug, PartialEq, Eq, Clone)]
|
||||
pub struct Ast {
|
||||
pub prog: Vec<Stmt>,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone)]
|
||||
pub enum Stmt {
|
||||
/// Just a simple expression. This might be an assignment, a function call or a calculation.
|
||||
Expr(Expr),
|
||||
/// A variable declaration and assignment. (variable name, assigned value)
|
||||
Let(String, Expr),
|
||||
/// A while loop consisting of a condition and a body. (condition, body)
|
||||
While(Expr, Ast),
|
||||
/// A for loop consisting of an initialization declaration, a condition, an advancement and a
|
||||
/// body. ((variable name, initial value), condition, advancement, body)
|
||||
For((String, Expr), Expr, Expr, Ast),
|
||||
/// If statement consisting of a condition, a true_body and a false_body.
|
||||
/// (condition, true_body, false_body)
|
||||
If(Expr, Ast, Ast),
|
||||
/// Debug print the value of an expression (show the internal type together with the value)
|
||||
DbgPrint(Expr),
|
||||
/// Print the value of an expression
|
||||
Print(Expr),
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone)]
|
||||
pub enum Expr {
|
||||
/// Integer literal (64-bit)
|
||||
I64(i64),
|
||||
/// String literal
|
||||
Str(Rc<String>),
|
||||
/// Identifier (variable name)
|
||||
Ident(String),
|
||||
/// Binary operation. Consists of type, left hand side and right hand side
|
||||
BinOp(BinOpType, Box<Expr>, Box<Expr>),
|
||||
/// Unary operation. Consists of type and the value that is operated on
|
||||
UnOp(UnOpType, Box<Expr>),
|
||||
}
|
||||
@ -1,6 +1,10 @@
|
||||
use std::{collections::HashMap, rc::Rc, fmt::Display};
|
||||
use std::{collections::HashMap, fmt::Display, rc::Rc};
|
||||
|
||||
use crate::{parser::{Expr, BinOpType, UnOpType, Ast, Stmt, parse}, lexer::lex};
|
||||
use crate::{
|
||||
ast::{Ast, BinOpType, Expr, Stmt, UnOpType},
|
||||
lexer::lex,
|
||||
parser::parse,
|
||||
};
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone)]
|
||||
pub enum Value {
|
||||
@ -10,7 +14,7 @@ pub enum Value {
|
||||
|
||||
pub struct Interpreter {
|
||||
/// The variable table maps all variables by their names to their values
|
||||
vartable: HashMap<String, Value>
|
||||
vartable: HashMap<String, Value>,
|
||||
}
|
||||
|
||||
impl Interpreter {
|
||||
@ -103,12 +107,10 @@ impl Interpreter {
|
||||
Expr::Str(name) => Value::Str(name.clone()),
|
||||
Expr::BinOp(bo, lhs, rhs) => self.resolve_binop(bo, &lhs, &rhs),
|
||||
Expr::UnOp(uo, val) => self.resolve_unop(uo, &val),
|
||||
Expr::Ident(name) => {
|
||||
match self.vartable.get(name) {
|
||||
Expr::Ident(name) => match self.vartable.get(name) {
|
||||
None => panic!("Runtime error: Use of undeclared variable '{}'", name),
|
||||
Some(val) => val.clone()
|
||||
}
|
||||
}
|
||||
Some(val) => val.clone(),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@ -125,7 +127,6 @@ impl Interpreter {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
let lhs = self.resolve_expr(lhs);
|
||||
let rhs = self.resolve_expr(rhs);
|
||||
|
||||
@ -158,11 +159,10 @@ impl Interpreter {
|
||||
match val {
|
||||
Value::I64(val) => match uo {
|
||||
UnOpType::Neg => Value::I64(-val),
|
||||
}
|
||||
},
|
||||
_ => panic!("Invalid unary operation for type"),
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
impl Display for Value {
|
||||
@ -174,11 +174,10 @@ impl Display for Value {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::{Interpreter, Value};
|
||||
use crate::parser::{Expr, BinOpType};
|
||||
use crate::ast::{BinOpType, Expr};
|
||||
|
||||
#[test]
|
||||
fn test_interpreter_expr() {
|
||||
|
||||
@ -2,3 +2,4 @@ pub mod lexer;
|
||||
pub mod parser;
|
||||
pub mod interpreter;
|
||||
pub mod token;
|
||||
pub mod ast;
|
||||
|
||||
144
src/parser.rs
144
src/parser.rs
@ -1,124 +1,9 @@
|
||||
use std::{iter::Peekable, rc::Rc};
|
||||
use std::iter::Peekable;
|
||||
|
||||
use crate::token::{Keyword, Literal, Token};
|
||||
|
||||
/// Types for binary operators
|
||||
#[derive(Debug, PartialEq, Eq, Clone)]
|
||||
pub enum BinOpType {
|
||||
/// Addition
|
||||
Add,
|
||||
|
||||
/// Subtraction
|
||||
Sub,
|
||||
|
||||
/// Multiplication
|
||||
Mul,
|
||||
|
||||
/// Divide
|
||||
Div,
|
||||
|
||||
/// Modulo
|
||||
Mod,
|
||||
|
||||
/// Bitwise OR (inclusive or)
|
||||
BOr,
|
||||
|
||||
/// Bitwise And
|
||||
BAnd,
|
||||
|
||||
/// Bitwise Xor (exclusive or)
|
||||
BXor,
|
||||
|
||||
/// Shift Left
|
||||
Shl,
|
||||
|
||||
/// Shift Right
|
||||
Shr,
|
||||
|
||||
/// Check equality
|
||||
Equ,
|
||||
|
||||
/// Check unequality
|
||||
Neq,
|
||||
|
||||
/// Check greater than
|
||||
Gt,
|
||||
|
||||
/// Check greater or equal
|
||||
Ge,
|
||||
|
||||
/// Check less than
|
||||
Lt,
|
||||
|
||||
/// Check less or equal
|
||||
Le,
|
||||
|
||||
/// Assign to a variable
|
||||
Assign,
|
||||
}
|
||||
|
||||
/// Types for unary operators
|
||||
#[derive(Debug, PartialEq, Eq, Clone)]
|
||||
pub enum UnOpType {
|
||||
/// Negation
|
||||
Neg,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone)]
|
||||
pub struct Ast {
|
||||
pub prog: Vec<Stmt>,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone)]
|
||||
pub enum Stmt {
|
||||
Expr(Expr),
|
||||
Let(String, Expr),
|
||||
While(Expr, Ast),
|
||||
For((String, Expr), Expr, Expr, Ast),
|
||||
If(Expr, Ast, Ast),
|
||||
DbgPrint(Expr),
|
||||
Print(Expr),
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone)]
|
||||
pub enum Expr {
|
||||
/// Integer literal (64-bit)
|
||||
I64(i64),
|
||||
/// String literal
|
||||
Str(Rc<String>),
|
||||
/// Identifier (variable name)
|
||||
Ident(String),
|
||||
/// Binary operation. Consists of type, left hand side and right hand side
|
||||
BinOp(BinOpType, Box<Expr>, Box<Expr>),
|
||||
/// Unary operation. Consists of type and the value that is operated on
|
||||
UnOp(UnOpType, Box<Expr>),
|
||||
}
|
||||
|
||||
/*
|
||||
## Grammar
|
||||
### Expressions
|
||||
LITERAL = I64 | Str
|
||||
expr_primary = LITERAL | IDENT | "(" expr ")" | "-" expr_primary
|
||||
expr_mul = expr_primary (("*" | "/" | "%") expr_primary)*
|
||||
expr_add = expr_mul (("+" | "-") expr_mul)*
|
||||
expr_shift = expr_add ((">>" | "<<") expr_add)*
|
||||
expr_rel = expr_shift ((">" | ">=" | "<" | "<=") expr_shift)*
|
||||
expr_equ = expr_rel (("==" | "!=") expr_rel)*
|
||||
expr_band = expr_equ ("&" expr_equ)*
|
||||
expr_bxor = expr_band ("^") expr_band)*
|
||||
expr_bor = expr_bxor ("|" expr_bxor)*
|
||||
expr = expr_bor
|
||||
|
||||
## Statements
|
||||
stmt_expr = expr
|
||||
stmt_let = "let" IDENT "=" expr
|
||||
stmt_while = "while" expr "{" (stmt)* "}"
|
||||
stmt_for = "for" stmt_let ";" expr ";" expr "{" (stmt)* "}"
|
||||
stmt_if = "if" expr "{" (stmt)* "}" ( "else" "{" (stmt)* "}" )
|
||||
stmt_dbgprint = "$$" expr
|
||||
stmt_print = "$" expr
|
||||
stmt = stmt_expr | stmt_let | stmt_while | stmt_for | stmt_if | stmt_dbgprint | stmt_print
|
||||
*/
|
||||
use crate::{
|
||||
ast::{Ast, BinOpType, Expr, Stmt, UnOpType},
|
||||
token::{Keyword, Literal, Token},
|
||||
};
|
||||
|
||||
struct Parser<T: Iterator<Item = Token>> {
|
||||
tokens: Peekable<T>,
|
||||
@ -131,6 +16,16 @@ impl<T: Iterator<Item = Token>> Parser<T> {
|
||||
Self { tokens }
|
||||
}
|
||||
|
||||
/// Get the next Token without removing it
|
||||
fn peek(&mut self) -> &Token {
|
||||
self.tokens.peek().unwrap_or(&Token::EoF)
|
||||
}
|
||||
|
||||
/// Advance to next Token and return the removed Token
|
||||
fn next(&mut self) -> Token {
|
||||
self.tokens.next().unwrap_or(Token::EoF)
|
||||
}
|
||||
|
||||
fn parse(&mut self) -> Ast {
|
||||
let mut prog = Vec::new();
|
||||
|
||||
@ -340,15 +235,6 @@ impl<T: Iterator<Item = Token>> Parser<T> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the next Token without removing it
|
||||
fn peek(&mut self) -> &Token {
|
||||
self.tokens.peek().unwrap_or(&Token::EoF)
|
||||
}
|
||||
|
||||
/// Advance to next Token and return the removed Token
|
||||
fn next(&mut self) -> Token {
|
||||
self.tokens.next().unwrap_or(Token::EoF)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse<T: Iterator<Item = Token>, A: IntoIterator<IntoIter = T>>(tokens: A) -> Ast {
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
use crate::parser::BinOpType;
|
||||
use crate::ast::BinOpType;
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub enum Literal {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user