[fine] Different source locations
This commit is contained in:
parent
2d233244cf
commit
81a7b09555
2 changed files with 18 additions and 58 deletions
|
|
@ -47,10 +47,10 @@ pub enum BinaryOp {
|
|||
Or,
|
||||
}
|
||||
|
||||
pub enum Expr {
|
||||
Literal(Literal),
|
||||
Unary(UnaryOp, ExprRef),
|
||||
Binary(BinaryOp, ExprRef, ExprRef),
|
||||
pub enum Expr<'a> {
|
||||
Literal(Literal, Token<'a>),
|
||||
Unary(UnaryOp, Token<'a>, ExprRef),
|
||||
Binary(BinaryOp, Token<'a>, ExprRef, ExprRef),
|
||||
}
|
||||
|
||||
pub struct ExprRef(Option<usize>);
|
||||
|
|
@ -63,8 +63,7 @@ impl ExprRef {
|
|||
|
||||
pub struct SyntaxTree<'a> {
|
||||
pub errors: Vec<SyntaxError>,
|
||||
expressions: Vec<Expr>,
|
||||
spans: Vec<(Option<Token<'a>>, Option<Token<'a>>)>,
|
||||
expressions: Vec<Expr<'a>>,
|
||||
}
|
||||
|
||||
impl<'a> SyntaxTree<'a> {
|
||||
|
|
@ -72,7 +71,6 @@ impl<'a> SyntaxTree<'a> {
|
|||
SyntaxTree {
|
||||
errors: Vec::new(),
|
||||
expressions: Vec::new(),
|
||||
spans: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -80,51 +78,23 @@ impl<'a> SyntaxTree<'a> {
|
|||
self.errors.push(error);
|
||||
}
|
||||
|
||||
pub fn add_expr(
|
||||
&mut self,
|
||||
expr: Expr,
|
||||
start: Option<Token<'a>>,
|
||||
end: Option<Token<'a>>,
|
||||
) -> ExprRef {
|
||||
pub fn add_expr(&mut self, expr: Expr<'a>) -> ExprRef {
|
||||
let index = self.expressions.len();
|
||||
self.expressions.push(expr);
|
||||
self.spans.push((start, end));
|
||||
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 {
|
||||
match expr.0 {
|
||||
Some(idx) => {
|
||||
let expr = &self.expressions[idx];
|
||||
match expr {
|
||||
Expr::Literal(lit) => match lit {
|
||||
Literal::Float64(f) => f.to_string(),
|
||||
},
|
||||
Expr::Unary(op, e) => {
|
||||
let op = match op {
|
||||
UnaryOp::Negate => "-",
|
||||
};
|
||||
format!("({op} {})", self.dump_expr(e))
|
||||
Expr::Literal(_, tok) => tok.to_string(),
|
||||
Expr::Unary(_, tok, e) => {
|
||||
format!("({tok} {})", self.dump_expr(e))
|
||||
}
|
||||
Expr::Binary(op, l, r) => {
|
||||
let op = match op {
|
||||
BinaryOp::Add => "+",
|
||||
BinaryOp::Subtract => "-",
|
||||
BinaryOp::Mutiply => "*",
|
||||
BinaryOp::Divide => "/",
|
||||
BinaryOp::And => "and",
|
||||
BinaryOp::Or => "or",
|
||||
};
|
||||
format!("({op} {} {})", self.dump_expr(l), self.dump_expr(r))
|
||||
Expr::Binary(_, tok, l, r) => {
|
||||
format!("({tok} {} {})", self.dump_expr(l), self.dump_expr(r))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -263,11 +233,7 @@ impl<'a> Parser<'a> {
|
|||
}
|
||||
};
|
||||
|
||||
self.tree.add_expr(
|
||||
Expr::Literal(literal),
|
||||
Some(token.clone()),
|
||||
Some(token.clone()),
|
||||
)
|
||||
self.tree.add_expr(Expr::Literal(literal, token.clone()))
|
||||
}
|
||||
|
||||
fn grouping(&mut self) -> ExprRef {
|
||||
|
|
@ -288,8 +254,7 @@ impl<'a> Parser<'a> {
|
|||
_ => panic!("unsuitable unary: {:?}: no op", kind),
|
||||
};
|
||||
|
||||
self.tree
|
||||
.add_expr(Expr::Unary(op, expr), Some(token), self.previous.clone())
|
||||
self.tree.add_expr(Expr::Unary(op, token, expr))
|
||||
}
|
||||
|
||||
fn binary(&mut self, power: u8, left: ExprRef) -> ExprRef {
|
||||
|
|
@ -304,12 +269,7 @@ impl<'a> Parser<'a> {
|
|||
_ => panic!("unsuitable binary: {:?}: no op", self.previous),
|
||||
};
|
||||
let right = self.expression_with_power(power + 1);
|
||||
|
||||
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)
|
||||
self.tree.add_expr(Expr::Binary(op, token, left, right))
|
||||
}
|
||||
|
||||
fn advance(&mut self) {
|
||||
|
|
@ -318,7 +278,7 @@ impl<'a> Parser<'a> {
|
|||
self.current = self.tokens.next();
|
||||
match &self.current {
|
||||
Some(token) if token.kind() == TokenKind::Error => {
|
||||
self.error_at_current(token.clone())
|
||||
self.error_at_current(token.to_string())
|
||||
}
|
||||
_ => break,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -89,9 +89,9 @@ impl<'a> Token<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a> Into<String> for Token<'a> {
|
||||
fn into(self) -> String {
|
||||
self.as_str().to_string()
|
||||
impl<'a> std::fmt::Display for Token<'a> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{}", self.as_str())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue