From f5f29ed1e2f3314c42245e64545e1c8454b8bd14 Mon Sep 17 00:00:00 2001 From: fef Date: Sun, 31 Jul 2022 17:42:10 +0200 Subject: [PATCH] ast: save node positions --- src/ast/mod.rs | 169 ++++++++------------ src/ast/tree.rs | 403 +++++++++++++++++++++++++++++++----------------- src/lex/mod.rs | 20 ++- 3 files changed, 341 insertions(+), 251 deletions(-) diff --git a/src/ast/mod.rs b/src/ast/mod.rs index ffc0b6e..c4fde31 100644 --- a/src/ast/mod.rs +++ b/src/ast/mod.rs @@ -5,7 +5,7 @@ use crate::lex::token; use crate::lex::token::Token; use crate::lex::Lexer; -use crate::ast::tree::Operator; +use crate::ast::tree::{File, Operator}; use std::fs; use std::io; @@ -62,10 +62,10 @@ impl Parser { } self.scope.pop(); - Ok(tree::Node::File { - name: self.filename.clone(), - content: nodes, - }) + Ok(tree::Node::File( + token::Position { file: self.filename.clone(), line: 0, col: 0 }, + File { name: self.filename.clone(), content: nodes } + )) } /// ```notrust @@ -101,10 +101,10 @@ impl Parser { /// : "break" ";" /// ``` fn parse_break_stmt(&mut self) -> Result { - self.lexer.expect_kind(token::Kind::BreakKeyword)?; + let break_keyword = self.lexer.expect_kind(token::Kind::BreakKeyword)?; self.assert_scope(Scope::Loop)?; self.lexer.expect_kind(token::Kind::Semi)?; - Ok(tree::Node::Break) + Ok(tree::Node::Break(break_keyword.pos)) } /// ```notrust @@ -116,7 +116,7 @@ impl Parser { /// ``` fn parse_block_stmt(&mut self) -> Result { let mut nodes = Vec::new(); - self.lexer.expect_kind(token::Kind::OBrace)?; + let obrace = self.lexer.expect_kind(token::Kind::OBrace)?; while let Some(result) = self.lexer.peek() { match result?.kind { token::Kind::CBrace => { @@ -126,7 +126,7 @@ impl Parser { _ => nodes.push(self.parse_stmt()?), } } - Ok(tree::Node::Block(nodes)) + Ok(tree::Node::Block(obrace.pos, nodes)) } /// ```notrust @@ -135,9 +135,9 @@ impl Parser { /// ``` fn parse_return_stmt(&mut self) -> Result { self.assert_scope(Scope::Function)?; - self.lexer.expect_kind(token::Kind::ReturnKeyword)?; + let return_keyword = self.lexer.expect_kind(token::Kind::ReturnKeyword)?; let expr = self.parse_expr(&[token::Kind::Semi])?; - Ok(tree::Node::ReturnStmt(Box::new(expr))) + Ok(tree::Node::ReturnStmt(return_keyword.pos, Box::new(expr))) } /// ```notrust @@ -149,16 +149,14 @@ impl Parser { self.assert_scope_not(Scope::Target)?; self.scope.push(Scope::Target); - self.lexer.expect_kind(token::Kind::TargetKeyword)?; + let target_keyword = self.lexer.expect_kind(token::Kind::TargetKeyword)?; let name_token = self.lexer.expect_kind(token::Kind::Ident)?; + let name = tree::Node::Ident(name_token.pos, name_token.raw); let children = self.parse_block_stmt()?; self.scope.pop(); - Ok(tree::Node::Target { - name: Box::new(tree::Node::Ident(name_token.raw)), - content: Box::new(children), - }) + Ok(tree::Node::make_target_stmt(target_keyword.pos, name, children)) } /// ```notrust @@ -168,10 +166,10 @@ impl Parser { fn parse_depend_stmt(&mut self) -> Result { self.assert_scope(Scope::Target)?; self.scope.push(Scope::DepList); - self.lexer.expect_kind(token::Kind::DependKeyword)?; + let depend_keyword = self.lexer.expect_kind(token::Kind::DependKeyword)?; let rvalue = self.parse_expr(&[token::Kind::Semi])?; self.scope.pop(); - Ok(tree::Node::DepList(Box::new(rvalue))) + Ok(tree::Node::DepList(depend_keyword.pos, Box::new(rvalue))) } /// ```notrust @@ -179,22 +177,16 @@ impl Parser { /// : "if" "(" Expression ")" BlockStatement [ "else" BlockStatement ] /// ``` fn parse_if_stmt(&mut self) -> Result { - self.lexer.expect_kind(token::Kind::IfKeyword)?; + let if_keyword = self.lexer.expect_kind(token::Kind::IfKeyword)?; self.lexer.expect_kind(token::Kind::OParen)?; let condition = self.parse_expr(&[token::Kind::CParen])?; let then_block = self.parse_block_stmt()?; - let mut else_block = None; - if let Some(Ok(token)) = self.lexer.peek() { - if token.kind == token::Kind::ElseKeyword { - self.lexer.next(); - else_block = Some(Box::new(self.parse_block_stmt()?)); - } - } - Ok(tree::Node::IfStmt { - condition: Box::new(condition), - then_block: Box::new(then_block), - else_block, - }) + let else_block = if self.lexer.next_if(token::Kind::ElseKeyword).is_some() { + Some(self.parse_block_stmt()?) + } else { + None + }; + Ok(tree::Node::make_if_stmt(if_keyword.pos, condition, then_block, else_block)) } /// ```notrust @@ -202,16 +194,13 @@ impl Parser { /// : "while" "(" Expression ")" BlockStatement /// ``` fn parse_while_stmt(&mut self) -> Result { - self.lexer.expect_kind(token::Kind::WhileKeyword)?; + let while_keyword = self.lexer.expect_kind(token::Kind::WhileKeyword)?; self.scope.push(Scope::Loop); self.lexer.expect_kind(token::Kind::OParen)?; let condition = self.parse_expr(&[token::Kind::CParen])?; - let block = self.parse_block_stmt()?; + let body = self.parse_block_stmt()?; self.scope.pop(); - Ok(tree::Node::WhileStmt { - condition: Box::new(condition), - block: Box::new(block), - }) + Ok(tree::Node::make_while_stmt(while_keyword.pos, condition, body)) } /// ```notrust @@ -219,26 +208,24 @@ impl Parser { /// : "for" "(" [ Expression ] ";" [ Expression ] ";" [ Expression ] ")" BlockStatement /// ``` fn parse_for_stmt(&mut self) -> Result { - self.lexer.expect_kind(token::Kind::ForKeyword)?; + let for_keyword = self.lexer.expect_kind(token::Kind::ForKeyword)?; self.scope.push(Scope::Loop); self.lexer.expect_kind(token::Kind::OParen)?; let terminators = [token::Kind::Semi, token::Kind::Semi, token::Kind::CParen]; let mut exprs = Vec::new(); for i in 0..3 { - exprs.push(if self.lexer.next_if(terminators[i]) { + exprs.push(if self.lexer.next_if(terminators[i]).is_some() { None } else { - Some(Box::new(self.parse_expr(&terminators[i..=i])?)) + Some(self.parse_expr(&terminators[i..=i])?) }); } let body = self.parse_block_stmt()?; self.scope.pop(); - Ok(tree::Node::ForStmt { - exec: exprs.pop().unwrap(), - condition: exprs.pop().unwrap(), - setup: exprs.pop().unwrap(), - body: Box::new(body), - }) + let exec = exprs.pop().unwrap(); + let condition = exprs.pop().unwrap(); + let setup = exprs.pop().unwrap(); + Ok(tree::Node::make_for_stmt(for_keyword.pos, setup, condition, exec, body)) } /// ```notrust @@ -247,15 +234,12 @@ impl Parser { /// ``` fn parse_set_stmt(&mut self) -> Result { self.assert_scope(Scope::File)?; - self.lexer.expect_kind(token::Kind::SetKeyword)?; + let set_keyword = self.lexer.expect_kind(token::Kind::SetKeyword)?; let expr = self.parse_expr(&[token::Kind::Semi])?; match expr { - tree::Node::BinaryExpr { op, lhs, rhs } => { - if op == Operator::Eq { - Ok(tree::Node::SetExpr { - name: lhs, - val: rhs, - }) + tree::Node::BinaryExpr(_, expr) => { + if expr.op == Operator::Eq { + Ok(tree::Node::make_set_stmt(set_keyword.pos, *expr.lhs, *expr.rhs)) } else { self.syntax_error(format!("Invalid operator"), self.lexer.current().unwrap()) } @@ -272,10 +256,10 @@ impl Parser { /// : "type" Expression ";" /// ``` fn parse_type_stmt(&mut self) -> Result { - self.lexer.expect_kind(token::Kind::TypeKeyword)?; + let type_keyword = self.lexer.expect_kind(token::Kind::TypeKeyword)?; self.assert_scope(Scope::Target)?; let expr = self.parse_expr(&[token::Kind::Semi])?; - Ok(tree::Node::TypeExpr(Box::new(expr))) + Ok(tree::Node::TypeStmt(type_keyword.pos, Box::new(expr))) } /// ```notrust @@ -283,12 +267,12 @@ impl Parser { /// : "source" Expression ";" /// ``` fn parse_source_stmt(&mut self) -> Result { - self.lexer.expect_kind(token::Kind::SourceKeyword)?; + let source_keyword = self.lexer.expect_kind(token::Kind::SourceKeyword)?; self.assert_scope(Scope::Target)?; self.scope.push(Scope::SourceList); let source = self.parse_expr(&[token::Kind::Semi])?; self.scope.pop(); - Ok(tree::Node::SourceList(Box::new(source))) + Ok(tree::Node::SourceList(source_keyword.pos, Box::new(source))) } /// ```notrust @@ -354,11 +338,7 @@ impl Parser { let op_token = self.lexer.require_next()?; let op = Operator::from_token(&op_token)?; let rhs = self.parse_binary_expr_or_higher(terminators)?; - return Ok(tree::Node::BinaryExpr { - op, - lhs: Box::new(lhs), - rhs: Box::new(rhs), - }); + return Ok(tree::Node::make_binary_expr(op_token.pos, lhs, op, rhs)); } else if token.kind.binary_op_precedence().is_some() { // shoot, this wasn't an assignment, all of our work was useless self.lexer.restore(bookmark); @@ -387,7 +367,7 @@ impl Parser { &mut self, terminators: &[token::Kind], ) -> Result { - let mut expr = self.parse_unary_expr_or_higher()?; + let mut lhs = self.parse_unary_expr_or_higher()?; while let Some(Ok(token)) = self.lexer.peek() { if terminators.contains(&token.kind) { @@ -398,14 +378,10 @@ impl Parser { let op = Operator::from_token(&token)?; self.lexer.next(); let precedence = token.kind.binary_op_precedence().unwrap(); - expr = tree::Node::BinaryExpr { - op, - lhs: Box::new(expr), - rhs: Box::new(self.parse_binary_rhs(precedence, terminators)?), - }; + lhs = tree::Node::make_binary_expr(token.pos, lhs, op, self.parse_binary_rhs(precedence, terminators)?); } - Ok(expr) + Ok(lhs) } /// This is for parsing the right-hand side of a binary expression. @@ -440,11 +416,7 @@ impl Parser { if new_precedence > precedence { let op = Operator::from_token(&token)?; self.lexer.next(); - lhs = tree::Node::BinaryExpr { - op, - lhs: Box::new(lhs), - rhs: Box::new(self.parse_binary_rhs(new_precedence, terminators)?), - }; + lhs = tree::Node::make_binary_expr(token.pos, lhs, op, self.parse_binary_rhs(new_precedence, terminators)?); } else { break; } @@ -470,10 +442,7 @@ impl Parser { self.lexer.next(); // consume unary operator token let op = Operator::from_token(&token)?; let expr = self.parse_primary_expr()?; - return Ok(tree::Node::UnaryExpr { - op, - node: Box::new(expr), - }); + return Ok(tree::Node::make_unary_expr(token.pos, op, expr)); } } self.parse_primary_expr() @@ -484,6 +453,7 @@ impl Parser { /// : "(" Expression ")" /// | ArrayExpression /// | CallExpression + /// | MemberExpression /// | Identifier /// | StringLiteral /// | IntLiteral @@ -499,6 +469,9 @@ impl Parser { /// ParameterList /// : Expression [ "," ] /// | Expression "," ParameterList + /// + /// MemberExpression + /// : PrimaryExpression "." PrimaryExpression /// ``` fn parse_primary_expr(&mut self) -> Result { let token = self.lexer.require_next()?; @@ -508,7 +481,7 @@ impl Parser { self.parse_primary_expr_rest(expr) } token::Kind::Ident => { - let ident = tree::Node::Ident(String::from(token.raw)); + let ident = tree::Node::Ident(token.pos, String::from(token.raw)); self.parse_primary_expr_rest(ident) } token::Kind::IntLiteral => { @@ -520,11 +493,11 @@ impl Parser { _ => raw.parse(), } .unwrap(); - Ok(tree::Node::Int(num)) + Ok(tree::Node::Int(token.pos, num)) } - token::Kind::StringLiteral => Ok(tree::Node::String(token.raw)), - token::Kind::TrueKeyword => Ok(tree::Node::Bool(true)), - token::Kind::FalseKeyword => Ok(tree::Node::Bool(false)), + token::Kind::StringLiteral => Ok(tree::Node::String(token.pos, token.raw)), + token::Kind::TrueKeyword => Ok(tree::Node::Bool(token.pos, true)), + token::Kind::FalseKeyword => Ok(tree::Node::Bool(token.pos, false)), token::Kind::FnKeyword => { self.lexer.prev(); // parse_fn() expects to consume the keyword self.parse_fn(true) @@ -532,7 +505,7 @@ impl Parser { token::Kind::OBracket => { let elements = self.parse_delimited_list(token::Kind::Comma, token::Kind::CBracket, true)?; - Ok(tree::Node::Array(elements)) + Ok(tree::Node::Array(token.pos, elements)) } _ => self.syntax_error(format!("Unexpected token {}", token.kind), &token), } @@ -556,29 +529,19 @@ impl Parser { self.lexer.next(); let params = self.parse_delimited_list(token::Kind::Comma, token::Kind::CParen, false)?; - self.parse_primary_expr_rest(tree::Node::CallExpr { - func: Box::new(start), - params, - }) + self.parse_primary_expr_rest(tree::Node::make_call_expr(token.pos, start, params)) } token::Kind::OBracket => { // array index self.lexer.next(); let index = self.parse_expr(&[token::Kind::CBracket])?; - self.parse_primary_expr_rest(tree::Node::ArrayExpr { - array: Box::new(start), - index: Box::new(index), - }) + self.parse_primary_expr_rest(tree::Node::make_array_expr(token.pos, start, index)) } token::Kind::Dot => { // member access self.lexer.next(); let member = self.lexer.expect_kind(token::Kind::Ident)?; - self.parse_primary_expr_rest(tree::Node::BinaryExpr { - op: Operator::Dot, - lhs: Box::new(start), - rhs: Box::new(tree::Node::Ident(member.raw)), - }) + self.parse_primary_expr_rest(tree::Node::make_binary_expr(token.pos, start, Operator::Dot, tree::Node::Ident(member.pos, member.raw))) } _ => Ok(start), } @@ -596,13 +559,13 @@ impl Parser { /// ``` fn parse_fn(&mut self, allow_anonymous: bool) -> Result { self.scope.push(Scope::Function); - self.lexer.expect_kind(token::Kind::FnKeyword)?; + let fn_keyword = self.lexer.expect_kind(token::Kind::FnKeyword)?; // function name is optional (there are inline anonymous functions) let name = if let Some(Ok(token)) = self.lexer.peek() { if token.kind == token::Kind::Ident { self.lexer.next(); - Some(Box::new(tree::Node::Ident(token.raw))) + Some(tree::Node::Ident(token.pos, token.raw)) } else { None } @@ -619,7 +582,7 @@ impl Parser { let params = self.parse_delimited_list(token::Kind::Comma, token::Kind::CParen, false)?; for p in ¶ms { match p { - tree::Node::Ident(_) => continue, + tree::Node::Ident(_, _) => continue, _ => { return self .syntax_error(format!("Not an identifier"), &self.lexer.current().unwrap()) @@ -630,11 +593,7 @@ impl Parser { let body = self.parse_block_stmt()?; self.scope.pop(); - Ok(tree::Node::Fn { - name, - params, - body: Box::new(body), - }) + Ok(tree::Node::make_fn(fn_keyword.pos, name, params, body)) } /// Parse a terminated, delimited list of expressions. This is used for diff --git a/src/ast/tree.rs b/src/ast/tree.rs index d0c9eb5..d70caae 100644 --- a/src/ast/tree.rs +++ b/src/ast/tree.rs @@ -1,75 +1,93 @@ use std::fmt; -use std::fmt::Formatter; use crate::error::Error; use crate::lex::token; -use crate::lex::token::Token; +use crate::lex::token::{Position, Token}; -#[derive(Debug)] pub enum Node { - Break, - Ident(String), - DepList(Box), - SourceList(Box), - Bool(bool), - Int(i128), - String(String), - Array(Vec), - Block(Vec), - Fn { - name: Option>, - params: Vec, - body: Box, - }, - ArrayExpr { - // array access - array: Box, - index: Box, - }, - CallExpr { - // function call - func: Box, - params: Vec, - }, - IfStmt { - condition: Box, - then_block: Box, - else_block: Option>, - }, - ReturnStmt(Box), - ForStmt { - setup: Option>, - condition: Option>, - exec: Option>, - body: Box, - }, - WhileStmt { - condition: Box, - block: Box, - }, - UnaryExpr { - op: Operator, - node: Box, - }, - BinaryExpr { - op: Operator, - lhs: Box, - rhs: Box, - }, - TypeExpr(Box), - SetExpr { - name: Box, - val: Box, - }, - Target { - name: Box, - content: Box, - }, - File { - name: String, - content: Vec, - }, + Break(Position), + Ident(Position, String), + DepList(Position, Box), + SourceList(Position, Box), + Bool(Position, bool), + Int(Position, i128), + String(Position, String), + Array(Position, Vec), + Block(Position, Vec), + Fn(Position, FnStmt), + ArrayExpr(Position, ArrayExpr), + CallExpr(Position, CallExpr), + IfStmt(Position, IfStmt), + ReturnStmt(Position, Box), + ForStmt(Position, ForStmt), + WhileStmt(Position, WhileStmt), + UnaryExpr(Position, UnaryExpr), + BinaryExpr(Position, BinaryExpr), + TypeStmt(Position, Box), + SetStmt(Position, SetStmt), + TargetStmt(Position, TargetStmt), + File(Position, File), +} + +pub struct File { + pub name: String, + pub content: Vec, +} + +pub struct FnStmt { + pub name: Option>, + pub params: Vec, + pub body: Box, +} + +pub struct IfStmt { + pub condition: Box, + pub then_body: Box, + pub else_body: Option>, +} + +pub struct ForStmt { + pub setup: Option>, + pub condition: Option>, + pub exec: Option>, + pub body: Box, +} + +pub struct WhileStmt { + pub condition: Box, + pub body: Box, +} + +pub struct SetStmt { + pub name: Box, + pub val: Box, +} + +pub struct TargetStmt { + pub name: Box, + pub val: Box, +} + +pub struct BinaryExpr { + pub lhs: Box, + pub op: Operator, + pub rhs: Box, +} + +pub struct UnaryExpr { + pub op: Operator, + pub rhs: Box, +} + +pub struct CallExpr { + pub func: Box, + pub params: Vec, +} + +pub struct ArrayExpr { + pub array: Box, + pub index: Box, } #[derive(Debug, PartialEq)] @@ -108,136 +126,237 @@ pub enum Operator { } impl Node { + pub fn assert_ident(&self) -> Result<&String, Error> { + match self { + Node::Ident(_, name) => Ok(name), + _ => Err(Error::syntax_error( + self.pos().clone(), + format!("Expected an identifier, got {}", self), + )), + } + } + pub fn walk(&self, cb: fn(node: &Node, depth: u32)) { self.visit(cb, 0); } + pub fn pos(&self) -> &Position { + match self { + Node::Break(pos) => pos, + Node::Ident(pos, _) => pos, + Node::Bool(pos, _) => pos, + Node::Int(pos, _) => pos, + Node::String(pos, _) => pos, + Node::Block(pos, _) => pos, + Node::Fn(pos, _) => pos, + Node::ReturnStmt(pos, _) => pos, + Node::DepList(pos, _) => pos, + Node::SourceList(pos, _) => pos, + Node::Array(pos, _) => pos, + Node::ArrayExpr(pos, _) => pos, + Node::CallExpr(pos, _) => pos, + Node::IfStmt(pos, _) => pos, + Node::ForStmt(pos, _) => pos, + Node::WhileStmt(pos, _) => pos, + Node::UnaryExpr(pos, _) => pos, + Node::BinaryExpr(pos, _) => pos, + Node::TypeStmt(pos, _) => pos, + Node::SetStmt(pos, _) => pos, + Node::TargetStmt(pos, _) => pos, + Node::File(pos, _) => pos, + } + } + fn visit(&self, cb: fn(node: &Node, depth: u32), current_depth: u32) { cb(self, current_depth); let depth = current_depth + 1; match self { - Node::DepList(list) => list.visit(cb, depth), - Node::SourceList(list) => list.visit(cb, depth), - Node::Array(elements) => { + Node::DepList(_, list) => list.visit(cb, depth), + Node::SourceList(_, list) => list.visit(cb, depth), + Node::Array(_, elements) => { for node in elements { node.visit(cb, depth); } } - Node::Block(statements) => { + Node::Block(_, statements) => { for node in statements { node.visit(cb, depth); } } - Node::Fn { name, params, body } => { - if let Some(n) = name { + Node::Fn(_, func) => { + if let Some(n) = &func.name { n.visit(cb, depth); } - for p in params { + for p in &func.params { p.visit(cb, depth); } - body.visit(cb, depth); + func.body.visit(cb, depth); } - Node::ArrayExpr { array, index } => { - array.visit(cb, depth); - index.visit(cb, depth); + Node::ArrayExpr(_, expr) => { + expr.array.visit(cb, depth); + expr.index.visit(cb, depth); } - Node::CallExpr { func, params } => { - func.visit(cb, depth); - for p in params { + Node::CallExpr(_, expr) => { + expr.func.visit(cb, depth); + for p in &expr.params { p.visit(cb, depth); } } - Node::IfStmt { - condition, - then_block, - else_block, - } => { - condition.visit(cb, depth); - then_block.visit(cb, depth); - if let Some(eb) = else_block { + Node::IfStmt(_, stmt) => { + stmt.condition.visit(cb, depth); + stmt.then_body.visit(cb, depth); + if let Some(eb) = &stmt.else_body { eb.visit(cb, depth); } } - Node::ForStmt { setup, condition, exec, body } => { - if let Some(s) = setup { + Node::ForStmt(_, stmt) => { + if let Some(s) = &stmt.setup { s.visit(cb, depth); } - if let Some(c) = condition { + if let Some(c) = &stmt.condition { c.visit(cb, depth); } - if let Some(e) = exec { + if let Some(e) = &stmt.exec { e.visit(cb, depth); } - body.visit(cb, depth); + stmt.body.visit(cb, depth); } - Node::WhileStmt { condition, block } => { - condition.visit(cb, depth); - block.visit(cb, depth); + Node::WhileStmt(_, stmt) => { + stmt.condition.visit(cb, depth); + stmt.body.visit(cb, depth); } - Node::ReturnStmt(node) => node.visit(cb, depth), - Node::UnaryExpr { op, node } => node.visit(cb, depth), - Node::BinaryExpr { op, lhs, rhs } => { - lhs.visit(cb, depth); - rhs.visit(cb, depth); + Node::ReturnStmt(_, node) => node.visit(cb, depth), + Node::UnaryExpr(_, expr) => expr.rhs.visit(cb, depth), + Node::BinaryExpr(_, expr) => { + expr.lhs.visit(cb, depth); + expr.rhs.visit(cb, depth); } - Node::TypeExpr(node) => node.visit(cb, depth), - Node::SetExpr { name, val } => { - name.visit(cb, depth); - val.visit(cb, depth); + Node::TypeStmt(_, expr) => expr.visit(cb, depth), + Node::SetStmt(_, expr) => { + expr.name.visit(cb, depth); + expr.val.visit(cb, depth); } - Node::Target { name, content } => { - name.visit(cb, depth); - content.visit(cb, depth); + Node::TargetStmt(_, stmt) => { + stmt.name.visit(cb, depth); + stmt.val.visit(cb, depth); } - Node::File { name, content } => { - for n in content { + Node::File(_, file) => { + for n in &file.content { n.visit(cb, depth); } } _ => return, } } + + pub fn make_fn(pos: Position, name: Option, params: Vec, body: Node) -> Node { + let name = if let Some(name) = name { + Some(Box::new(name)) + } else { + None + }; + Node::Fn(pos, FnStmt { name, params, body: Box::new(body) }) + } + + pub fn make_binary_expr(pos: Position, lhs: Node, op: Operator, rhs: Node) -> Node { + Node::BinaryExpr(pos, BinaryExpr { lhs: Box::new(lhs), op, rhs: Box::new(rhs) }) + } + + pub fn make_unary_expr(pos: Position, op: Operator, rhs: Node) -> Node { + Node::UnaryExpr(pos, UnaryExpr { op, rhs: Box::new(rhs) }) + } + + pub fn make_call_expr(pos: Position, func: Node, params: Vec) -> Node { + Node::CallExpr(pos, CallExpr { func: Box::new(func), params }) + } + + pub fn make_array_expr(pos: Position, array: Node, index: Node) -> Node { + Node::ArrayExpr(pos, ArrayExpr { array: Box::new(array), index: Box::new(index) }) + } + + pub fn make_set_stmt(pos: Position, name: Node, val: Node) -> Node { + Node::SetStmt(pos, SetStmt { name: Box::new(name), val: Box::new(val) }) + } + + pub fn make_target_stmt(pos: Position, name: Node, val: Node) -> Node { + Node::TargetStmt(pos, TargetStmt { name: Box::new(name), val: Box::new(val) }) + } + + pub fn make_if_stmt(pos: Position, condition: Node, then_body: Node, else_body: Option) -> Node { + let else_body = if let Some(else_body) = else_body { + Some(Box::new(else_body)) + } else { + None + }; + Node::IfStmt(pos, IfStmt { + condition: Box::new(condition), + then_body: Box::new(then_body), + else_body, + }) + } + + pub fn make_while_stmt(pos: Position, condition: Node, body: Node) -> Node { + Node::WhileStmt(pos, WhileStmt { + condition: Box::new(condition), + body: Box::new(body) + }) + } + + pub fn make_for_stmt(pos: Position, setup: Option, condition: Option, exec: Option, body: Node) -> Node { + let setup = if let Some(setup) = setup { + Some(Box::new(setup)) + } else { + None + }; + let condition = if let Some(condition) = condition { + Some(Box::new(condition)) + } else { + None + }; + let exec = if let Some(exec) = exec { + Some(Box::new(exec)) + } else { + None + }; + Node::ForStmt(pos, ForStmt { setup, condition, exec, body: Box::new(body) }) + } } impl fmt::Display for Node { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let tmp: String; write!( f, "{}", match self { - Node::Break => "", - Node::Ident(name) => name.as_str(), - Node::Bool(b) => { + Node::Break(_) => "", + Node::Ident(_, name) => name.as_str(), + Node::Bool(_, b) => { tmp = format!("{}", b); tmp.as_str() } - Node::Int(i) => { + Node::Int(_, i) => { tmp = format!("{}", i); tmp.as_str() } - Node::String(s) => s.as_str(), - Node::Block(_) => "", - Node::Fn { name, params, body } => "fn", - Node::ReturnStmt(_) => "return", - Node::DepList(_) => "depend", - Node::SourceList(_) => "source", - Node::Array(_) => "", - Node::ArrayExpr { array, index } => "", - Node::CallExpr { func, params } => "", - Node::IfStmt { - condition, - then_block, - else_block, - } => "", - Node::ForStmt { setup, condition, exec, body } => "", - Node::WhileStmt { condition, block } => "", - Node::UnaryExpr { op, node } => op.raw(), - Node::BinaryExpr { op, lhs, rhs } => op.raw(), - Node::TypeExpr(_) => "type", - Node::SetExpr { name, val } => "set", - Node::Target { name, content } => "target", - Node::File { name, content } => "file", + Node::String(_, s) => s.as_str(), + Node::Block(_, _) => "", + Node::Fn(_, _) => "fn", + Node::ReturnStmt(_, _) => "return", + Node::DepList(_, _) => "depend", + Node::SourceList(_, _) => "source", + Node::Array(_, _) => "", + Node::ArrayExpr(_, _) => "", + Node::CallExpr(_, _) => "", + Node::IfStmt(_, _) => "", + Node::ForStmt(_, _) => "", + Node::WhileStmt(_, _) => "", + Node::UnaryExpr(_, expr) => expr.op.raw(), + Node::BinaryExpr(_, expr) => expr.op.raw(), + Node::TypeStmt(_, _) => "type", + Node::SetStmt(_, _) => "set", + Node::TargetStmt(_, _) => "target", + Node::File(pos, _) => pos.file.as_str(), } ) } @@ -321,7 +440,7 @@ impl Operator { } impl fmt::Display for Operator { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{}", self.raw()) } } @@ -331,9 +450,12 @@ pub enum Type { /// For identifier tokens (evaluates at runtime) Unknown, /// For expressions that don't emit a value - None, + Void, + Bool, Int, String, + Array, + Fn, } impl Type { @@ -353,9 +475,12 @@ impl fmt::Display for Type { "{}", match self { Type::Unknown => "", - Type::None => "()", + Type::Void => "()", + Type::Bool => "bool", Type::Int => "int", Type::String => "string", + Type::Array => "array", + Type::Fn => "fn", } ) } diff --git a/src/lex/mod.rs b/src/lex/mod.rs index 9a26453..cf10a9e 100644 --- a/src/lex/mod.rs +++ b/src/lex/mod.rs @@ -210,15 +210,17 @@ impl Lexer { } } - pub fn next_if(&mut self, kind: token::Kind) -> bool { + pub fn next_if(&mut self, kind: token::Kind) -> Option { if let Some(Ok(token)) = self.peek() { if token.kind == kind { self.next(); - return true; + Some(token) + } else { + None } + } else { + None } - - false } pub fn require_next(&mut self) -> Result { @@ -292,13 +294,17 @@ impl Lexer { Some('x') => self.read_int_literal(16), Some('o') => self.read_int_literal(8), Some('b') => self.read_int_literal(2), - Some(c @ '0'..='9') => self.syntax_error(String::from("Decimal literals must not start with a 0")), - Some(c) if c.is_ident_part() => self.syntax_error(format!("Unexpected character '{}'", c)), + Some(_c @ '0'..='9') => { + self.syntax_error(String::from("Decimal literals must not start with a 0")) + } + Some(c) if c.is_ident_part() => { + self.syntax_error(format!("Unexpected character '{}'", c)) + } _ => { // it wasn't a prefixed int literal at all, just a single 0 self.cursor.prev(); self.token_ok(token::Kind::IntLiteral) - }, + } } }