ast: save node positions

main
anna 2 years ago
parent bdb5f9ad4b
commit f5f29ed1e2
Signed by: fef
GPG Key ID: EC22E476DC2D3D84

@ -5,7 +5,7 @@ use crate::lex::token;
use crate::lex::token::Token; use crate::lex::token::Token;
use crate::lex::Lexer; use crate::lex::Lexer;
use crate::ast::tree::Operator; use crate::ast::tree::{File, Operator};
use std::fs; use std::fs;
use std::io; use std::io;
@ -62,10 +62,10 @@ impl Parser {
} }
self.scope.pop(); self.scope.pop();
Ok(tree::Node::File { Ok(tree::Node::File(
name: self.filename.clone(), token::Position { file: self.filename.clone(), line: 0, col: 0 },
content: nodes, File { name: self.filename.clone(), content: nodes }
}) ))
} }
/// ```notrust /// ```notrust
@ -101,10 +101,10 @@ impl Parser {
/// : "break" ";" /// : "break" ";"
/// ``` /// ```
fn parse_break_stmt(&mut self) -> Result<tree::Node, Error> { fn parse_break_stmt(&mut self) -> Result<tree::Node, Error> {
self.lexer.expect_kind(token::Kind::BreakKeyword)?; let break_keyword = self.lexer.expect_kind(token::Kind::BreakKeyword)?;
self.assert_scope(Scope::Loop)?; self.assert_scope(Scope::Loop)?;
self.lexer.expect_kind(token::Kind::Semi)?; self.lexer.expect_kind(token::Kind::Semi)?;
Ok(tree::Node::Break) Ok(tree::Node::Break(break_keyword.pos))
} }
/// ```notrust /// ```notrust
@ -116,7 +116,7 @@ impl Parser {
/// ``` /// ```
fn parse_block_stmt(&mut self) -> Result<tree::Node, Error> { fn parse_block_stmt(&mut self) -> Result<tree::Node, Error> {
let mut nodes = Vec::new(); 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() { while let Some(result) = self.lexer.peek() {
match result?.kind { match result?.kind {
token::Kind::CBrace => { token::Kind::CBrace => {
@ -126,7 +126,7 @@ impl Parser {
_ => nodes.push(self.parse_stmt()?), _ => nodes.push(self.parse_stmt()?),
} }
} }
Ok(tree::Node::Block(nodes)) Ok(tree::Node::Block(obrace.pos, nodes))
} }
/// ```notrust /// ```notrust
@ -135,9 +135,9 @@ impl Parser {
/// ``` /// ```
fn parse_return_stmt(&mut self) -> Result<tree::Node, Error> { fn parse_return_stmt(&mut self) -> Result<tree::Node, Error> {
self.assert_scope(Scope::Function)?; 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])?; 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 /// ```notrust
@ -149,16 +149,14 @@ impl Parser {
self.assert_scope_not(Scope::Target)?; self.assert_scope_not(Scope::Target)?;
self.scope.push(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_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()?; let children = self.parse_block_stmt()?;
self.scope.pop(); self.scope.pop();
Ok(tree::Node::Target { Ok(tree::Node::make_target_stmt(target_keyword.pos, name, children))
name: Box::new(tree::Node::Ident(name_token.raw)),
content: Box::new(children),
})
} }
/// ```notrust /// ```notrust
@ -168,10 +166,10 @@ impl Parser {
fn parse_depend_stmt(&mut self) -> Result<tree::Node, Error> { fn parse_depend_stmt(&mut self) -> Result<tree::Node, Error> {
self.assert_scope(Scope::Target)?; self.assert_scope(Scope::Target)?;
self.scope.push(Scope::DepList); 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])?; let rvalue = self.parse_expr(&[token::Kind::Semi])?;
self.scope.pop(); self.scope.pop();
Ok(tree::Node::DepList(Box::new(rvalue))) Ok(tree::Node::DepList(depend_keyword.pos, Box::new(rvalue)))
} }
/// ```notrust /// ```notrust
@ -179,22 +177,16 @@ impl Parser {
/// : "if" "(" Expression ")" BlockStatement [ "else" BlockStatement ] /// : "if" "(" Expression ")" BlockStatement [ "else" BlockStatement ]
/// ``` /// ```
fn parse_if_stmt(&mut self) -> Result<tree::Node, Error> { fn parse_if_stmt(&mut self) -> Result<tree::Node, Error> {
self.lexer.expect_kind(token::Kind::IfKeyword)?; let if_keyword = self.lexer.expect_kind(token::Kind::IfKeyword)?;
self.lexer.expect_kind(token::Kind::OParen)?; self.lexer.expect_kind(token::Kind::OParen)?;
let condition = self.parse_expr(&[token::Kind::CParen])?; let condition = self.parse_expr(&[token::Kind::CParen])?;
let then_block = self.parse_block_stmt()?; let then_block = self.parse_block_stmt()?;
let mut else_block = None; let else_block = if self.lexer.next_if(token::Kind::ElseKeyword).is_some() {
if let Some(Ok(token)) = self.lexer.peek() { Some(self.parse_block_stmt()?)
if token.kind == token::Kind::ElseKeyword { } else {
self.lexer.next(); None
else_block = Some(Box::new(self.parse_block_stmt()?)); };
} Ok(tree::Node::make_if_stmt(if_keyword.pos, condition, then_block, else_block))
}
Ok(tree::Node::IfStmt {
condition: Box::new(condition),
then_block: Box::new(then_block),
else_block,
})
} }
/// ```notrust /// ```notrust
@ -202,16 +194,13 @@ impl Parser {
/// : "while" "(" Expression ")" BlockStatement /// : "while" "(" Expression ")" BlockStatement
/// ``` /// ```
fn parse_while_stmt(&mut self) -> Result<tree::Node, Error> { fn parse_while_stmt(&mut self) -> Result<tree::Node, Error> {
self.lexer.expect_kind(token::Kind::WhileKeyword)?; let while_keyword = self.lexer.expect_kind(token::Kind::WhileKeyword)?;
self.scope.push(Scope::Loop); self.scope.push(Scope::Loop);
self.lexer.expect_kind(token::Kind::OParen)?; self.lexer.expect_kind(token::Kind::OParen)?;
let condition = self.parse_expr(&[token::Kind::CParen])?; let condition = self.parse_expr(&[token::Kind::CParen])?;
let block = self.parse_block_stmt()?; let body = self.parse_block_stmt()?;
self.scope.pop(); self.scope.pop();
Ok(tree::Node::WhileStmt { Ok(tree::Node::make_while_stmt(while_keyword.pos, condition, body))
condition: Box::new(condition),
block: Box::new(block),
})
} }
/// ```notrust /// ```notrust
@ -219,26 +208,24 @@ impl Parser {
/// : "for" "(" [ Expression ] ";" [ Expression ] ";" [ Expression ] ")" BlockStatement /// : "for" "(" [ Expression ] ";" [ Expression ] ";" [ Expression ] ")" BlockStatement
/// ``` /// ```
fn parse_for_stmt(&mut self) -> Result<tree::Node, Error> { fn parse_for_stmt(&mut self) -> Result<tree::Node, Error> {
self.lexer.expect_kind(token::Kind::ForKeyword)?; let for_keyword = self.lexer.expect_kind(token::Kind::ForKeyword)?;
self.scope.push(Scope::Loop); self.scope.push(Scope::Loop);
self.lexer.expect_kind(token::Kind::OParen)?; self.lexer.expect_kind(token::Kind::OParen)?;
let terminators = [token::Kind::Semi, token::Kind::Semi, token::Kind::CParen]; let terminators = [token::Kind::Semi, token::Kind::Semi, token::Kind::CParen];
let mut exprs = Vec::new(); let mut exprs = Vec::new();
for i in 0..3 { 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 None
} else { } else {
Some(Box::new(self.parse_expr(&terminators[i..=i])?)) Some(self.parse_expr(&terminators[i..=i])?)
}); });
} }
let body = self.parse_block_stmt()?; let body = self.parse_block_stmt()?;
self.scope.pop(); self.scope.pop();
Ok(tree::Node::ForStmt { let exec = exprs.pop().unwrap();
exec: exprs.pop().unwrap(), let condition = exprs.pop().unwrap();
condition: exprs.pop().unwrap(), let setup = exprs.pop().unwrap();
setup: exprs.pop().unwrap(), Ok(tree::Node::make_for_stmt(for_keyword.pos, setup, condition, exec, body))
body: Box::new(body),
})
} }
/// ```notrust /// ```notrust
@ -247,15 +234,12 @@ impl Parser {
/// ``` /// ```
fn parse_set_stmt(&mut self) -> Result<tree::Node, Error> { fn parse_set_stmt(&mut self) -> Result<tree::Node, Error> {
self.assert_scope(Scope::File)?; 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])?; let expr = self.parse_expr(&[token::Kind::Semi])?;
match expr { match expr {
tree::Node::BinaryExpr { op, lhs, rhs } => { tree::Node::BinaryExpr(_, expr) => {
if op == Operator::Eq { if expr.op == Operator::Eq {
Ok(tree::Node::SetExpr { Ok(tree::Node::make_set_stmt(set_keyword.pos, *expr.lhs, *expr.rhs))
name: lhs,
val: rhs,
})
} else { } else {
self.syntax_error(format!("Invalid operator"), self.lexer.current().unwrap()) self.syntax_error(format!("Invalid operator"), self.lexer.current().unwrap())
} }
@ -272,10 +256,10 @@ impl Parser {
/// : "type" Expression ";" /// : "type" Expression ";"
/// ``` /// ```
fn parse_type_stmt(&mut self) -> Result<tree::Node, Error> { fn parse_type_stmt(&mut self) -> Result<tree::Node, Error> {
self.lexer.expect_kind(token::Kind::TypeKeyword)?; let type_keyword = self.lexer.expect_kind(token::Kind::TypeKeyword)?;
self.assert_scope(Scope::Target)?; self.assert_scope(Scope::Target)?;
let expr = self.parse_expr(&[token::Kind::Semi])?; 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 /// ```notrust
@ -283,12 +267,12 @@ impl Parser {
/// : "source" Expression ";" /// : "source" Expression ";"
/// ``` /// ```
fn parse_source_stmt(&mut self) -> Result<tree::Node, Error> { fn parse_source_stmt(&mut self) -> Result<tree::Node, Error> {
self.lexer.expect_kind(token::Kind::SourceKeyword)?; let source_keyword = self.lexer.expect_kind(token::Kind::SourceKeyword)?;
self.assert_scope(Scope::Target)?; self.assert_scope(Scope::Target)?;
self.scope.push(Scope::SourceList); self.scope.push(Scope::SourceList);
let source = self.parse_expr(&[token::Kind::Semi])?; let source = self.parse_expr(&[token::Kind::Semi])?;
self.scope.pop(); self.scope.pop();
Ok(tree::Node::SourceList(Box::new(source))) Ok(tree::Node::SourceList(source_keyword.pos, Box::new(source)))
} }
/// ```notrust /// ```notrust
@ -354,11 +338,7 @@ impl Parser {
let op_token = self.lexer.require_next()?; let op_token = self.lexer.require_next()?;
let op = Operator::from_token(&op_token)?; let op = Operator::from_token(&op_token)?;
let rhs = self.parse_binary_expr_or_higher(terminators)?; let rhs = self.parse_binary_expr_or_higher(terminators)?;
return Ok(tree::Node::BinaryExpr { return Ok(tree::Node::make_binary_expr(op_token.pos, lhs, op, rhs));
op,
lhs: Box::new(lhs),
rhs: Box::new(rhs),
});
} else if token.kind.binary_op_precedence().is_some() { } else if token.kind.binary_op_precedence().is_some() {
// shoot, this wasn't an assignment, all of our work was useless // shoot, this wasn't an assignment, all of our work was useless
self.lexer.restore(bookmark); self.lexer.restore(bookmark);
@ -387,7 +367,7 @@ impl Parser {
&mut self, &mut self,
terminators: &[token::Kind], terminators: &[token::Kind],
) -> Result<tree::Node, Error> { ) -> Result<tree::Node, Error> {
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() { while let Some(Ok(token)) = self.lexer.peek() {
if terminators.contains(&token.kind) { if terminators.contains(&token.kind) {
@ -398,14 +378,10 @@ impl Parser {
let op = Operator::from_token(&token)?; let op = Operator::from_token(&token)?;
self.lexer.next(); self.lexer.next();
let precedence = token.kind.binary_op_precedence().unwrap(); let precedence = token.kind.binary_op_precedence().unwrap();
expr = tree::Node::BinaryExpr { lhs = tree::Node::make_binary_expr(token.pos, lhs, op, self.parse_binary_rhs(precedence, terminators)?);
op,
lhs: Box::new(expr),
rhs: Box::new(self.parse_binary_rhs(precedence, terminators)?),
};
} }
Ok(expr) Ok(lhs)
} }
/// This is for parsing the right-hand side of a binary expression. /// This is for parsing the right-hand side of a binary expression.
@ -440,11 +416,7 @@ impl Parser {
if new_precedence > precedence { if new_precedence > precedence {
let op = Operator::from_token(&token)?; let op = Operator::from_token(&token)?;
self.lexer.next(); self.lexer.next();
lhs = tree::Node::BinaryExpr { lhs = tree::Node::make_binary_expr(token.pos, lhs, op, self.parse_binary_rhs(new_precedence, terminators)?);
op,
lhs: Box::new(lhs),
rhs: Box::new(self.parse_binary_rhs(new_precedence, terminators)?),
};
} else { } else {
break; break;
} }
@ -470,10 +442,7 @@ impl Parser {
self.lexer.next(); // consume unary operator token self.lexer.next(); // consume unary operator token
let op = Operator::from_token(&token)?; let op = Operator::from_token(&token)?;
let expr = self.parse_primary_expr()?; let expr = self.parse_primary_expr()?;
return Ok(tree::Node::UnaryExpr { return Ok(tree::Node::make_unary_expr(token.pos, op, expr));
op,
node: Box::new(expr),
});
} }
} }
self.parse_primary_expr() self.parse_primary_expr()
@ -484,6 +453,7 @@ impl Parser {
/// : "(" Expression ")" /// : "(" Expression ")"
/// | ArrayExpression /// | ArrayExpression
/// | CallExpression /// | CallExpression
/// | MemberExpression
/// | Identifier /// | Identifier
/// | StringLiteral /// | StringLiteral
/// | IntLiteral /// | IntLiteral
@ -499,6 +469,9 @@ impl Parser {
/// ParameterList /// ParameterList
/// : Expression [ "," ] /// : Expression [ "," ]
/// | Expression "," ParameterList /// | Expression "," ParameterList
///
/// MemberExpression
/// : PrimaryExpression "." PrimaryExpression
/// ``` /// ```
fn parse_primary_expr(&mut self) -> Result<tree::Node, Error> { fn parse_primary_expr(&mut self) -> Result<tree::Node, Error> {
let token = self.lexer.require_next()?; let token = self.lexer.require_next()?;
@ -508,7 +481,7 @@ impl Parser {
self.parse_primary_expr_rest(expr) self.parse_primary_expr_rest(expr)
} }
token::Kind::Ident => { 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) self.parse_primary_expr_rest(ident)
} }
token::Kind::IntLiteral => { token::Kind::IntLiteral => {
@ -520,11 +493,11 @@ impl Parser {
_ => raw.parse(), _ => raw.parse(),
} }
.unwrap(); .unwrap();
Ok(tree::Node::Int(num)) Ok(tree::Node::Int(token.pos, num))
} }
token::Kind::StringLiteral => Ok(tree::Node::String(token.raw)), token::Kind::StringLiteral => Ok(tree::Node::String(token.pos, token.raw)),
token::Kind::TrueKeyword => Ok(tree::Node::Bool(true)), token::Kind::TrueKeyword => Ok(tree::Node::Bool(token.pos, true)),
token::Kind::FalseKeyword => Ok(tree::Node::Bool(false)), token::Kind::FalseKeyword => Ok(tree::Node::Bool(token.pos, false)),
token::Kind::FnKeyword => { token::Kind::FnKeyword => {
self.lexer.prev(); // parse_fn() expects to consume the keyword self.lexer.prev(); // parse_fn() expects to consume the keyword
self.parse_fn(true) self.parse_fn(true)
@ -532,7 +505,7 @@ impl Parser {
token::Kind::OBracket => { token::Kind::OBracket => {
let elements = let elements =
self.parse_delimited_list(token::Kind::Comma, token::Kind::CBracket, true)?; 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), _ => self.syntax_error(format!("Unexpected token {}", token.kind), &token),
} }
@ -556,29 +529,19 @@ impl Parser {
self.lexer.next(); self.lexer.next();
let params = let params =
self.parse_delimited_list(token::Kind::Comma, token::Kind::CParen, false)?; self.parse_delimited_list(token::Kind::Comma, token::Kind::CParen, false)?;
self.parse_primary_expr_rest(tree::Node::CallExpr { self.parse_primary_expr_rest(tree::Node::make_call_expr(token.pos, start, params))
func: Box::new(start),
params,
})
} }
token::Kind::OBracket => { token::Kind::OBracket => {
// array index // array index
self.lexer.next(); self.lexer.next();
let index = self.parse_expr(&[token::Kind::CBracket])?; let index = self.parse_expr(&[token::Kind::CBracket])?;
self.parse_primary_expr_rest(tree::Node::ArrayExpr { self.parse_primary_expr_rest(tree::Node::make_array_expr(token.pos, start, index))
array: Box::new(start),
index: Box::new(index),
})
} }
token::Kind::Dot => { token::Kind::Dot => {
// member access // member access
self.lexer.next(); self.lexer.next();
let member = self.lexer.expect_kind(token::Kind::Ident)?; let member = self.lexer.expect_kind(token::Kind::Ident)?;
self.parse_primary_expr_rest(tree::Node::BinaryExpr { self.parse_primary_expr_rest(tree::Node::make_binary_expr(token.pos, start, Operator::Dot, tree::Node::Ident(member.pos, member.raw)))
op: Operator::Dot,
lhs: Box::new(start),
rhs: Box::new(tree::Node::Ident(member.raw)),
})
} }
_ => Ok(start), _ => Ok(start),
} }
@ -596,13 +559,13 @@ impl Parser {
/// ``` /// ```
fn parse_fn(&mut self, allow_anonymous: bool) -> Result<tree::Node, Error> { fn parse_fn(&mut self, allow_anonymous: bool) -> Result<tree::Node, Error> {
self.scope.push(Scope::Function); 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) // function name is optional (there are inline anonymous functions)
let name = if let Some(Ok(token)) = self.lexer.peek() { let name = if let Some(Ok(token)) = self.lexer.peek() {
if token.kind == token::Kind::Ident { if token.kind == token::Kind::Ident {
self.lexer.next(); self.lexer.next();
Some(Box::new(tree::Node::Ident(token.raw))) Some(tree::Node::Ident(token.pos, token.raw))
} else { } else {
None None
} }
@ -619,7 +582,7 @@ impl Parser {
let params = self.parse_delimited_list(token::Kind::Comma, token::Kind::CParen, false)?; let params = self.parse_delimited_list(token::Kind::Comma, token::Kind::CParen, false)?;
for p in &params { for p in &params {
match p { match p {
tree::Node::Ident(_) => continue, tree::Node::Ident(_, _) => continue,
_ => { _ => {
return self return self
.syntax_error(format!("Not an identifier"), &self.lexer.current().unwrap()) .syntax_error(format!("Not an identifier"), &self.lexer.current().unwrap())
@ -630,11 +593,7 @@ impl Parser {
let body = self.parse_block_stmt()?; let body = self.parse_block_stmt()?;
self.scope.pop(); self.scope.pop();
Ok(tree::Node::Fn { Ok(tree::Node::make_fn(fn_keyword.pos, name, params, body))
name,
params,
body: Box::new(body),
})
} }
/// Parse a terminated, delimited list of expressions. This is used for /// Parse a terminated, delimited list of expressions. This is used for

@ -1,75 +1,93 @@
use std::fmt; use std::fmt;
use std::fmt::Formatter;
use crate::error::Error; use crate::error::Error;
use crate::lex::token; use crate::lex::token;
use crate::lex::token::Token; use crate::lex::token::{Position, Token};
#[derive(Debug)]
pub enum Node { pub enum Node {
Break, Break(Position),
Ident(String), Ident(Position, String),
DepList(Box<Node>), DepList(Position, Box<Node>),
SourceList(Box<Node>), SourceList(Position, Box<Node>),
Bool(bool), Bool(Position, bool),
Int(i128), Int(Position, i128),
String(String), String(Position, String),
Array(Vec<Node>), Array(Position, Vec<Node>),
Block(Vec<Node>), Block(Position, Vec<Node>),
Fn { Fn(Position, FnStmt),
name: Option<Box<Node>>, ArrayExpr(Position, ArrayExpr),
params: Vec<Node>, CallExpr(Position, CallExpr),
body: Box<Node>, IfStmt(Position, IfStmt),
}, ReturnStmt(Position, Box<Node>),
ArrayExpr { ForStmt(Position, ForStmt),
// array access WhileStmt(Position, WhileStmt),
array: Box<Node>, UnaryExpr(Position, UnaryExpr),
index: Box<Node>, BinaryExpr(Position, BinaryExpr),
}, TypeStmt(Position, Box<Node>),
CallExpr { SetStmt(Position, SetStmt),
// function call TargetStmt(Position, TargetStmt),
func: Box<Node>, File(Position, File),
params: Vec<Node>, }
},
IfStmt { pub struct File {
condition: Box<Node>, pub name: String,
then_block: Box<Node>, pub content: Vec<Node>,
else_block: Option<Box<Node>>, }
},
ReturnStmt(Box<Node>), pub struct FnStmt {
ForStmt { pub name: Option<Box<Node>>,
setup: Option<Box<Node>>, pub params: Vec<Node>,
condition: Option<Box<Node>>, pub body: Box<Node>,
exec: Option<Box<Node>>, }
body: Box<Node>,
}, pub struct IfStmt {
WhileStmt { pub condition: Box<Node>,
condition: Box<Node>, pub then_body: Box<Node>,
block: Box<Node>, pub else_body: Option<Box<Node>>,
}, }
UnaryExpr {
op: Operator, pub struct ForStmt {
node: Box<Node>, pub setup: Option<Box<Node>>,
}, pub condition: Option<Box<Node>>,
BinaryExpr { pub exec: Option<Box<Node>>,
op: Operator, pub body: Box<Node>,
lhs: Box<Node>, }
rhs: Box<Node>,
}, pub struct WhileStmt {
TypeExpr(Box<Node>), pub condition: Box<Node>,
SetExpr { pub body: Box<Node>,
name: Box<Node>, }
val: Box<Node>,
}, pub struct SetStmt {
Target { pub name: Box<Node>,
name: Box<Node>, pub val: Box<Node>,
content: Box<Node>, }
},
File { pub struct TargetStmt {
name: String, pub name: Box<Node>,
content: Vec<Node>, pub val: Box<Node>,
}, }
pub struct BinaryExpr {
pub lhs: Box<Node>,
pub op: Operator,
pub rhs: Box<Node>,
}
pub struct UnaryExpr {
pub op: Operator,
pub rhs: Box<Node>,
}
pub struct CallExpr {
pub func: Box<Node>,
pub params: Vec<Node>,
}
pub struct ArrayExpr {
pub array: Box<Node>,
pub index: Box<Node>,
} }
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
@ -108,136 +126,237 @@ pub enum Operator {
} }
impl Node { 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)) { pub fn walk(&self, cb: fn(node: &Node, depth: u32)) {
self.visit(cb, 0); 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) { fn visit(&self, cb: fn(node: &Node, depth: u32), current_depth: u32) {
cb(self, current_depth); cb(self, current_depth);
let depth = current_depth + 1; let depth = current_depth + 1;
match self { match self {
Node::DepList(list) => list.visit(cb, depth), Node::DepList(_, list) => list.visit(cb, depth),
Node::SourceList(list) => list.visit(cb, depth), Node::SourceList(_, list) => list.visit(cb, depth),
Node::Array(elements) => { Node::Array(_, elements) => {
for node in elements { for node in elements {
node.visit(cb, depth); node.visit(cb, depth);
} }
} }
Node::Block(statements) => { Node::Block(_, statements) => {
for node in statements { for node in statements {
node.visit(cb, depth); node.visit(cb, depth);
} }
} }
Node::Fn { name, params, body } => { Node::Fn(_, func) => {
if let Some(n) = name { if let Some(n) = &func.name {
n.visit(cb, depth); n.visit(cb, depth);
} }
for p in params { for p in &func.params {
p.visit(cb, depth); p.visit(cb, depth);
} }
body.visit(cb, depth); func.body.visit(cb, depth);
} }
Node::ArrayExpr { array, index } => { Node::ArrayExpr(_, expr) => {
array.visit(cb, depth); expr.array.visit(cb, depth);
index.visit(cb, depth); expr.index.visit(cb, depth);
} }
Node::CallExpr { func, params } => { Node::CallExpr(_, expr) => {
func.visit(cb, depth); expr.func.visit(cb, depth);
for p in params { for p in &expr.params {
p.visit(cb, depth); p.visit(cb, depth);
} }
} }
Node::IfStmt { Node::IfStmt(_, stmt) => {
condition, stmt.condition.visit(cb, depth);
then_block, stmt.then_body.visit(cb, depth);
else_block, if let Some(eb) = &stmt.else_body {
} => {
condition.visit(cb, depth);
then_block.visit(cb, depth);
if let Some(eb) = else_block {
eb.visit(cb, depth); eb.visit(cb, depth);
} }
} }
Node::ForStmt { setup, condition, exec, body } => { Node::ForStmt(_, stmt) => {
if let Some(s) = setup { if let Some(s) = &stmt.setup {
s.visit(cb, depth); s.visit(cb, depth);
} }
if let Some(c) = condition { if let Some(c) = &stmt.condition {
c.visit(cb, depth); c.visit(cb, depth);
} }
if let Some(e) = exec { if let Some(e) = &stmt.exec {
e.visit(cb, depth); e.visit(cb, depth);
} }
body.visit(cb, depth); stmt.body.visit(cb, depth);
} }
Node::WhileStmt { condition, block } => { Node::WhileStmt(_, stmt) => {
condition.visit(cb, depth); stmt.condition.visit(cb, depth);
block.visit(cb, depth); stmt.body.visit(cb, depth);
} }
Node::ReturnStmt(node) => node.visit(cb, depth), Node::ReturnStmt(_, node) => node.visit(cb, depth),
Node::UnaryExpr { op, node } => node.visit(cb, depth), Node::UnaryExpr(_, expr) => expr.rhs.visit(cb, depth),
Node::BinaryExpr { op, lhs, rhs } => { Node::BinaryExpr(_, expr) => {
lhs.visit(cb, depth); expr.lhs.visit(cb, depth);
rhs.visit(cb, depth); expr.rhs.visit(cb, depth);
} }
Node::TypeExpr(node) => node.visit(cb, depth), Node::TypeStmt(_, expr) => expr.visit(cb, depth),
Node::SetExpr { name, val } => { Node::SetStmt(_, expr) => {
name.visit(cb, depth); expr.name.visit(cb, depth);
val.visit(cb, depth); expr.val.visit(cb, depth);
} }
Node::Target { name, content } => { Node::TargetStmt(_, stmt) => {
name.visit(cb, depth); stmt.name.visit(cb, depth);
content.visit(cb, depth); stmt.val.visit(cb, depth);
} }
Node::File { name, content } => { Node::File(_, file) => {
for n in content { for n in &file.content {
n.visit(cb, depth); n.visit(cb, depth);
} }
} }
_ => return, _ => return,
} }
} }
pub fn make_fn(pos: Position, name: Option<Node>, params: Vec<Node>, 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 {
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>) -> 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<Node>, condition: Option<Node>, exec: Option<Node>, 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 { 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; let tmp: String;
write!( write!(
f, f,
"{}", "{}",
match self { match self {
Node::Break => "<break>", Node::Break(_) => "<break>",
Node::Ident(name) => name.as_str(), Node::Ident(_, name) => name.as_str(),
Node::Bool(b) => { Node::Bool(_, b) => {
tmp = format!("{}", b); tmp = format!("{}", b);
tmp.as_str() tmp.as_str()
} }
Node::Int(i) => { Node::Int(_, i) => {
tmp = format!("{}", i); tmp = format!("{}", i);
tmp.as_str() tmp.as_str()
} }
Node::String(s) => s.as_str(), Node::String(_, s) => s.as_str(),
Node::Block(_) => "<block>", Node::Block(_, _) => "<block>",
Node::Fn { name, params, body } => "fn", Node::Fn(_, _) => "fn",
Node::ReturnStmt(_) => "return", Node::ReturnStmt(_, _) => "return",
Node::DepList(_) => "depend", Node::DepList(_, _) => "depend",
Node::SourceList(_) => "source", Node::SourceList(_, _) => "source",
Node::Array(_) => "<array>", Node::Array(_, _) => "<array>",
Node::ArrayExpr { array, index } => "<array-access>", Node::ArrayExpr(_, _) => "<array-access>",
Node::CallExpr { func, params } => "<call>", Node::CallExpr(_, _) => "<call>",
Node::IfStmt { Node::IfStmt(_, _) => "<if>",
condition, Node::ForStmt(_, _) => "<for>",
then_block, Node::WhileStmt(_, _) => "<while>",
else_block, Node::UnaryExpr(_, expr) => expr.op.raw(),
} => "<if>", Node::BinaryExpr(_, expr) => expr.op.raw(),
Node::ForStmt { setup, condition, exec, body } => "<for>", Node::TypeStmt(_, _) => "type",
Node::WhileStmt { condition, block } => "<while>", Node::SetStmt(_, _) => "set",
Node::UnaryExpr { op, node } => op.raw(), Node::TargetStmt(_, _) => "target",
Node::BinaryExpr { op, lhs, rhs } => op.raw(), Node::File(pos, _) => pos.file.as_str(),
Node::TypeExpr(_) => "type",
Node::SetExpr { name, val } => "set",
Node::Target { name, content } => "target",
Node::File { name, content } => "file",
} }
) )
} }
@ -321,7 +440,7 @@ impl Operator {
} }
impl fmt::Display for 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()) write!(f, "{}", self.raw())
} }
} }
@ -331,9 +450,12 @@ pub enum Type {
/// For identifier tokens (evaluates at runtime) /// For identifier tokens (evaluates at runtime)
Unknown, Unknown,
/// For expressions that don't emit a value /// For expressions that don't emit a value
None, Void,
Bool,
Int, Int,
String, String,
Array,
Fn,
} }
impl Type { impl Type {
@ -353,9 +475,12 @@ impl fmt::Display for Type {
"{}", "{}",
match self { match self {
Type::Unknown => "<unknown>", Type::Unknown => "<unknown>",
Type::None => "()", Type::Void => "()",
Type::Bool => "bool",
Type::Int => "int", Type::Int => "int",
Type::String => "string", Type::String => "string",
Type::Array => "array",
Type::Fn => "fn",
} }
) )
} }

@ -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<Token> {
if let Some(Ok(token)) = self.peek() { if let Some(Ok(token)) = self.peek() {
if token.kind == kind { if token.kind == kind {
self.next(); self.next();
return true; Some(token)
} else {
None
} }
} else {
None
} }
false
} }
pub fn require_next(&mut self) -> Result<Token, Error> { pub fn require_next(&mut self) -> Result<Token, Error> {
@ -292,13 +294,17 @@ impl Lexer {
Some('x') => self.read_int_literal(16), Some('x') => self.read_int_literal(16),
Some('o') => self.read_int_literal(8), Some('o') => self.read_int_literal(8),
Some('b') => self.read_int_literal(2), 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 @ '0'..='9') => {
Some(c) if c.is_ident_part() => self.syntax_error(format!("Unexpected character '{}'", c)), 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 // it wasn't a prefixed int literal at all, just a single 0
self.cursor.prev(); self.cursor.prev();
self.token_ok(token::Kind::IntLiteral) self.token_ok(token::Kind::IntLiteral)
}, }
} }
} }

Loading…
Cancel
Save