[fine] Different source locations

This commit is contained in:
John Doty 2024-01-01 09:05:13 -08:00
parent 2d233244cf
commit 81a7b09555
2 changed files with 18 additions and 58 deletions

View file

@ -47,10 +47,10 @@ pub enum BinaryOp {
Or, Or,
} }
pub enum Expr { pub enum Expr<'a> {
Literal(Literal), Literal(Literal, Token<'a>),
Unary(UnaryOp, ExprRef), Unary(UnaryOp, Token<'a>, ExprRef),
Binary(BinaryOp, ExprRef, ExprRef), Binary(BinaryOp, Token<'a>, ExprRef, ExprRef),
} }
pub struct ExprRef(Option<usize>); pub struct ExprRef(Option<usize>);
@ -63,8 +63,7 @@ impl ExprRef {
pub struct SyntaxTree<'a> { pub struct SyntaxTree<'a> {
pub errors: Vec<SyntaxError>, pub errors: Vec<SyntaxError>,
expressions: Vec<Expr>, expressions: Vec<Expr<'a>>,
spans: Vec<(Option<Token<'a>>, Option<Token<'a>>)>,
} }
impl<'a> SyntaxTree<'a> { impl<'a> SyntaxTree<'a> {
@ -72,7 +71,6 @@ impl<'a> SyntaxTree<'a> {
SyntaxTree { SyntaxTree {
errors: Vec::new(), errors: Vec::new(),
expressions: Vec::new(), expressions: Vec::new(),
spans: Vec::new(),
} }
} }
@ -80,51 +78,23 @@ impl<'a> SyntaxTree<'a> {
self.errors.push(error); self.errors.push(error);
} }
pub fn add_expr( pub fn add_expr(&mut self, expr: Expr<'a>) -> ExprRef {
&mut self,
expr: Expr,
start: Option<Token<'a>>,
end: Option<Token<'a>>,
) -> ExprRef {
let index = self.expressions.len(); let index = self.expressions.len();
self.expressions.push(expr); self.expressions.push(expr);
self.spans.push((start, end));
ExprRef(Some(index)) ExprRef(Some(index))
} }
pub fn span(&self, expr: &ExprRef) -> (Option<Token<'a>>, Option<Token<'a>>) {
if let ExprRef(Some(idx)) = expr {
let (start, end) = &self.spans[*idx];
(start.clone(), end.clone())
} else {
(None, None)
}
}
pub fn dump_expr(&self, expr: &ExprRef) -> String { pub fn dump_expr(&self, expr: &ExprRef) -> String {
match expr.0 { match expr.0 {
Some(idx) => { Some(idx) => {
let expr = &self.expressions[idx]; let expr = &self.expressions[idx];
match expr { match expr {
Expr::Literal(lit) => match lit { Expr::Literal(_, tok) => tok.to_string(),
Literal::Float64(f) => f.to_string(), Expr::Unary(_, tok, e) => {
}, format!("({tok} {})", self.dump_expr(e))
Expr::Unary(op, e) => {
let op = match op {
UnaryOp::Negate => "-",
};
format!("({op} {})", self.dump_expr(e))
} }
Expr::Binary(op, l, r) => { Expr::Binary(_, tok, l, r) => {
let op = match op { format!("({tok} {} {})", self.dump_expr(l), self.dump_expr(r))
BinaryOp::Add => "+",
BinaryOp::Subtract => "-",
BinaryOp::Mutiply => "*",
BinaryOp::Divide => "/",
BinaryOp::And => "and",
BinaryOp::Or => "or",
};
format!("({op} {} {})", self.dump_expr(l), self.dump_expr(r))
} }
} }
} }
@ -263,11 +233,7 @@ impl<'a> Parser<'a> {
} }
}; };
self.tree.add_expr( self.tree.add_expr(Expr::Literal(literal, token.clone()))
Expr::Literal(literal),
Some(token.clone()),
Some(token.clone()),
)
} }
fn grouping(&mut self) -> ExprRef { fn grouping(&mut self) -> ExprRef {
@ -288,8 +254,7 @@ impl<'a> Parser<'a> {
_ => panic!("unsuitable unary: {:?}: no op", kind), _ => panic!("unsuitable unary: {:?}: no op", kind),
}; };
self.tree self.tree.add_expr(Expr::Unary(op, token, expr))
.add_expr(Expr::Unary(op, expr), Some(token), self.previous.clone())
} }
fn binary(&mut self, power: u8, left: ExprRef) -> ExprRef { fn binary(&mut self, power: u8, left: ExprRef) -> ExprRef {
@ -304,12 +269,7 @@ impl<'a> Parser<'a> {
_ => panic!("unsuitable binary: {:?}: no op", self.previous), _ => panic!("unsuitable binary: {:?}: no op", self.previous),
}; };
let right = self.expression_with_power(power + 1); let right = self.expression_with_power(power + 1);
self.tree.add_expr(Expr::Binary(op, token, left, right))
let (left_start, _) = self.tree.span(&left);
let (_, right_end) = self.tree.span(&right);
self.tree
.add_expr(Expr::Binary(op, left, right), left_start, right_end)
} }
fn advance(&mut self) { fn advance(&mut self) {
@ -318,7 +278,7 @@ impl<'a> Parser<'a> {
self.current = self.tokens.next(); self.current = self.tokens.next();
match &self.current { match &self.current {
Some(token) if token.kind() == TokenKind::Error => { Some(token) if token.kind() == TokenKind::Error => {
self.error_at_current(token.clone()) self.error_at_current(token.to_string())
} }
_ => break, _ => break,
} }

View file

@ -89,9 +89,9 @@ impl<'a> Token<'a> {
} }
} }
impl<'a> Into<String> for Token<'a> { impl<'a> std::fmt::Display for Token<'a> {
fn into(self) -> String { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.as_str().to_string() write!(f, "{}", self.as_str())
} }
} }