Add comments to parser
This commit is contained in:
parent
d7001a5c52
commit
f8e5bd7423
26
src/ast.rs
26
src/ast.rs
@ -122,3 +122,29 @@ pub enum Statement {
|
|||||||
pub struct Ast {
|
pub struct Ast {
|
||||||
pub prog: Vec<Statement>,
|
pub prog: Vec<Statement>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl BinOpType {
|
||||||
|
/// Get the precedence for a binary operator. Higher value means the OP is stronger binding.
|
||||||
|
/// For example Multiplication is stronger than addition, so Mul has higher precedence than Add.
|
||||||
|
///
|
||||||
|
/// The operator precedences are derived from the C language operator precedences. While not all
|
||||||
|
/// C operators are included or the exact same, the precedence oder is the same.
|
||||||
|
/// See: https://en.cppreference.com/w/c/language/operator_precedence
|
||||||
|
|
||||||
|
pub fn precedence(&self) -> u8 {
|
||||||
|
match self {
|
||||||
|
BinOpType::Declare => 0,
|
||||||
|
BinOpType::Assign => 1,
|
||||||
|
BinOpType::LOr => 2,
|
||||||
|
BinOpType::LAnd => 3,
|
||||||
|
BinOpType::BOr => 4,
|
||||||
|
BinOpType::BXor => 5,
|
||||||
|
BinOpType::BAnd => 6,
|
||||||
|
BinOpType::EquEqu | BinOpType::NotEqu => 7,
|
||||||
|
BinOpType::Less | BinOpType::LessEqu | BinOpType::Greater | BinOpType::GreaterEqu => 8,
|
||||||
|
BinOpType::Shl | BinOpType::Shr => 9,
|
||||||
|
BinOpType::Add | BinOpType::Sub => 10,
|
||||||
|
BinOpType::Mul | BinOpType::Div | BinOpType::Mod => 11,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -3,6 +3,12 @@ use std::iter::Peekable;
|
|||||||
use crate::token::Token;
|
use crate::token::Token;
|
||||||
use crate::ast::*;
|
use crate::ast::*;
|
||||||
|
|
||||||
|
/// Parse the given tokens into an abstract syntax tree
|
||||||
|
pub fn parse<T: Iterator<Item = Token>, A: IntoIterator<IntoIter = T>>(tokens: A) -> Ast {
|
||||||
|
let mut parser = Parser::new(tokens);
|
||||||
|
parser.parse()
|
||||||
|
}
|
||||||
|
|
||||||
struct Parser<T: Iterator<Item = Token>> {
|
struct Parser<T: Iterator<Item = Token>> {
|
||||||
tokens: Peekable<T>,
|
tokens: Peekable<T>,
|
||||||
}
|
}
|
||||||
@ -14,6 +20,8 @@ impl<T: Iterator<Item = Token>> Parser<T> {
|
|||||||
Self { tokens }
|
Self { tokens }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Parse tokens into an abstract syntax tree. This will continuously parse statements until
|
||||||
|
/// encountering end-of-file or a block end '}' .
|
||||||
fn parse(&mut self) -> Ast {
|
fn parse(&mut self) -> Ast {
|
||||||
let mut prog = Vec::new();
|
let mut prog = Vec::new();
|
||||||
|
|
||||||
@ -38,6 +46,7 @@ impl<T: Iterator<Item = Token>> Parser<T> {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Parse a single statement from the tokens.
|
||||||
fn parse_stmt(&mut self) -> Statement {
|
fn parse_stmt(&mut self) -> Statement {
|
||||||
match self.peek() {
|
match self.peek() {
|
||||||
Token::Loop => Statement::Loop(self.parse_loop()),
|
Token::Loop => Statement::Loop(self.parse_loop()),
|
||||||
@ -71,6 +80,7 @@ impl<T: Iterator<Item = Token>> Parser<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Parse an if statement from the tokens
|
||||||
fn parse_if(&mut self) -> If {
|
fn parse_if(&mut self) -> If {
|
||||||
if !matches!(self.next(), Token::If) {
|
if !matches!(self.next(), Token::If) {
|
||||||
panic!("Error lexing if: Expected if token");
|
panic!("Error lexing if: Expected if token");
|
||||||
@ -107,6 +117,7 @@ impl<T: Iterator<Item = Token>> Parser<T> {
|
|||||||
If { condition, body_true, body_false }
|
If { condition, body_true, body_false }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Parse a loop statement from the tokens
|
||||||
fn parse_loop(&mut self) -> Loop {
|
fn parse_loop(&mut self) -> Loop {
|
||||||
if !matches!(self.next(), Token::Loop) {
|
if !matches!(self.next(), Token::Loop) {
|
||||||
panic!("Error lexing loop: Expected loop token");
|
panic!("Error lexing loop: Expected loop token");
|
||||||
@ -143,6 +154,7 @@ impl<T: Iterator<Item = Token>> Parser<T> {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Parse a single expression from the tokens
|
||||||
fn parse_expr(&mut self) -> Expression {
|
fn parse_expr(&mut self) -> Expression {
|
||||||
let lhs = self.parse_primary();
|
let lhs = self.parse_primary();
|
||||||
self.parse_expr_precedence(lhs, 0)
|
self.parse_expr_precedence(lhs, 0)
|
||||||
@ -232,37 +244,6 @@ impl<T: Iterator<Item = Token>> Parser<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse<T: Iterator<Item = Token>, A: IntoIterator<IntoIter = T>>(tokens: A) -> Ast {
|
|
||||||
let mut parser = Parser::new(tokens);
|
|
||||||
parser.parse()
|
|
||||||
}
|
|
||||||
|
|
||||||
impl BinOpType {
|
|
||||||
/// Get the precedence for a binary operator. Higher value means the OP is stronger binding.
|
|
||||||
/// For example Multiplication is stronger than addition, so Mul has higher precedence than Add.
|
|
||||||
///
|
|
||||||
/// The operator precedences are derived from the C language operator precedences. While not all
|
|
||||||
/// C operators are included or the exact same, the precedence oder is the same.
|
|
||||||
/// See: https://en.cppreference.com/w/c/language/operator_precedence
|
|
||||||
|
|
||||||
fn precedence(&self) -> u8 {
|
|
||||||
match self {
|
|
||||||
BinOpType::Declare => 0,
|
|
||||||
BinOpType::Assign => 1,
|
|
||||||
BinOpType::LOr => 2,
|
|
||||||
BinOpType::LAnd => 3,
|
|
||||||
BinOpType::BOr => 4,
|
|
||||||
BinOpType::BXor => 5,
|
|
||||||
BinOpType::BAnd => 6,
|
|
||||||
BinOpType::EquEqu | BinOpType::NotEqu => 7,
|
|
||||||
BinOpType::Less | BinOpType::LessEqu | BinOpType::Greater | BinOpType::GreaterEqu => 8,
|
|
||||||
BinOpType::Shl | BinOpType::Shr => 9,
|
|
||||||
BinOpType::Add | BinOpType::Sub => 10,
|
|
||||||
BinOpType::Mul | BinOpType::Div | BinOpType::Mod => 11,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::{parse, Expression, BinOpType};
|
use super::{parse, Expression, BinOpType};
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user