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::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<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.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<tree::Node, Error> {
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<tree::Node, Error> {
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<tree::Node, Error> {
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<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)?;
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<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.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<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.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<tree::Node, Error> {
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<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)?;
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<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.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<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() {
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<tree::Node, Error> {
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<tree::Node, Error> {
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 &params {
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

@ -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<Node>),
SourceList(Box<Node>),
Bool(bool),
Int(i128),
String(String),
Array(Vec<Node>),
Block(Vec<Node>),
Fn {
name: Option<Box<Node>>,
params: Vec<Node>,
body: Box<Node>,
},
ArrayExpr {
// array access
array: Box<Node>,
index: Box<Node>,
},
CallExpr {
// function call
func: Box<Node>,
params: Vec<Node>,
},
IfStmt {
condition: Box<Node>,
then_block: Box<Node>,
else_block: Option<Box<Node>>,
},
ReturnStmt(Box<Node>),
ForStmt {
setup: Option<Box<Node>>,
condition: Option<Box<Node>>,
exec: Option<Box<Node>>,
body: Box<Node>,
},
WhileStmt {
condition: Box<Node>,
block: Box<Node>,
},
UnaryExpr {
op: Operator,
node: Box<Node>,
},
BinaryExpr {
op: Operator,
lhs: Box<Node>,
rhs: Box<Node>,
},
TypeExpr(Box<Node>),
SetExpr {
name: Box<Node>,
val: Box<Node>,
},
Target {
name: Box<Node>,
content: Box<Node>,
},
File {
name: String,
content: Vec<Node>,
},
Break(Position),
Ident(Position, String),
DepList(Position, Box<Node>),
SourceList(Position, Box<Node>),
Bool(Position, bool),
Int(Position, i128),
String(Position, String),
Array(Position, Vec<Node>),
Block(Position, Vec<Node>),
Fn(Position, FnStmt),
ArrayExpr(Position, ArrayExpr),
CallExpr(Position, CallExpr),
IfStmt(Position, IfStmt),
ReturnStmt(Position, Box<Node>),
ForStmt(Position, ForStmt),
WhileStmt(Position, WhileStmt),
UnaryExpr(Position, UnaryExpr),
BinaryExpr(Position, BinaryExpr),
TypeStmt(Position, Box<Node>),
SetStmt(Position, SetStmt),
TargetStmt(Position, TargetStmt),
File(Position, File),
}
pub struct File {
pub name: String,
pub content: Vec<Node>,
}
pub struct FnStmt {
pub name: Option<Box<Node>>,
pub params: Vec<Node>,
pub body: Box<Node>,
}
pub struct IfStmt {
pub condition: Box<Node>,
pub then_body: Box<Node>,
pub else_body: Option<Box<Node>>,
}
pub struct ForStmt {
pub setup: Option<Box<Node>>,
pub condition: Option<Box<Node>>,
pub exec: Option<Box<Node>>,
pub body: Box<Node>,
}
pub struct WhileStmt {
pub condition: Box<Node>,
pub body: Box<Node>,
}
pub struct SetStmt {
pub name: Box<Node>,
pub val: Box<Node>,
}
pub struct TargetStmt {
pub name: Box<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)]
@ -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<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 {
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 => "<break>",
Node::Ident(name) => name.as_str(),
Node::Bool(b) => {
Node::Break(_) => "<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(_) => "<block>",
Node::Fn { name, params, body } => "fn",
Node::ReturnStmt(_) => "return",
Node::DepList(_) => "depend",
Node::SourceList(_) => "source",
Node::Array(_) => "<array>",
Node::ArrayExpr { array, index } => "<array-access>",
Node::CallExpr { func, params } => "<call>",
Node::IfStmt {
condition,
then_block,
else_block,
} => "<if>",
Node::ForStmt { setup, condition, exec, body } => "<for>",
Node::WhileStmt { condition, block } => "<while>",
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(_, _) => "<block>",
Node::Fn(_, _) => "fn",
Node::ReturnStmt(_, _) => "return",
Node::DepList(_, _) => "depend",
Node::SourceList(_, _) => "source",
Node::Array(_, _) => "<array>",
Node::ArrayExpr(_, _) => "<array-access>",
Node::CallExpr(_, _) => "<call>",
Node::IfStmt(_, _) => "<if>",
Node::ForStmt(_, _) => "<for>",
Node::WhileStmt(_, _) => "<while>",
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 => "<unknown>",
Type::None => "()",
Type::Void => "()",
Type::Bool => "bool",
Type::Int => "int",
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 token.kind == kind {
self.next();
return true;
Some(token)
} else {
None
}
} else {
None
}
false
}
pub fn require_next(&mut self) -> Result<Token, Error> {
@ -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)
},
}
}
}

Loading…
Cancel
Save