add fileid to span
This commit is contained in:
parent
a6fe813ed1
commit
7539dda162
5 changed files with 47 additions and 42 deletions
|
@ -2,8 +2,9 @@ use crate::dynval::DynVal;
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use serde::{Deserialize, Serialize};
|
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)]
|
#[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 {
|
impl std::fmt::Display for Span {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
|
23
src/error.rs
23
src/error.rs
|
@ -8,7 +8,7 @@ pub type Result<T> = std::result::Result<T, Error>;
|
||||||
#[derive(thiserror::Error, Debug)]
|
#[derive(thiserror::Error, Debug)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
#[error("Parse error: {source}")]
|
#[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}")]
|
#[error("Type error: {0}")]
|
||||||
ConversionError(#[from] dynval::ConversionError),
|
ConversionError(#[from] dynval::ConversionError),
|
||||||
|
@ -24,8 +24,8 @@ pub enum Error {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Error {
|
impl Error {
|
||||||
pub fn from_parse_error(err: lalrpop_util::ParseError<usize, lexer::Token, lexer::LexicalError>) -> Self {
|
pub fn from_parse_error(file_id: usize, err: lalrpop_util::ParseError<usize, lexer::Token, lexer::LexicalError>) -> Self {
|
||||||
Error::ParseError { source: err }
|
Error::ParseError { file_id, source: err }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn at(self, span: Span) -> Self {
|
pub fn at(self, span: Span) -> Self {
|
||||||
|
@ -34,7 +34,7 @@ impl Error {
|
||||||
|
|
||||||
pub fn get_span(&self) -> Option<Span> {
|
pub fn get_span(&self) -> Option<Span> {
|
||||||
match self {
|
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::Spanned(span, _) => Some(*span),
|
||||||
Self::Eval(err) => err.span(),
|
Self::Eval(err) => err.span(),
|
||||||
Self::ConversionError(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 {
|
match err {
|
||||||
lalrpop_util::ParseError::InvalidToken { location } => Some(Span(*location, *location)),
|
lalrpop_util::ParseError::InvalidToken { location } => Some(Span(*location, *location, file_id)),
|
||||||
lalrpop_util::ParseError::UnrecognizedEOF { location, expected: _ } => Some(Span(*location, *location)),
|
lalrpop_util::ParseError::UnrecognizedEOF { location, expected: _ } => Some(Span(*location, *location, file_id)),
|
||||||
lalrpop_util::ParseError::UnrecognizedToken { token, expected: _ } => Some(Span(token.0, token.2)),
|
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)),
|
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)),
|
lalrpop_util::ParseError::User { error: LexicalError(l, r) } => Some(Span(*l, *r, file_id)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,9 @@ pub mod dynval;
|
||||||
pub mod error;
|
pub mod error;
|
||||||
pub mod eval;
|
pub mod eval;
|
||||||
pub mod parser;
|
pub mod parser;
|
||||||
use ast::SimplExpr;
|
|
||||||
|
pub use ast::{SimplExpr, Span};
|
||||||
|
|
||||||
use lalrpop_util::lalrpop_mod;
|
use lalrpop_util::lalrpop_mod;
|
||||||
|
|
||||||
lalrpop_mod!(
|
lalrpop_mod!(
|
||||||
|
@ -14,7 +16,6 @@ lalrpop_mod!(
|
||||||
pub simplexpr_parser
|
pub simplexpr_parser
|
||||||
);
|
);
|
||||||
|
|
||||||
pub fn parse_string(s: &str) -> Result<SimplExpr, error::Error> {
|
pub fn parse_string(file_id: usize, s: &str) -> Result<SimplExpr, error::Error> {
|
||||||
parser::parse_string(s)
|
parser::parse_string(file_id, s)
|
||||||
}
|
}
|
||||||
pub use ast::Span;
|
|
||||||
|
|
|
@ -6,10 +6,10 @@ use crate::{
|
||||||
error::{Error, Result},
|
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 lexer = lexer::Lexer::new(s);
|
||||||
let parser = crate::simplexpr_parser::ExprParser::new();
|
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)]
|
#[cfg(test)]
|
||||||
|
@ -20,7 +20,7 @@ mod tests {
|
||||||
use crate::parser::lexer::Lexer;
|
use crate::parser::lexer::Lexer;
|
||||||
::insta::with_settings!({sort_maps => true}, {
|
::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)));
|
||||||
)*
|
)*
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
|
|
|
@ -4,7 +4,7 @@ use crate::parser::lalrpop_helpers::*;
|
||||||
use lalrpop_util::ParseError;
|
use lalrpop_util::ParseError;
|
||||||
|
|
||||||
|
|
||||||
grammar;
|
grammar(fid: usize);
|
||||||
|
|
||||||
extern {
|
extern {
|
||||||
type Location = usize;
|
type Location = usize;
|
||||||
|
@ -66,54 +66,54 @@ pub Expr: SimplExpr = {
|
||||||
},
|
},
|
||||||
|
|
||||||
<Literal>,
|
<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> ")",
|
"(" <ExprReset> ")",
|
||||||
|
|
||||||
#[precedence(level="1")] #[assoc(side="right")]
|
#[precedence(level="1")] #[assoc(side="right")]
|
||||||
<l:@L> <ident:"identifier"> "(" <args: Comma<ExprReset>> ")" <r:@R> => FunctionCall(Span(l, r), ident, args),
|
<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), b(value), b(index)),
|
<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> => {
|
<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")]
|
#[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")]
|
#[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, fid), 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, fid), 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), Mod, b(re)),
|
||||||
|
|
||||||
#[precedence(level="4")] #[assoc(side="left")]
|
#[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, fid), 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), Minus, b(re)),
|
||||||
|
|
||||||
#[precedence(level="5")] #[assoc(side="left")]
|
#[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, fid), 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, fid), 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, fid), 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, fid), 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), RegexMatch, b(re)),
|
||||||
|
|
||||||
#[precedence(level="6")] #[assoc(side="left")]
|
#[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, fid), 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, fid), 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), Elvis, b(re)),
|
||||||
|
|
||||||
#[precedence(level="7")] #[assoc(side="right")]
|
#[precedence(level="7")] #[assoc(side="right")]
|
||||||
<l:@L> <cond:Expr> "?" <then:ExprReset> ":" <els:Expr> <r:@R> => {
|
<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>;
|
ExprReset = <Expr>;
|
||||||
|
|
||||||
Literal: SimplExpr = {
|
Literal: SimplExpr = {
|
||||||
<l:@L> <x:StrLit> <r:@R> => SimplExpr::literal(Span(l, r), x),
|
<l:@L> <x:StrLit> <r:@R> => SimplExpr::literal(Span(l, r, fid), x),
|
||||||
<l:@L> <x:"number"> <r:@R> => SimplExpr::literal(Span(l, r), x),
|
<l:@L> <x:"number"> <r:@R> => SimplExpr::literal(Span(l, r, fid), x),
|
||||||
<l:@L> "true" <r:@R> => SimplExpr::literal(Span(l, r), "true".into()),
|
<l:@L> "true" <r:@R> => SimplExpr::literal(Span(l, r, fid), "true".into()),
|
||||||
<l:@L> "false" <r:@R> => SimplExpr::literal(Span(l, r), "false".into()),
|
<l:@L> "false" <r:@R> => SimplExpr::literal(Span(l, r, fid), "false".into()),
|
||||||
}
|
}
|
||||||
|
|
||||||
StrLit: String = {
|
StrLit: String = {
|
||||||
|
|
Loading…
Add table
Reference in a new issue