From 63a33b47a1b4750fa358f0333c6e00ada6823f26 Mon Sep 17 00:00:00 2001 From: Joscha Date: Fri, 18 Nov 2022 14:59:21 +0100 Subject: [PATCH] Parse field access suffix --- src/ast.rs | 2 +- src/parser.rs | 131 +++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 130 insertions(+), 3 deletions(-) diff --git a/src/ast.rs b/src/ast.rs index 0ca5669..9805edd 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -402,7 +402,7 @@ impl HasSpan for Expr { Expr::Paren { span, .. } => *span, Expr::TableConstr(tcr) => tcr.span(), Expr::Var { span, .. } => *span, - Expr::VarIdent(_) => todo!(), + Expr::VarIdent(name) => name.span(), Expr::VarAssign { span, .. } => *span, Expr::VarIdentAssign { name, value, .. } => name.span().join(value.span()), Expr::Neg { minus, expr, .. } => minus.join(expr.span()), diff --git a/src/parser.rs b/src/parser.rs index d4c7d92..5bbf015 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -5,7 +5,7 @@ use crate::ast::{ Expr, Ident, Lit, NumLit, NumLitStr, Space, StringLit, TableConstr, TableConstrElem, TableLit, TableLitElem, }; -use crate::span::Span; +use crate::span::{HasSpan, Span}; type Error = Simple; @@ -286,10 +286,137 @@ fn atom( .or(var_ident) } +enum Suffix { + /// See [`Expr::Field`]. + Field { + s0: Space, + s1: Space, + index: Box, + s2: Space, + span: Span, + }, + + /// See [`Expr::FieldIdent`]. + FieldIdent { s0: Space, s1: Space, ident: Ident }, + + /// See [`Expr::FieldAssign`]. + FieldAssign { + s0: Space, + s1: Space, + index: Box, + s2: Space, + s3: Space, + s4: Space, + value: Box, + }, + + /// See [`Expr::FieldIdentAssign`]. + FieldIdentAssign { + s0: Space, + s1: Space, + ident: Ident, + s2: Space, + s3: Space, + value: Box, + }, +} + +impl Suffix { + fn into_expr(self, expr: Expr) -> Expr { + let expr = Box::new(expr); + match self { + Suffix::Field { + s0, + s1, + index, + s2, + span, + } => Expr::Field { + span: expr.span().join(span), + expr, + s0, + s1, + index, + s2, + }, + Suffix::FieldIdent { s0, s1, ident } => Expr::FieldIdent { + expr, + s0, + s1, + ident, + }, + Suffix::FieldAssign { + s0, + s1, + index, + s2, + s3, + s4, + value, + } => Expr::FieldAssign { + expr, + s0, + s1, + index, + s2, + s3, + s4, + value, + }, + Suffix::FieldIdentAssign { + s0, + s1, + ident, + s2, + s3, + value, + } => Expr::FieldIdentAssign { + expr, + s0, + s1, + ident, + s2, + s3, + value, + }, + } + } +} + +fn suffix_field( + expr: impl Parser + Clone, +) -> impl Parser { + space() + .then_ignore(just("[")) + .then(space()) + .then(expr) + .then(space()) + .then_ignore(just("]")) + .map_with_span(|(((s0, s1), index), s2), span| Suffix::Field { + s0, + s1, + index: Box::new(index), + s2, + span, + }) +} + +fn suffixed( + expr: impl Parser + Clone, +) -> impl Parser { + let suffix_field = suffix_field(expr.clone()); + + let suffix = suffix_field; + + atom(expr) + .then(suffix.repeated()) + .foldl(|expr, suffix| suffix.into_expr(expr)) +} + fn expr( expr: impl Parser + Clone, ) -> impl Parser { - atom(expr) + suffixed(expr) } pub fn parser() -> impl Parser {