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
|
- [ ] IO Intrinsics
|
||||||
- [x] Print
|
- [x] Print
|
||||||
- [ ] ReadLine
|
- [ ] 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)]
|
#[derive(Debug, PartialEq, Eq, Clone)]
|
||||||
pub enum Value {
|
pub enum Value {
|
||||||
@ -10,7 +14,7 @@ pub enum Value {
|
|||||||
|
|
||||||
pub struct Interpreter {
|
pub struct Interpreter {
|
||||||
/// The variable table maps all variables by their names to their values
|
/// The variable table maps all variables by their names to their values
|
||||||
vartable: HashMap<String, Value>
|
vartable: HashMap<String, Value>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Interpreter {
|
impl Interpreter {
|
||||||
@ -103,12 +107,10 @@ impl Interpreter {
|
|||||||
Expr::Str(name) => Value::Str(name.clone()),
|
Expr::Str(name) => Value::Str(name.clone()),
|
||||||
Expr::BinOp(bo, lhs, rhs) => self.resolve_binop(bo, &lhs, &rhs),
|
Expr::BinOp(bo, lhs, rhs) => self.resolve_binop(bo, &lhs, &rhs),
|
||||||
Expr::UnOp(uo, val) => self.resolve_unop(uo, &val),
|
Expr::UnOp(uo, val) => self.resolve_unop(uo, &val),
|
||||||
Expr::Ident(name) => {
|
Expr::Ident(name) => match self.vartable.get(name) {
|
||||||
match self.vartable.get(name) {
|
|
||||||
None => panic!("Runtime error: Use of undeclared variable '{}'", 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 lhs = self.resolve_expr(lhs);
|
||||||
let rhs = self.resolve_expr(rhs);
|
let rhs = self.resolve_expr(rhs);
|
||||||
|
|
||||||
@ -158,11 +159,10 @@ impl Interpreter {
|
|||||||
match val {
|
match val {
|
||||||
Value::I64(val) => match uo {
|
Value::I64(val) => match uo {
|
||||||
UnOpType::Neg => Value::I64(-val),
|
UnOpType::Neg => Value::I64(-val),
|
||||||
}
|
},
|
||||||
_ => panic!("Invalid unary operation for type"),
|
_ => panic!("Invalid unary operation for type"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for Value {
|
impl Display for Value {
|
||||||
@ -174,11 +174,10 @@ impl Display for Value {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use super::{Interpreter, Value};
|
use super::{Interpreter, Value};
|
||||||
use crate::parser::{Expr, BinOpType};
|
use crate::ast::{BinOpType, Expr};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_interpreter_expr() {
|
fn test_interpreter_expr() {
|
||||||
|
|||||||
@ -2,3 +2,4 @@ pub mod lexer;
|
|||||||
pub mod parser;
|
pub mod parser;
|
||||||
pub mod interpreter;
|
pub mod interpreter;
|
||||||
pub mod token;
|
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};
|
use crate::{
|
||||||
|
ast::{Ast, BinOpType, Expr, Stmt, UnOpType},
|
||||||
/// Types for binary operators
|
token::{Keyword, Literal, Token},
|
||||||
#[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
|
|
||||||
*/
|
|
||||||
|
|
||||||
struct Parser<T: Iterator<Item = Token>> {
|
struct Parser<T: Iterator<Item = Token>> {
|
||||||
tokens: Peekable<T>,
|
tokens: Peekable<T>,
|
||||||
@ -131,6 +16,16 @@ impl<T: Iterator<Item = Token>> Parser<T> {
|
|||||||
Self { tokens }
|
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 {
|
fn parse(&mut self) -> Ast {
|
||||||
let mut prog = Vec::new();
|
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 {
|
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)]
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
pub enum Literal {
|
pub enum Literal {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user