add fileid to span

This commit is contained in:
elkowar 2021-07-18 20:52:38 +02:00
parent a6fe813ed1
commit 7539dda162
No known key found for this signature in database
GPG key ID: E321AD71B1D1F27F
5 changed files with 47 additions and 42 deletions

View file

@ -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 {

View file

@ -8,7 +8,7 @@ pub type Result<T> = std::result::Result<T, Error>;
#[derive(thiserror::Error, Debug)]
pub enum Error {
#[error("Parse error: {source}")]
ParseError { source: lalrpop_util::ParseError<usize, lexer::Token, lexer::LexicalError> },
ParseError { file_id: usize, source: lalrpop_util::ParseError<usize, lexer::Token, lexer::LexicalError> },
#[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<usize, lexer::Token, lexer::LexicalError>) -> Self {
Error::ParseError { source: err }
pub fn from_parse_error(file_id: usize, err: lalrpop_util::ParseError<usize, lexer::Token, lexer::LexicalError>) -> 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<Span> {
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<usize, lexer::Token, lexer::LexicalError>) -> Option<Span> {
fn get_parse_error_span(
file_id: usize,
err: &lalrpop_util::ParseError<usize, lexer::Token, lexer::LexicalError>,
) -> Option<Span> {
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)),
}
}

View file

@ -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<SimplExpr, error::Error> {
parser::parse_string(s)
pub fn parse_string(file_id: usize, s: &str) -> Result<SimplExpr, error::Error> {
parser::parse_string(file_id, s)
}
pub use ast::Span;

View file

@ -6,10 +6,10 @@ use crate::{
error::{Error, Result},
};
pub fn parse_string(s: &str) -> Result<SimplExpr> {
pub fn parse_string(file_id: usize, s: &str) -> Result<SimplExpr> {
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)));
)*
});
}}

View file

@ -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 = {
},
<Literal>,
<l:@L> <ident:"identifier"> <r:@R> => VarRef(Span(l, r), ident.to_string()),
<l:@L> <ident:"identifier"> <r:@R> => VarRef(Span(l, r, fid), ident.to_string()),
"(" <ExprReset> ")",
#[precedence(level="1")] #[assoc(side="right")]
<l:@L> <ident:"identifier"> "(" <args: Comma<ExprReset>> ")" <r:@R> => FunctionCall(Span(l, r), ident, args),
<l:@L> <value:Expr> "[" <index: ExprReset> "]" <r:@R> => JsonAccess(Span(l, r), b(value), b(index)),
<l:@L> <ident:"identifier"> "(" <args: Comma<ExprReset>> ")" <r:@R> => FunctionCall(Span(l, r, fid), ident, args),
<l:@L> <value:Expr> "[" <index: ExprReset> "]" <r:@R> => JsonAccess(Span(l, r, fid), b(value), b(index)),
<l:@L> <value:Expr> "." <lit_l:@L> <index:"identifier"> <r:@R> => {
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")]
<l:@L> "!" <e:Expr> <r:@R> => UnaryOp(Span(l, r), Not, b(e)),
<l:@L> "!" <e:Expr> <r:@R> => UnaryOp(Span(l, r, fid), Not, b(e)),
#[precedence(level="3")] #[assoc(side="left")]
<l:@L> <le:Expr> "*" <re:Expr> <r:@R> => BinOp(Span(l, r), b(le), Times, b(re)),
<l:@L> <le:Expr> "/" <re:Expr> <r:@R> => BinOp(Span(l, r), b(le), Div, b(re)),
<l:@L> <le:Expr> "%" <re:Expr> <r:@R> => BinOp(Span(l, r), b(le), Mod, b(re)),
<l:@L> <le:Expr> "*" <re:Expr> <r:@R> => BinOp(Span(l, r, fid), b(le), Times, b(re)),
<l:@L> <le:Expr> "/" <re:Expr> <r:@R> => BinOp(Span(l, r, fid), b(le), Div, b(re)),
<l:@L> <le:Expr> "%" <re:Expr> <r:@R> => BinOp(Span(l, r, fid), b(le), Mod, b(re)),
#[precedence(level="4")] #[assoc(side="left")]
<l:@L> <le:Expr> "+" <re:Expr> <r:@R> => BinOp(Span(l, r), b(le), Plus, b(re)),
<l:@L> <le:Expr> "-" <re:Expr> <r:@R> => BinOp(Span(l, r), b(le), Minus, b(re)),
<l:@L> <le:Expr> "+" <re:Expr> <r:@R> => BinOp(Span(l, r, fid), b(le), Plus, b(re)),
<l:@L> <le:Expr> "-" <re:Expr> <r:@R> => BinOp(Span(l, r, fid), b(le), Minus, b(re)),
#[precedence(level="5")] #[assoc(side="left")]
<l:@L> <le:Expr> "==" <re:Expr> <r:@R> => BinOp(Span(l, r), b(le), Equals, b(re)),
<l:@L> <le:Expr> "!=" <re:Expr> <r:@R> => BinOp(Span(l, r), b(le), NotEquals, b(re)),
<l:@L> <le:Expr> "<" <re:Expr> <r:@R> => BinOp(Span(l, r), b(le), GT, b(re)),
<l:@L> <le:Expr> ">" <re:Expr> <r:@R> => BinOp(Span(l, r), b(le), LT, b(re)),
<l:@L> <le:Expr> "=~" <re:Expr> <r:@R> => BinOp(Span(l, r), b(le), RegexMatch, b(re)),
<l:@L> <le:Expr> "==" <re:Expr> <r:@R> => BinOp(Span(l, r, fid), b(le), Equals, b(re)),
<l:@L> <le:Expr> "!=" <re:Expr> <r:@R> => BinOp(Span(l, r, fid), b(le), NotEquals, b(re)),
<l:@L> <le:Expr> "<" <re:Expr> <r:@R> => BinOp(Span(l, r, fid), b(le), GT, b(re)),
<l:@L> <le:Expr> ">" <re:Expr> <r:@R> => BinOp(Span(l, r, fid), b(le), LT, b(re)),
<l:@L> <le:Expr> "=~" <re:Expr> <r:@R> => BinOp(Span(l, r, fid), b(le), RegexMatch, b(re)),
#[precedence(level="6")] #[assoc(side="left")]
<l:@L> <le:Expr> "&&" <re:Expr> <r:@R> => BinOp(Span(l, r), b(le), And, b(re)),
<l:@L> <le:Expr> "||" <re:Expr> <r:@R> => BinOp(Span(l, r), b(le), Or, b(re)),
<l:@L> <le:Expr> "?:" <re:Expr> <r:@R> => BinOp(Span(l, r), b(le), Elvis, b(re)),
<l:@L> <le:Expr> "&&" <re:Expr> <r:@R> => BinOp(Span(l, r, fid), b(le), And, b(re)),
<l:@L> <le:Expr> "||" <re:Expr> <r:@R> => BinOp(Span(l, r, fid), b(le), Or, b(re)),
<l:@L> <le:Expr> "?:" <re:Expr> <r:@R> => BinOp(Span(l, r, fid), b(le), Elvis, b(re)),
#[precedence(level="7")] #[assoc(side="right")]
<l:@L> <cond:Expr> "?" <then:ExprReset> ":" <els:Expr> <r:@R> => {
IfElse(Span(l, r), b(cond), b(then), b(els))
IfElse(Span(l, r, fid), b(cond), b(then), b(els))
},
};
ExprReset = <Expr>;
Literal: SimplExpr = {
<l:@L> <x:StrLit> <r:@R> => SimplExpr::literal(Span(l, r), x),
<l:@L> <x:"number"> <r:@R> => SimplExpr::literal(Span(l, r), x),
<l:@L> "true" <r:@R> => SimplExpr::literal(Span(l, r), "true".into()),
<l:@L> "false" <r:@R> => SimplExpr::literal(Span(l, r), "false".into()),
<l:@L> <x:StrLit> <r:@R> => SimplExpr::literal(Span(l, r, fid), x),
<l:@L> <x:"number"> <r:@R> => SimplExpr::literal(Span(l, r, fid), x),
<l:@L> "true" <r:@R> => SimplExpr::literal(Span(l, r, fid), "true".into()),
<l:@L> "false" <r:@R> => SimplExpr::literal(Span(l, r, fid), "false".into()),
}
StrLit: String = {