aboutsummaryrefslogtreecommitdiff
path: root/sloth/src/parser
diff options
context:
space:
mode:
Diffstat (limited to 'sloth/src/parser')
-rw-r--r--sloth/src/parser/ast.rs29
-rw-r--r--sloth/src/parser/expr.rs17
-rw-r--r--sloth/src/parser/mod.rs11
-rw-r--r--sloth/src/parser/stmt.rs56
4 files changed, 95 insertions, 18 deletions
diff --git a/sloth/src/parser/ast.rs b/sloth/src/parser/ast.rs
index 8442cc2..a542847 100644
--- a/sloth/src/parser/ast.rs
+++ b/sloth/src/parser/ast.rs
@@ -21,11 +21,19 @@ impl<'a> AstNode<'a> {
}
children.into_iter()
}
+
+ pub fn line(&self) -> u32 {
+ match self {
+ Self::Expr(expr) => expr.line,
+ Self::Stmt(stmt) => stmt.line,
+ }
+ }
}
#[derive(Clone, Debug)]
pub struct Expr {
pub id: i32,
+ pub line: u32,
pub kind: ExprKind,
pub symtable: SymbolTable,
}
@@ -37,14 +45,20 @@ impl PartialEq for Expr {
}
impl Expr {
- pub fn new(id: i32, kind: ExprKind, symtable: SymbolTable) -> Self {
- Self { id, kind, symtable }
+ pub fn new(id: i32, line: u32, kind: ExprKind, symtable: SymbolTable) -> Self {
+ Self {
+ id,
+ line,
+ kind,
+ symtable,
+ }
}
/// Useful for testing
pub fn without_table(id: i32, kind: ExprKind) -> Self {
Self {
id,
+ line: 0,
kind,
symtable: SymbolTable::new(),
}
@@ -98,6 +112,7 @@ pub enum ExprKind {
#[derive(Clone, Debug)]
pub struct Stmt {
pub id: i32,
+ pub line: u32,
pub kind: StmtKind,
pub symtable: SymbolTable,
}
@@ -109,14 +124,20 @@ impl PartialEq for Stmt {
}
impl Stmt {
- pub fn new(id: i32, kind: StmtKind, symtable: SymbolTable) -> Self {
- Self { id, kind, symtable }
+ pub fn new(id: i32, line: u32, kind: StmtKind, symtable: SymbolTable) -> Self {
+ Self {
+ id,
+ line,
+ kind,
+ symtable,
+ }
}
/// Useful for testing
pub fn without_table(id: i32, kind: StmtKind) -> Self {
Self {
id,
+ line: 0,
kind,
symtable: SymbolTable::new(),
}
diff --git a/sloth/src/parser/expr.rs b/sloth/src/parser/expr.rs
index 5fd9b49..7ec283f 100644
--- a/sloth/src/parser/expr.rs
+++ b/sloth/src/parser/expr.rs
@@ -21,7 +21,12 @@ impl<'a> AstParser<'a> {
value: Box::new(value),
};
- return Ok(Expr::new(self.reserve_id(), kind, self.top.clone()));
+ return Ok(Expr::new(
+ self.reserve_id(),
+ self.line,
+ kind,
+ self.top.clone(),
+ ));
}
self.call()
@@ -45,6 +50,7 @@ impl<'a> AstParser<'a> {
expr = Expr::new(
self.reserve_id(),
+ self.line,
ExprKind::Call {
callee: Box::new(expr),
args: arguments,
@@ -70,7 +76,12 @@ impl<'a> AstParser<'a> {
_ => return Err(ParsingError::UnexpectedToken),
};
- Ok(Expr::new(self.reserve_id(), kind, self.top.clone()))
+ Ok(Expr::new(
+ self.reserve_id(),
+ self.line,
+ kind,
+ self.top.clone(),
+ ))
}
}
@@ -92,7 +103,7 @@ macro_rules! binary_expr {
rhs: Box::new(rhs),
};
- expr = Expr::new(self.reserve_id(), kind, self.top.clone());
+ expr = Expr::new(self.reserve_id(), self.line, kind, self.top.clone());
}
Ok(expr)
diff --git a/sloth/src/parser/mod.rs b/sloth/src/parser/mod.rs
index 3328137..748a0da 100644
--- a/sloth/src/parser/mod.rs
+++ b/sloth/src/parser/mod.rs
@@ -17,10 +17,11 @@ pub enum ParsingError {
#[derive(Debug)]
pub struct AstParser<'a> {
+ top: SymbolTable,
tokens: Vec<Token<'a>>,
index: usize,
id: i32,
- top: SymbolTable,
+ line: u32,
}
impl<'a> AstParser<'a> {
@@ -34,6 +35,7 @@ impl<'a> AstParser<'a> {
let root = Stmt::new(
parser.reserve_id(),
+ parser.line,
StmtKind::Block(statements),
parser.top.clone(),
);
@@ -46,10 +48,11 @@ impl<'a> AstParser<'a> {
impl<'a> AstParser<'a> {
pub fn new(tokens: Vec<Token<'a>>, root: SymbolTable) -> Self {
Self {
+ top: root,
tokens,
index: 0,
id: 0,
- top: root,
+ line: 0,
}
}
@@ -66,8 +69,10 @@ impl<'a> AstParser<'a> {
return None;
}
+ let current = &self.tokens[self.index];
self.index += 1;
- Some(&self.tokens[self.index - 1])
+ self.line = current.start.row;
+ Some(current)
}
pub fn advance_if(&mut self, next: impl FnOnce(&Token) -> bool) -> bool {
diff --git a/sloth/src/parser/stmt.rs b/sloth/src/parser/stmt.rs
index c7433c2..7897e21 100644
--- a/sloth/src/parser/stmt.rs
+++ b/sloth/src/parser/stmt.rs
@@ -42,7 +42,12 @@ impl<'a> AstParser<'a> {
else_then: else_then.map(|it| it.into()),
};
- Ok(Stmt::new(self.reserve_id(), kind, self.top.clone()))
+ Ok(Stmt::new(
+ self.reserve_id(),
+ self.line,
+ kind,
+ self.top.clone(),
+ ))
}
fn while_stmt(&mut self) -> Result<Stmt, ParsingError> {
@@ -57,7 +62,12 @@ impl<'a> AstParser<'a> {
body: body.into(),
};
- Ok(Stmt::new(self.reserve_id(), kind, self.top.clone()))
+ Ok(Stmt::new(
+ self.reserve_id(),
+ self.line,
+ kind,
+ self.top.clone(),
+ ))
}
// TODO: Make variable types optional
@@ -82,7 +92,12 @@ impl<'a> AstParser<'a> {
typ,
};
- Ok(Stmt::new(self.reserve_id(), kind, self.top.clone()))
+ Ok(Stmt::new(
+ self.reserve_id(),
+ self.line,
+ kind,
+ self.top.clone(),
+ ))
}
// TODO: Make argument types optional
@@ -126,7 +141,12 @@ impl<'a> AstParser<'a> {
body: body.into(),
};
- Ok(Stmt::new(self.reserve_id(), kind, self.top.clone()))
+ Ok(Stmt::new(
+ self.reserve_id(),
+ self.line,
+ kind,
+ self.top.clone(),
+ ))
}
fn return_stmt(&mut self) -> Result<Stmt, ParsingError> {
@@ -134,7 +154,12 @@ impl<'a> AstParser<'a> {
let value = self.expression()?;
self.consume(TokenType::SemiColon, "Expected ';' at end of statement")?;
let kind = StmtKind::Return(value);
- Ok(Stmt::new(self.reserve_id(), kind, self.top.clone()))
+ Ok(Stmt::new(
+ self.reserve_id(),
+ self.line,
+ kind,
+ self.top.clone(),
+ ))
}
fn assign_variable(&mut self) -> Result<Stmt, ParsingError> {
@@ -143,14 +168,24 @@ impl<'a> AstParser<'a> {
let value = self.expression()?;
self.consume(TokenType::SemiColon, "Expected ';' at end of statement")?;
let kind = StmtKind::AssignVariable { identifier, value };
- Ok(Stmt::new(self.reserve_id(), kind, self.top.clone()))
+ Ok(Stmt::new(
+ self.reserve_id(),
+ self.line,
+ kind,
+ self.top.clone(),
+ ))
}
fn expression_stmt(&mut self) -> Result<Stmt, ParsingError> {
let expr = self.expression()?;
self.consume(TokenType::SemiColon, "Expected ';' at end of statement")?;
let kind = StmtKind::ExprStmt(expr);
- Ok(Stmt::new(self.reserve_id(), kind, self.top.clone()))
+ Ok(Stmt::new(
+ self.reserve_id(),
+ self.line,
+ kind,
+ self.top.clone(),
+ ))
}
fn block(&mut self) -> Result<Stmt, ParsingError> {
@@ -171,7 +206,12 @@ impl<'a> AstParser<'a> {
let kind = StmtKind::Block(body);
- Ok(Stmt::new(this.reserve_id(), kind, this.top.clone()))
+ Ok(Stmt::new(
+ this.reserve_id(),
+ this.line,
+ kind,
+ this.top.clone(),
+ ))
}
// Push a table, call the inner function and then pop that table