diff --git a/oden-script/src/parser.rs b/oden-script/src/parser.rs index e05c9a84..262164f7 100644 --- a/oden-script/src/parser.rs +++ b/oden-script/src/parser.rs @@ -61,16 +61,18 @@ impl ExprRef { } } -pub struct SyntaxTree { +pub struct SyntaxTree<'a> { pub errors: Vec, expressions: Vec, + spans: Vec<(Option>, Option>)>, } -impl SyntaxTree { +impl<'a> SyntaxTree<'a> { pub fn new() -> Self { SyntaxTree { errors: Vec::new(), expressions: Vec::new(), + spans: Vec::new(), } } @@ -78,12 +80,27 @@ impl SyntaxTree { self.errors.push(error); } - pub fn add_expr(&mut self, expr: Expr) -> ExprRef { + pub fn add_expr( + &mut self, + expr: Expr, + start: Option>, + end: Option>, + ) -> 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>, Option>) { + 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) => { @@ -153,7 +170,7 @@ fn token_power<'a>(token: &Option>) -> Option { pub struct Parser<'a> { tokens: Tokens<'a>, - tree: SyntaxTree, + tree: SyntaxTree<'a>, current: Option>, previous: Option>, @@ -173,7 +190,7 @@ impl<'a> Parser<'a> { parser } - pub fn parse(mut self) -> (SyntaxTree, ExprRef) { + pub fn parse(mut self) -> (SyntaxTree<'a>, ExprRef) { let expr = self.expression(); self.consume(None, "expected end of expression"); (self.tree, expr) @@ -238,13 +255,19 @@ impl<'a> Parser<'a> { let token = self.previous.as_ref().unwrap(); // What kind is it? For now let's just ... make it good. - match token.as_str().parse::() { - Ok(v) => self.tree.add_expr(Expr::Literal(Literal::Float64(v))), + let literal = match token.as_str().parse::() { + Ok(v) => Literal::Float64(v), Err(e) => { self.error(format!("invalid f64: {e}")); - ExprRef::error() + return ExprRef::error(); } - } + }; + + self.tree.add_expr( + Expr::Literal(literal), + Some(token.clone()), + Some(token.clone()), + ) } fn grouping(&mut self) -> ExprRef { @@ -257,17 +280,21 @@ impl<'a> Parser<'a> { } fn unary(&mut self) -> ExprRef { - let kind = self.previous.as_ref().unwrap().kind(); + let token = self.previous.as_ref().unwrap().clone(); + let kind = token.kind(); let expr = self.expression_with_power(UNARY_POWER); let op = match kind { TokenKind::Minus => UnaryOp::Negate, _ => panic!("unsuitable unary: {:?}: no op", kind), }; - self.tree.add_expr(Expr::Unary(op, expr)) + + self.tree + .add_expr(Expr::Unary(op, expr), Some(token), self.previous.clone()) } fn binary(&mut self, power: u8, left: ExprRef) -> ExprRef { - let op = match self.previous.as_ref().unwrap().kind() { + let token = self.previous.as_ref().unwrap().clone(); + let op = match token.kind() { TokenKind::Plus => BinaryOp::Add, TokenKind::Minus => BinaryOp::Subtract, TokenKind::Star => BinaryOp::Mutiply, @@ -278,7 +305,11 @@ impl<'a> Parser<'a> { }; let right = self.expression_with_power(power + 1); - self.tree.add_expr(Expr::Binary(op, 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) {