From 7539dda162bba856b8b00e724f9b1f734e81a0ca Mon Sep 17 00:00:00 2001 From: elkowar <5300871+elkowar@users.noreply.github.com> Date: Sun, 18 Jul 2021 20:52:38 +0200 Subject: [PATCH] add fileid to span --- src/ast.rs | 3 ++- src/error.rs | 23 +++++++++-------- src/lib.rs | 9 ++++--- src/parser/mod.rs | 6 ++--- src/simplexpr_parser.lalrpop | 48 ++++++++++++++++++------------------ 5 files changed, 47 insertions(+), 42 deletions(-) diff --git a/src/ast.rs b/src/ast.rs index 8b7562c..519b0d3 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -2,8 +2,9 @@ use crate::dynval::DynVal; use itertools::Itertools; use serde::{Deserialize, Serialize}; +/// stores the left and right end of a span, and a given file identifier. #[derive(Eq, PartialEq, Clone, Copy, Serialize, Deserialize)] -pub struct Span(pub usize, pub usize); +pub struct Span(pub usize, pub usize, pub usize); impl std::fmt::Display for Span { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { diff --git a/src/error.rs b/src/error.rs index 22b6041..74e193f 100644 --- a/src/error.rs +++ b/src/error.rs @@ -8,7 +8,7 @@ pub type Result = std::result::Result; #[derive(thiserror::Error, Debug)] pub enum Error { #[error("Parse error: {source}")] - ParseError { source: lalrpop_util::ParseError }, + ParseError { file_id: usize, source: lalrpop_util::ParseError }, #[error("Type error: {0}")] ConversionError(#[from] dynval::ConversionError), @@ -24,8 +24,8 @@ pub enum Error { } impl Error { - pub fn from_parse_error(err: lalrpop_util::ParseError) -> Self { - Error::ParseError { source: err } + pub fn from_parse_error(file_id: usize, err: lalrpop_util::ParseError) -> Self { + Error::ParseError { file_id, source: err } } pub fn at(self, span: Span) -> Self { @@ -34,7 +34,7 @@ impl Error { pub fn get_span(&self) -> Option { match self { - Self::ParseError { source } => get_parse_error_span(source), + Self::ParseError { file_id, source } => get_parse_error_span(*file_id, source), Self::Spanned(span, _) => Some(*span), Self::Eval(err) => err.span(), Self::ConversionError(err) => err.span(), @@ -43,13 +43,16 @@ impl Error { } } -fn get_parse_error_span(err: &lalrpop_util::ParseError) -> Option { +fn get_parse_error_span( + file_id: usize, + err: &lalrpop_util::ParseError, +) -> Option { match err { - lalrpop_util::ParseError::InvalidToken { location } => Some(Span(*location, *location)), - lalrpop_util::ParseError::UnrecognizedEOF { location, expected: _ } => Some(Span(*location, *location)), - lalrpop_util::ParseError::UnrecognizedToken { token, expected: _ } => Some(Span(token.0, token.2)), - lalrpop_util::ParseError::ExtraToken { token } => Some(Span(token.0, token.2)), - lalrpop_util::ParseError::User { error: LexicalError(l, r) } => Some(Span(*l, *r)), + lalrpop_util::ParseError::InvalidToken { location } => Some(Span(*location, *location, file_id)), + lalrpop_util::ParseError::UnrecognizedEOF { location, expected: _ } => Some(Span(*location, *location, file_id)), + lalrpop_util::ParseError::UnrecognizedToken { token, expected: _ } => Some(Span(token.0, token.2, file_id)), + lalrpop_util::ParseError::ExtraToken { token } => Some(Span(token.0, token.2, file_id)), + lalrpop_util::ParseError::User { error: LexicalError(l, r) } => Some(Span(*l, *r, file_id)), } } diff --git a/src/lib.rs b/src/lib.rs index 2398211..74df615 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -6,7 +6,9 @@ pub mod dynval; pub mod error; pub mod eval; pub mod parser; -use ast::SimplExpr; + +pub use ast::{SimplExpr, Span}; + use lalrpop_util::lalrpop_mod; lalrpop_mod!( @@ -14,7 +16,6 @@ lalrpop_mod!( pub simplexpr_parser ); -pub fn parse_string(s: &str) -> Result { - parser::parse_string(s) +pub fn parse_string(file_id: usize, s: &str) -> Result { + parser::parse_string(file_id, s) } -pub use ast::Span; diff --git a/src/parser/mod.rs b/src/parser/mod.rs index a867374..f833b61 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -6,10 +6,10 @@ use crate::{ error::{Error, Result}, }; -pub fn parse_string(s: &str) -> Result { +pub fn parse_string(file_id: usize, s: &str) -> Result { let lexer = lexer::Lexer::new(s); let parser = crate::simplexpr_parser::ExprParser::new(); - parser.parse(lexer).map_err(Error::from_parse_error) + parser.parse(file_id, lexer).map_err(|e| Error::from_parse_error(file_id, e)) } #[cfg(test)] @@ -20,7 +20,7 @@ mod tests { use crate::parser::lexer::Lexer; ::insta::with_settings!({sort_maps => true}, { $( - ::insta::assert_debug_snapshot!(p.parse(Lexer::new($text))); + ::insta::assert_debug_snapshot!(p.parse(0, Lexer::new($text))); )* }); }} diff --git a/src/simplexpr_parser.lalrpop b/src/simplexpr_parser.lalrpop index 2f1c8dd..f351087 100644 --- a/src/simplexpr_parser.lalrpop +++ b/src/simplexpr_parser.lalrpop @@ -4,7 +4,7 @@ use crate::parser::lalrpop_helpers::*; use lalrpop_util::ParseError; -grammar; +grammar(fid: usize); extern { type Location = usize; @@ -66,54 +66,54 @@ pub Expr: SimplExpr = { }, , - => VarRef(Span(l, r), ident.to_string()), + => VarRef(Span(l, r, fid), ident.to_string()), "(" ")", #[precedence(level="1")] #[assoc(side="right")] - "(" > ")" => FunctionCall(Span(l, r), ident, args), - "[" "]" => JsonAccess(Span(l, r), b(value), b(index)), + "(" > ")" => FunctionCall(Span(l, r, fid), ident, args), + "[" "]" => JsonAccess(Span(l, r, fid), b(value), b(index)), "." => { - JsonAccess(Span(l, r), b(value), b(Literal(Span(lit_l, r), index.into()))) + JsonAccess(Span(l, r, fid), b(value), b(Literal(Span(lit_l, r, fid), index.into()))) }, #[precedence(level="2")] #[assoc(side="right")] - "!" => UnaryOp(Span(l, r), Not, b(e)), + "!" => UnaryOp(Span(l, r, fid), Not, b(e)), #[precedence(level="3")] #[assoc(side="left")] - "*" => BinOp(Span(l, r), b(le), Times, b(re)), - "/" => BinOp(Span(l, r), b(le), Div, b(re)), - "%" => BinOp(Span(l, r), b(le), Mod, b(re)), + "*" => BinOp(Span(l, r, fid), b(le), Times, b(re)), + "/" => BinOp(Span(l, r, fid), b(le), Div, b(re)), + "%" => BinOp(Span(l, r, fid), b(le), Mod, b(re)), #[precedence(level="4")] #[assoc(side="left")] - "+" => BinOp(Span(l, r), b(le), Plus, b(re)), - "-" => BinOp(Span(l, r), b(le), Minus, b(re)), + "+" => BinOp(Span(l, r, fid), b(le), Plus, b(re)), + "-" => BinOp(Span(l, r, fid), b(le), Minus, b(re)), #[precedence(level="5")] #[assoc(side="left")] - "==" => BinOp(Span(l, r), b(le), Equals, b(re)), - "!=" => BinOp(Span(l, r), b(le), NotEquals, b(re)), - "<" => BinOp(Span(l, r), b(le), GT, b(re)), - ">" => BinOp(Span(l, r), b(le), LT, b(re)), - "=~" => BinOp(Span(l, r), b(le), RegexMatch, b(re)), + "==" => BinOp(Span(l, r, fid), b(le), Equals, b(re)), + "!=" => BinOp(Span(l, r, fid), b(le), NotEquals, b(re)), + "<" => BinOp(Span(l, r, fid), b(le), GT, b(re)), + ">" => BinOp(Span(l, r, fid), b(le), LT, b(re)), + "=~" => BinOp(Span(l, r, fid), b(le), RegexMatch, b(re)), #[precedence(level="6")] #[assoc(side="left")] - "&&" => BinOp(Span(l, r), b(le), And, b(re)), - "||" => BinOp(Span(l, r), b(le), Or, b(re)), - "?:" => BinOp(Span(l, r), b(le), Elvis, b(re)), + "&&" => BinOp(Span(l, r, fid), b(le), And, b(re)), + "||" => BinOp(Span(l, r, fid), b(le), Or, b(re)), + "?:" => BinOp(Span(l, r, fid), b(le), Elvis, b(re)), #[precedence(level="7")] #[assoc(side="right")] "?" ":" => { - IfElse(Span(l, r), b(cond), b(then), b(els)) + IfElse(Span(l, r, fid), b(cond), b(then), b(els)) }, }; ExprReset = ; Literal: SimplExpr = { - => SimplExpr::literal(Span(l, r), x), - => SimplExpr::literal(Span(l, r), x), - "true" => SimplExpr::literal(Span(l, r), "true".into()), - "false" => SimplExpr::literal(Span(l, r), "false".into()), + => SimplExpr::literal(Span(l, r, fid), x), + => SimplExpr::literal(Span(l, r, fid), x), + "true" => SimplExpr::literal(Span(l, r, fid), "true".into()), + "false" => SimplExpr::literal(Span(l, r, fid), "false".into()), } StrLit: String = {