Finish basic parser
This commit is contained in:
parent
923d478b33
commit
c5643424ca
35 changed files with 596 additions and 235 deletions
|
@ -19,6 +19,8 @@ logos = "0.12"
|
||||||
serde = {version = "1.0", features = ["derive"]}
|
serde = {version = "1.0", features = ["derive"]}
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
|
|
||||||
|
strum = { version = "0.21", features = ["derive"] }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
|
|
2
build.rs
2
build.rs
|
@ -1,4 +1,4 @@
|
||||||
extern crate lalrpop;
|
extern crate lalrpop;
|
||||||
fn main() {
|
fn main() {
|
||||||
lalrpop::process_root().unwrap();
|
lalrpop::Configuration::new().log_verbose().process_current_dir().unwrap();
|
||||||
}
|
}
|
||||||
|
|
19
examples/errors.rs
Normal file
19
examples/errors.rs
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
fn main() {
|
||||||
|
let mut files = codespan_reporting::files::SimpleFiles::new();
|
||||||
|
|
||||||
|
let input = "12 + \"hi\" * foo ) ? bar == baz : false";
|
||||||
|
|
||||||
|
let _ = files.add("foo.eww", input);
|
||||||
|
let ast = simplexpr::parse_string(input);
|
||||||
|
match ast {
|
||||||
|
Ok(ast) => {
|
||||||
|
println!("{:?}", ast);
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
let diag = err.pretty_diagnostic();
|
||||||
|
use codespan_reporting::term;
|
||||||
|
let mut writer = term::termcolor::StandardStream::stderr(term::termcolor::ColorChoice::Always);
|
||||||
|
term::emit(&mut writer, &term::Config::default(), &files, &diag).unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
100
src/ast.rs
100
src/ast.rs
|
@ -1,8 +1,8 @@
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[derive(Eq, PartialEq, Clone, Copy)]
|
#[derive(Eq, PartialEq, Clone, Copy, Serialize, Deserialize)]
|
||||||
pub struct Span(pub usize, pub usize, pub usize);
|
pub struct Span(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 {
|
||||||
|
@ -16,79 +16,59 @@ impl std::fmt::Debug for Span {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Serialize, Deserialize, Debug)]
|
#[rustfmt::skip]
|
||||||
|
#[derive(Clone, PartialEq, Serialize, Deserialize, Debug, strum::EnumString, strum::Display)]
|
||||||
pub enum BinOp {
|
pub enum BinOp {
|
||||||
Plus,
|
#[strum(serialize = "+") ] Plus,
|
||||||
Minus,
|
#[strum(serialize = "-") ] Minus,
|
||||||
Times,
|
#[strum(serialize = "*") ] Times,
|
||||||
Div,
|
#[strum(serialize = "/") ] Div,
|
||||||
Mod,
|
#[strum(serialize = "%") ] Mod,
|
||||||
Equals,
|
#[strum(serialize = "==")] Equals,
|
||||||
NotEquals,
|
#[strum(serialize = "!=")] NotEquals,
|
||||||
And,
|
#[strum(serialize = "&&")] And,
|
||||||
Or,
|
#[strum(serialize = "||")] Or,
|
||||||
GT,
|
#[strum(serialize = ">") ] GT,
|
||||||
LT,
|
#[strum(serialize = "<") ] LT,
|
||||||
Elvis,
|
#[strum(serialize = "?:")] Elvis,
|
||||||
RegexMatch,
|
#[strum(serialize = "=~")] RegexMatch,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::fmt::Display for BinOp {
|
#[derive(Clone, PartialEq, Serialize, Deserialize, Debug, strum::EnumString, strum::Display)]
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
||||||
match self {
|
|
||||||
BinOp::Plus => write!(f, "+"),
|
|
||||||
BinOp::Minus => write!(f, "-"),
|
|
||||||
BinOp::Times => write!(f, "*"),
|
|
||||||
BinOp::Div => write!(f, "/"),
|
|
||||||
BinOp::Mod => write!(f, "%"),
|
|
||||||
BinOp::Equals => write!(f, "=="),
|
|
||||||
BinOp::NotEquals => write!(f, "!="),
|
|
||||||
BinOp::And => write!(f, "&&"),
|
|
||||||
BinOp::Or => write!(f, "||"),
|
|
||||||
BinOp::GT => write!(f, ">"),
|
|
||||||
BinOp::LT => write!(f, "<"),
|
|
||||||
BinOp::Elvis => write!(f, "?:"),
|
|
||||||
BinOp::RegexMatch => write!(f, "=~"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Serialize, Deserialize, Debug)]
|
|
||||||
pub enum UnaryOp {
|
pub enum UnaryOp {
|
||||||
|
#[strum(serialize = "!")]
|
||||||
Not,
|
Not,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::fmt::Display for UnaryOp {
|
#[derive(Clone, PartialEq, Serialize, Deserialize)]
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
||||||
match self {
|
|
||||||
UnaryOp::Not => write!(f, "!"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Serialize, Deserialize, Debug)]
|
|
||||||
pub enum SimplExpr {
|
pub enum SimplExpr {
|
||||||
Literal(String),
|
Literal(Span, String),
|
||||||
VarRef(String),
|
VarRef(Span, String),
|
||||||
BinOp(Box<SimplExpr>, BinOp, Box<SimplExpr>),
|
BinOp(Span, Box<SimplExpr>, BinOp, Box<SimplExpr>),
|
||||||
UnaryOp(UnaryOp, Box<SimplExpr>),
|
UnaryOp(Span, UnaryOp, Box<SimplExpr>),
|
||||||
IfElse(Box<SimplExpr>, Box<SimplExpr>, Box<SimplExpr>),
|
IfElse(Span, Box<SimplExpr>, Box<SimplExpr>, Box<SimplExpr>),
|
||||||
JsonAccess(Box<SimplExpr>, Box<SimplExpr>),
|
JsonAccess(Span, Box<SimplExpr>, Box<SimplExpr>),
|
||||||
FunctionCall(String, Vec<SimplExpr>),
|
FunctionCall(Span, String, Vec<SimplExpr>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::fmt::Display for SimplExpr {
|
impl std::fmt::Display for SimplExpr {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
SimplExpr::VarRef(x) => write!(f, "{}", x),
|
SimplExpr::VarRef(_, x) => write!(f, "{}", x),
|
||||||
SimplExpr::Literal(x) => write!(f, "\"{}\"", x),
|
SimplExpr::Literal(_, x) => write!(f, "\"{}\"", x),
|
||||||
SimplExpr::BinOp(l, op, r) => write!(f, "({} {} {})", l, op, r),
|
SimplExpr::BinOp(_, l, op, r) => write!(f, "({} {} {})", l, op, r),
|
||||||
SimplExpr::UnaryOp(op, x) => write!(f, "{}{}", op, x),
|
SimplExpr::UnaryOp(_, op, x) => write!(f, "{}{}", op, x),
|
||||||
SimplExpr::IfElse(a, b, c) => write!(f, "(if {} then {} else {})", a, b, c),
|
SimplExpr::IfElse(_, a, b, c) => write!(f, "(if {} then {} else {})", a, b, c),
|
||||||
SimplExpr::JsonAccess(value, index) => write!(f, "{}[{}]", value, index),
|
SimplExpr::JsonAccess(_, value, index) => write!(f, "{}[{}]", value, index),
|
||||||
SimplExpr::FunctionCall(function_name, args) => {
|
SimplExpr::FunctionCall(_, function_name, args) => {
|
||||||
write!(f, "{}({})", function_name, args.iter().join(", "))
|
write!(f, "{}({})", function_name, args.iter().join(", "))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Debug for SimplExpr {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(f, "{}", self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
46
src/error.rs
Normal file
46
src/error.rs
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
use crate::{ast::Span, lexer};
|
||||||
|
use codespan_reporting::diagnostic;
|
||||||
|
|
||||||
|
pub type Result<T> = std::result::Result<T, Error>;
|
||||||
|
pub enum Error {
|
||||||
|
ParseError { source: lalrpop_util::ParseError<usize, lexer::Token, lexer::LexicalError> },
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Display for Error {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
Self::ParseError { source } => write!(f, "Parse error: {}", source),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Error {
|
||||||
|
pub fn from_parse_error(err: lalrpop_util::ParseError<usize, lexer::Token, lexer::LexicalError>) -> Self {
|
||||||
|
Error::ParseError { source: err }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_span(&self) -> Option<Span> {
|
||||||
|
match self {
|
||||||
|
Self::ParseError { source } => get_parse_error_span(source),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn pretty_diagnostic(&self) -> diagnostic::Diagnostic<usize> {
|
||||||
|
let diag = diagnostic::Diagnostic::error().with_message(format!("{}", self));
|
||||||
|
if let Some(span) = self.get_span() {
|
||||||
|
diag.with_labels(vec![diagnostic::Label::primary(0, span.0..span.1)])
|
||||||
|
} else {
|
||||||
|
diag
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_parse_error_span(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: _ } => None,
|
||||||
|
}
|
||||||
|
}
|
3
src/lalrpop_helpers.rs
Normal file
3
src/lalrpop_helpers.rs
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
pub fn b<T>(x: T) -> Box<T> {
|
||||||
|
Box::new(x)
|
||||||
|
}
|
78
src/lexer.rs
Normal file
78
src/lexer.rs
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
use logos::Logos;
|
||||||
|
|
||||||
|
#[rustfmt::skip]
|
||||||
|
#[derive(Logos, Debug, PartialEq, Eq, Clone, strum::Display)]
|
||||||
|
pub enum Token {
|
||||||
|
#[strum(serialize = "+") ] #[token("+") ] Plus,
|
||||||
|
#[strum(serialize = "-") ] #[token("-") ] Minus,
|
||||||
|
#[strum(serialize = "*") ] #[token("*") ] Times,
|
||||||
|
#[strum(serialize = "/") ] #[token("/") ] Div,
|
||||||
|
#[strum(serialize = "%") ] #[token("%") ] Mod,
|
||||||
|
#[strum(serialize = "==")] #[token("==")] Equals,
|
||||||
|
#[strum(serialize = "!=")] #[token("!=")] NotEquals,
|
||||||
|
#[strum(serialize = "&&")] #[token("&&")] And,
|
||||||
|
#[strum(serialize = "||")] #[token("||")] Or,
|
||||||
|
#[strum(serialize = ">") ] #[token(">") ] GT,
|
||||||
|
#[strum(serialize = "<") ] #[token("<") ] LT,
|
||||||
|
#[strum(serialize = "?:")] #[token("?:")] Elvis,
|
||||||
|
#[strum(serialize = "=~")] #[token("=~")] RegexMatch,
|
||||||
|
|
||||||
|
#[strum(serialize = "!") ] #[token("!") ] Not,
|
||||||
|
|
||||||
|
#[strum(serialize = ",") ] #[token(",") ] Comma,
|
||||||
|
#[strum(serialize = "?") ] #[token("?") ] Question,
|
||||||
|
#[strum(serialize = ":") ] #[token(":") ] Colon,
|
||||||
|
#[strum(serialize = "(") ] #[token("(") ] LPren,
|
||||||
|
#[strum(serialize = ")") ] #[token(")") ] RPren,
|
||||||
|
#[strum(serialize = "[") ] #[token("[") ] LBrack,
|
||||||
|
#[strum(serialize = "]") ] #[token("]") ] RBrack,
|
||||||
|
#[strum(serialize = ".") ] #[token(".") ] Dot,
|
||||||
|
#[strum(serialize = "true") ] #[token("true") ] True,
|
||||||
|
#[strum(serialize = "false")] #[token("false")] False,
|
||||||
|
|
||||||
|
#[regex(r"[a-zA-Z_-]+", |x| x.slice().to_string())]
|
||||||
|
Ident(String),
|
||||||
|
#[regex(r"[+-]?(?:[0-9]+[.])?[0-9]+", |x| x.slice().to_string())]
|
||||||
|
NumLit(String),
|
||||||
|
#[regex(r#""(?:[^"\\]|\\.)*""#, |x| x.slice().to_string())]
|
||||||
|
StrLit(String),
|
||||||
|
|
||||||
|
|
||||||
|
#[error]
|
||||||
|
#[regex(r"[ \t\n\f]+", logos::skip)]
|
||||||
|
Error,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Eq, PartialEq, Copy, Clone)]
|
||||||
|
pub struct LexicalError(usize, usize);
|
||||||
|
|
||||||
|
impl std::fmt::Display for LexicalError {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(f, "Lexical error at {}..{}", self.0, self.1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type SpannedResult<Tok, Loc, Error> = Result<(Loc, Tok, Loc), Error>;
|
||||||
|
|
||||||
|
pub struct Lexer<'input> {
|
||||||
|
lexer: logos::SpannedIter<'input, Token>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'input> Lexer<'input> {
|
||||||
|
pub fn new(text: &'input str) -> Self {
|
||||||
|
Lexer { lexer: logos::Lexer::new(text).spanned() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'input> Iterator for Lexer<'input> {
|
||||||
|
type Item = SpannedResult<Token, usize, LexicalError>;
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
let (token, range) = self.lexer.next()?;
|
||||||
|
if token == Token::Error {
|
||||||
|
Some(Err(LexicalError(range.start, range.end)))
|
||||||
|
} else {
|
||||||
|
Some(Ok((range.start, token, range.end)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
38
src/lib.rs
38
src/lib.rs
|
@ -1,23 +1,33 @@
|
||||||
pub mod ast;
|
pub mod ast;
|
||||||
|
pub mod error;
|
||||||
|
mod lalrpop_helpers;
|
||||||
|
mod lexer;
|
||||||
|
use ast::SimplExpr;
|
||||||
|
use error::{Error, Result};
|
||||||
use lalrpop_util::lalrpop_mod;
|
use lalrpop_util::lalrpop_mod;
|
||||||
|
|
||||||
lalrpop_mod!(pub parser);
|
lalrpop_mod!(pub parser);
|
||||||
|
|
||||||
macro_rules! test_parser {
|
pub fn parse_string(s: &str) -> Result<SimplExpr> {
|
||||||
($($text:literal),*) => {{
|
let lexer = lexer::Lexer::new(s);
|
||||||
let p = crate::parser::ExprParser::new();
|
let parser = parser::ExprParser::new();
|
||||||
//use crate::lexer::Lexer;
|
Ok(parser.parse(lexer).map_err(|e| Error::from_parse_error(e))?)
|
||||||
|
|
||||||
::insta::with_settings!({sort_maps => true}, {
|
|
||||||
$(
|
|
||||||
::insta::assert_debug_snapshot!(p.parse($text));
|
|
||||||
)*
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
macro_rules! test_parser {
|
||||||
|
($($text:literal),* $(,)?) => {{
|
||||||
|
let p = crate::parser::ExprParser::new();
|
||||||
|
use crate::lexer::Lexer;
|
||||||
|
::insta::with_settings!({sort_maps => true}, {
|
||||||
|
$(
|
||||||
|
::insta::assert_debug_snapshot!(p.parse(Lexer::new($text)));
|
||||||
|
)*
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test() {
|
fn test() {
|
||||||
test_parser!(
|
test_parser!(
|
||||||
|
@ -29,7 +39,11 @@ mod tests {
|
||||||
"1 + true ? 2 : 5 + 2",
|
"1 + true ? 2 : 5 + 2",
|
||||||
"1 + (true ? 2 : 5) + 2",
|
"1 + (true ? 2 : 5) + 2",
|
||||||
"foo(1, 2)",
|
"foo(1, 2)",
|
||||||
"! false || ! true"
|
"! false || ! true",
|
||||||
|
"\"foo\" + 12.4",
|
||||||
|
"hi[\"ho\"]",
|
||||||
|
"foo.bar.baz",
|
||||||
|
"foo.bar[2 + 2] * asdf[foo.bar]",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,50 @@
|
||||||
|
|
||||||
use crate::ast::{SimplExpr, Span, BinOp, UnaryOp};
|
use crate::ast::{SimplExpr::{self, *}, Span, BinOp::*, UnaryOp::*};
|
||||||
|
use crate::lexer::{Token, LexicalError};
|
||||||
|
use crate::lalrpop_helpers::*;
|
||||||
|
|
||||||
|
|
||||||
grammar;
|
grammar;
|
||||||
|
|
||||||
|
extern {
|
||||||
|
type Location = usize;
|
||||||
|
type Error = LexicalError;
|
||||||
|
|
||||||
|
enum Token {
|
||||||
|
"+" => Token::Plus,
|
||||||
|
"-" => Token::Minus,
|
||||||
|
"*" => Token::Times,
|
||||||
|
"/" => Token::Div,
|
||||||
|
"%" => Token::Mod,
|
||||||
|
"==" => Token::Equals,
|
||||||
|
"!=" => Token::NotEquals,
|
||||||
|
"&&" => Token::And,
|
||||||
|
"||" => Token::Or,
|
||||||
|
">" => Token::GT,
|
||||||
|
"<" => Token::LT,
|
||||||
|
"?:" => Token::Elvis,
|
||||||
|
"=~" => Token::RegexMatch,
|
||||||
|
|
||||||
|
"!" => Token::Not,
|
||||||
|
|
||||||
|
"," => Token::Comma,
|
||||||
|
"?" => Token::Question,
|
||||||
|
":" => Token::Colon,
|
||||||
|
"(" => Token::LPren,
|
||||||
|
")" => Token::RPren,
|
||||||
|
"[" => Token::LBrack,
|
||||||
|
"]" => Token::RBrack,
|
||||||
|
"." => Token::Dot,
|
||||||
|
"true" => Token::True,
|
||||||
|
"false" => Token::False,
|
||||||
|
|
||||||
|
"identifier" => Token::Ident(<String>),
|
||||||
|
"number" => Token::NumLit(<String>),
|
||||||
|
"string" => Token::StrLit(<String>),
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Comma<T>: Vec<T> = {
|
Comma<T>: Vec<T> = {
|
||||||
<mut v:(<T> ",")*> <e:T?> => match e {
|
<mut v:(<T> ",")*> <e:T?> => match e {
|
||||||
None => v,
|
None => v,
|
||||||
|
@ -15,43 +57,57 @@ Comma<T>: Vec<T> = {
|
||||||
|
|
||||||
pub Expr: SimplExpr = {
|
pub Expr: SimplExpr = {
|
||||||
#[precedence(level="0")]
|
#[precedence(level="0")]
|
||||||
"true" => SimplExpr::Literal("true".to_string()),
|
<Literal>,
|
||||||
"false" => SimplExpr::Literal("false".to_string()),
|
<l:@L> <ident:"identifier"> <r:@R> => VarRef(Span(l, r), ident.to_string()),
|
||||||
<Number>,
|
|
||||||
"(" <ExprReset> ")",
|
"(" <ExprReset> ")",
|
||||||
<ident:Ident> "(" <args: Comma<ExprReset>> ")" => SimplExpr::FunctionCall(ident, args),
|
|
||||||
|
|
||||||
|
#[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)),
|
||||||
|
|
||||||
#[precedence(level="1")] #[assoc(side="left")]
|
<l:@L> <value:Expr> "." <lit_l:@L> <index:"identifier"> <r:@R> => {
|
||||||
"!" <Expr> => SimplExpr::UnaryOp(UnaryOp::Not, Box::new(<>))
|
JsonAccess(Span(l, r), b(value), b(Literal(Span(lit_l, r), index)))
|
||||||
|
},
|
||||||
|
|
||||||
|
#[precedence(level="2")] #[assoc(side="right")]
|
||||||
#[precedence(level="2")] #[assoc(side="left")]
|
<l:@L> "!" <e:Expr> <r:@R> => UnaryOp(Span(l, r), Not, b(e)),
|
||||||
<l:Expr> "*" <r:Expr> => SimplExpr::BinOp(Box::new(l), BinOp::Times, Box::new(r)),
|
|
||||||
<l:Expr> "/" <r:Expr> => SimplExpr::BinOp(Box::new(l), BinOp::Div, Box::new(r)),
|
|
||||||
<l:Expr> "%" <r:Expr> => SimplExpr::BinOp(Box::new(l), BinOp::Mod, Box::new(r)),
|
|
||||||
|
|
||||||
#[precedence(level="3")] #[assoc(side="left")]
|
#[precedence(level="3")] #[assoc(side="left")]
|
||||||
<l:Expr> "+" <r:Expr> => SimplExpr::BinOp(Box::new(l), BinOp::Plus, Box::new(r)),
|
<l:@L> <le:Expr> "*" <re:Expr> <r:@R> => BinOp(Span(l, r), b(le), Times, b(re)),
|
||||||
<l:Expr> "-" <r:Expr> => SimplExpr::BinOp(Box::new(l), BinOp::Minus, Box::new(r)),
|
<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)),
|
||||||
|
|
||||||
#[precedence(level="4")] #[assoc(side="left")]
|
#[precedence(level="4")] #[assoc(side="left")]
|
||||||
<l:Expr> "==" <r:Expr> => SimplExpr::BinOp(Box::new(l), BinOp::Equals, Box::new(r)),
|
<l:@L> <le:Expr> "+" <re:Expr> <r:@R> => BinOp(Span(l, r), b(le), Plus, b(re)),
|
||||||
<l:Expr> "!=" <r:Expr> => SimplExpr::BinOp(Box::new(l), BinOp::NotEquals, Box::new(r)),
|
<l:@L> <le:Expr> "-" <re:Expr> <r:@R> => BinOp(Span(l, r), b(le), Minus, b(re)),
|
||||||
<l:Expr> "<" <r:Expr> => SimplExpr::BinOp(Box::new(l), BinOp::GT, Box::new(r)),
|
|
||||||
<l:Expr> ">" <r:Expr> => SimplExpr::BinOp(Box::new(l), BinOp::LT, Box::new(r)),
|
|
||||||
<l:Expr> "=~" <r:Expr> => SimplExpr::BinOp(Box::new(l), BinOp::RegexMatch, Box::new(r)),
|
|
||||||
|
|
||||||
#[precedence(level="5")] #[assoc(side="left")]
|
#[precedence(level="5")] #[assoc(side="left")]
|
||||||
<l:Expr> "&&" <r:Expr> => SimplExpr::BinOp(Box::new(l), BinOp::And, Box::new(r)),
|
<l:@L> <le:Expr> "==" <re:Expr> <r:@R> => BinOp(Span(l, r), b(le), Equals, b(re)),
|
||||||
<l:Expr> "||" <r:Expr> => SimplExpr::BinOp(Box::new(l), BinOp::Or, Box::new(r)),
|
<l:@L> <le:Expr> "!=" <re:Expr> <r:@R> => BinOp(Span(l, r), b(le), NotEquals, b(re)),
|
||||||
<l:Expr> "?:" <r:Expr> => SimplExpr::BinOp(Box::new(l), BinOp::Elvis, Box::new(r)),
|
<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)),
|
||||||
|
|
||||||
#[precedence(level="6")] #[assoc(side="right")]
|
#[precedence(level="6")] #[assoc(side="left")]
|
||||||
<cond:Expr> "?" <then:ExprReset> ":" <els:Expr> => SimplExpr::IfElse(Box::new(cond), Box::new(then), Box::new(els)),
|
<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)),
|
||||||
|
|
||||||
|
#[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))
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
ExprReset = <Expr>;
|
ExprReset = <Expr>;
|
||||||
|
|
||||||
Number: SimplExpr = r"[+-]?(?:[0-9]+[.])?[0-9]+" => SimplExpr::Literal(<>.to_string());
|
Literal: SimplExpr = {
|
||||||
Ident: String = r"[a-zA-Z_][^\s{}\(\)]*" => <>.to_string();
|
<l:@L> <x:StrLit> <r:@R> => Literal(Span(l, r), x),
|
||||||
|
<l:@L> <x:"number"> <r:@R> => Literal(Span(l, r), x.to_string()),
|
||||||
|
<l:@L> "true" <r:@R> => Literal(Span(l, r), "true".to_string()),
|
||||||
|
<l:@L> "false" <r:@R> => Literal(Span(l, r), "false".to_string()),
|
||||||
|
}
|
||||||
|
|
||||||
|
StrLit: String = {
|
||||||
|
<x:"string"> => x[1..x.len() - 1].to_owned(),
|
||||||
|
};
|
||||||
|
|
8
src/snapshots/simplexpr__tests__test-10.snap
Normal file
8
src/snapshots/simplexpr__tests__test-10.snap
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
---
|
||||||
|
source: src/lib.rs
|
||||||
|
expression: "p.parse(Lexer::new(\"\\\"foo\\\" + 12.4\"))"
|
||||||
|
|
||||||
|
---
|
||||||
|
Ok(
|
||||||
|
("foo" + "12.4"),
|
||||||
|
)
|
8
src/snapshots/simplexpr__tests__test-11.snap
Normal file
8
src/snapshots/simplexpr__tests__test-11.snap
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
---
|
||||||
|
source: src/lib.rs
|
||||||
|
expression: "p.parse(Lexer::new(\"hi[\\\"ho\\\"]\"))"
|
||||||
|
|
||||||
|
---
|
||||||
|
Ok(
|
||||||
|
hi["ho"],
|
||||||
|
)
|
8
src/snapshots/simplexpr__tests__test-12.snap
Normal file
8
src/snapshots/simplexpr__tests__test-12.snap
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
---
|
||||||
|
source: src/lib.rs
|
||||||
|
expression: "p.parse(Lexer::new(\"foo.bar.baz\"))"
|
||||||
|
|
||||||
|
---
|
||||||
|
Ok(
|
||||||
|
foo["bar"]["baz"],
|
||||||
|
)
|
8
src/snapshots/simplexpr__tests__test-13.snap
Normal file
8
src/snapshots/simplexpr__tests__test-13.snap
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
---
|
||||||
|
source: src/lib.rs
|
||||||
|
expression: "p.parse(Lexer::new(\"foo.bar[2 + 2] * asdf[foo.bar]\"))"
|
||||||
|
|
||||||
|
---
|
||||||
|
Ok(
|
||||||
|
(foo["bar"][("2" + "2")] * asdf[foo["bar"]]),
|
||||||
|
)
|
30
src/snapshots/simplexpr__tests__test-14.snap
Normal file
30
src/snapshots/simplexpr__tests__test-14.snap
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
---
|
||||||
|
source: src/lib.rs
|
||||||
|
expression: "p.parse(Lexer::new(\"1 + (true ? 2 : 5) + 2\"))"
|
||||||
|
|
||||||
|
---
|
||||||
|
Ok(
|
||||||
|
BinOp(
|
||||||
|
BinOp(
|
||||||
|
Literal(
|
||||||
|
"1",
|
||||||
|
),
|
||||||
|
Plus,
|
||||||
|
IfElse(
|
||||||
|
Literal(
|
||||||
|
"true",
|
||||||
|
),
|
||||||
|
Literal(
|
||||||
|
"2",
|
||||||
|
),
|
||||||
|
Literal(
|
||||||
|
"5",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Plus,
|
||||||
|
Literal(
|
||||||
|
"2",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
13
src/snapshots/simplexpr__tests__test-15.snap
Normal file
13
src/snapshots/simplexpr__tests__test-15.snap
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
---
|
||||||
|
source: src/lib.rs
|
||||||
|
expression: "Lexer::new(\"foo(1, 2)\").filter_map(|x|\n x.ok()).map(|(_, x, _)|\n match x {\n Token::Ident(x) |\n Token::NumLit(x) |\n Token::StrLit(x) =>\n format!(\"{}\", x),\n x =>\n format!(\"{}\", x),\n }).collect::<Vec<_>>()"
|
||||||
|
|
||||||
|
---
|
||||||
|
[
|
||||||
|
"foo",
|
||||||
|
"LPren",
|
||||||
|
"1",
|
||||||
|
"Comma",
|
||||||
|
"2",
|
||||||
|
"RPren",
|
||||||
|
]
|
18
src/snapshots/simplexpr__tests__test-16.snap
Normal file
18
src/snapshots/simplexpr__tests__test-16.snap
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
---
|
||||||
|
source: src/lib.rs
|
||||||
|
expression: "p.parse(Lexer::new(\"foo(1, 2)\"))"
|
||||||
|
|
||||||
|
---
|
||||||
|
Ok(
|
||||||
|
FunctionCall(
|
||||||
|
"foo",
|
||||||
|
[
|
||||||
|
Literal(
|
||||||
|
"1",
|
||||||
|
),
|
||||||
|
Literal(
|
||||||
|
"2",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
)
|
12
src/snapshots/simplexpr__tests__test-17.snap
Normal file
12
src/snapshots/simplexpr__tests__test-17.snap
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
---
|
||||||
|
source: src/lib.rs
|
||||||
|
expression: "Lexer::new(\"! false || ! true\").filter_map(|x|\n x.ok()).map(|(_, x, _)|\n match x {\n Token::Ident(x)\n |\n Token::NumLit(x)\n |\n Token::StrLit(x)\n =>\n format!(\"{}\",\n x),\n x =>\n format!(\"{}\",\n x),\n }).collect::<Vec<_>>()"
|
||||||
|
|
||||||
|
---
|
||||||
|
[
|
||||||
|
"!",
|
||||||
|
"False",
|
||||||
|
"||",
|
||||||
|
"!",
|
||||||
|
"True",
|
||||||
|
]
|
22
src/snapshots/simplexpr__tests__test-18.snap
Normal file
22
src/snapshots/simplexpr__tests__test-18.snap
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
---
|
||||||
|
source: src/lib.rs
|
||||||
|
expression: "p.parse(Lexer::new(\"! false || ! true\"))"
|
||||||
|
|
||||||
|
---
|
||||||
|
Ok(
|
||||||
|
BinOp(
|
||||||
|
UnaryOp(
|
||||||
|
Not,
|
||||||
|
Literal(
|
||||||
|
"false",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Or,
|
||||||
|
UnaryOp(
|
||||||
|
Not,
|
||||||
|
Literal(
|
||||||
|
"true",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
10
src/snapshots/simplexpr__tests__test-19.snap
Normal file
10
src/snapshots/simplexpr__tests__test-19.snap
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
---
|
||||||
|
source: src/lib.rs
|
||||||
|
expression: "Lexer::new(\"\\\"foo\\\" + 12.4\").filter_map(|x|\n x.ok()).map(|(_, x, _)|\n match x {\n Token::Ident(x)\n |\n Token::NumLit(x)\n |\n Token::StrLit(x)\n =>\n format!(\"{}\",\n x),\n x =>\n format!(\"{}\",\n x),\n }).collect::<Vec<_>>()"
|
||||||
|
|
||||||
|
---
|
||||||
|
[
|
||||||
|
"\"foo\"",
|
||||||
|
"+",
|
||||||
|
"12.4",
|
||||||
|
]
|
|
@ -1,16 +1,8 @@
|
||||||
---
|
---
|
||||||
source: src/lib.rs
|
source: src/lib.rs
|
||||||
expression: "p.parse(\"2 + 5\")"
|
expression: "p.parse(Lexer::new(\"2 + 5\"))"
|
||||||
|
|
||||||
---
|
---
|
||||||
Ok(
|
Ok(
|
||||||
BinOp(
|
("2" + "5"),
|
||||||
Literal(
|
|
||||||
"2",
|
|
||||||
),
|
|
||||||
Plus,
|
|
||||||
Literal(
|
|
||||||
"5",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
|
16
src/snapshots/simplexpr__tests__test-20.snap
Normal file
16
src/snapshots/simplexpr__tests__test-20.snap
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
---
|
||||||
|
source: src/lib.rs
|
||||||
|
expression: "p.parse(Lexer::new(\"\\\"foo\\\" + 12.4\"))"
|
||||||
|
|
||||||
|
---
|
||||||
|
Ok(
|
||||||
|
BinOp(
|
||||||
|
Literal(
|
||||||
|
"foo",
|
||||||
|
),
|
||||||
|
Plus,
|
||||||
|
Literal(
|
||||||
|
"12.4",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
11
src/snapshots/simplexpr__tests__test-21.snap
Normal file
11
src/snapshots/simplexpr__tests__test-21.snap
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
---
|
||||||
|
source: src/lib.rs
|
||||||
|
expression: "Lexer::new(\"hi[\\\"ho\\\"]\").filter_map(|x|\n x.ok()).map(|(_, x, _)|\n match x {\n Token::Ident(x) |\n Token::NumLit(x) |\n Token::StrLit(x)\n =>\n format!(\"{}\", x),\n x =>\n format!(\"{}\", x),\n }).collect::<Vec<_>>()"
|
||||||
|
|
||||||
|
---
|
||||||
|
[
|
||||||
|
"hi",
|
||||||
|
"LBrack",
|
||||||
|
"\"ho\"",
|
||||||
|
"RBrack",
|
||||||
|
]
|
15
src/snapshots/simplexpr__tests__test-22.snap
Normal file
15
src/snapshots/simplexpr__tests__test-22.snap
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
---
|
||||||
|
source: src/lib.rs
|
||||||
|
expression: "p.parse(Lexer::new(\"hi[\\\"ho\\\"]\"))"
|
||||||
|
|
||||||
|
---
|
||||||
|
Ok(
|
||||||
|
JsonAccess(
|
||||||
|
VarRef(
|
||||||
|
"hi",
|
||||||
|
),
|
||||||
|
Literal(
|
||||||
|
"ho",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
12
src/snapshots/simplexpr__tests__test-23.snap
Normal file
12
src/snapshots/simplexpr__tests__test-23.snap
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
---
|
||||||
|
source: src/lib.rs
|
||||||
|
expression: "Lexer::new(\"foo.bar.baz\").filter_map(|x|\n x.ok()).map(|(_, x, _)|\n match x {\n Token::Ident(x) |\n Token::NumLit(x)\n |\n Token::StrLit(x)\n =>\n format!(\"{}\", x),\n x =>\n format!(\"{}\", x),\n }).collect::<Vec<_>>()"
|
||||||
|
|
||||||
|
---
|
||||||
|
[
|
||||||
|
"foo",
|
||||||
|
"Dot",
|
||||||
|
"bar",
|
||||||
|
"Dot",
|
||||||
|
"baz",
|
||||||
|
]
|
20
src/snapshots/simplexpr__tests__test-24.snap
Normal file
20
src/snapshots/simplexpr__tests__test-24.snap
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
---
|
||||||
|
source: src/lib.rs
|
||||||
|
expression: "p.parse(Lexer::new(\"foo.bar.baz\"))"
|
||||||
|
|
||||||
|
---
|
||||||
|
Ok(
|
||||||
|
JsonAccess(
|
||||||
|
JsonAccess(
|
||||||
|
VarRef(
|
||||||
|
"foo",
|
||||||
|
),
|
||||||
|
Literal(
|
||||||
|
"bar",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Literal(
|
||||||
|
"baz",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
22
src/snapshots/simplexpr__tests__test-25.snap
Normal file
22
src/snapshots/simplexpr__tests__test-25.snap
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
---
|
||||||
|
source: src/lib.rs
|
||||||
|
expression: "Lexer::new(\"foo.bar[2 + 2] * asdf[foo.bar]\").filter_map(|x|\n x.ok()).map(|(_,\n x,\n _)|\n match x\n {\n Token::Ident(x)\n |\n Token::NumLit(x)\n |\n Token::StrLit(x)\n =>\n format!(\"{}\",\n x),\n x\n =>\n format!(\"{}\",\n x),\n }).collect::<Vec<_>>()"
|
||||||
|
|
||||||
|
---
|
||||||
|
[
|
||||||
|
"foo",
|
||||||
|
"Dot",
|
||||||
|
"bar",
|
||||||
|
"LBrack",
|
||||||
|
"2",
|
||||||
|
"+",
|
||||||
|
"2",
|
||||||
|
"RBrack",
|
||||||
|
"*",
|
||||||
|
"asdf",
|
||||||
|
"LBrack",
|
||||||
|
"foo",
|
||||||
|
"Dot",
|
||||||
|
"bar",
|
||||||
|
"RBrack",
|
||||||
|
]
|
42
src/snapshots/simplexpr__tests__test-26.snap
Normal file
42
src/snapshots/simplexpr__tests__test-26.snap
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
---
|
||||||
|
source: src/lib.rs
|
||||||
|
expression: "p.parse(Lexer::new(\"foo.bar[2 + 2] * asdf[foo.bar]\"))"
|
||||||
|
|
||||||
|
---
|
||||||
|
Ok(
|
||||||
|
BinOp(
|
||||||
|
JsonAccess(
|
||||||
|
JsonAccess(
|
||||||
|
VarRef(
|
||||||
|
"foo",
|
||||||
|
),
|
||||||
|
Literal(
|
||||||
|
"bar",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
BinOp(
|
||||||
|
Literal(
|
||||||
|
"2",
|
||||||
|
),
|
||||||
|
Plus,
|
||||||
|
Literal(
|
||||||
|
"2",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Times,
|
||||||
|
JsonAccess(
|
||||||
|
VarRef(
|
||||||
|
"asdf",
|
||||||
|
),
|
||||||
|
JsonAccess(
|
||||||
|
VarRef(
|
||||||
|
"foo",
|
||||||
|
),
|
||||||
|
Literal(
|
||||||
|
"bar",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
|
@ -1,34 +1,8 @@
|
||||||
---
|
---
|
||||||
source: src/lib.rs
|
source: src/lib.rs
|
||||||
expression: "p.parse(\"2 * 5 + 1 * 1 + 3\")"
|
expression: "p.parse(Lexer::new(\"2 * 5 + 1 * 1 + 3\"))"
|
||||||
|
|
||||||
---
|
---
|
||||||
Ok(
|
Ok(
|
||||||
BinOp(
|
((("2" * "5") + ("1" * "1")) + "3"),
|
||||||
BinOp(
|
|
||||||
BinOp(
|
|
||||||
Literal(
|
|
||||||
"2",
|
|
||||||
),
|
|
||||||
Times,
|
|
||||||
Literal(
|
|
||||||
"5",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Plus,
|
|
||||||
BinOp(
|
|
||||||
Literal(
|
|
||||||
"1",
|
|
||||||
),
|
|
||||||
Times,
|
|
||||||
Literal(
|
|
||||||
"1",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Plus,
|
|
||||||
Literal(
|
|
||||||
"3",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,22 +1,8 @@
|
||||||
---
|
---
|
||||||
source: src/lib.rs
|
source: src/lib.rs
|
||||||
expression: "p.parse(\"(1 + 2) * 2\")"
|
expression: "p.parse(Lexer::new(\"(1 + 2) * 2\"))"
|
||||||
|
|
||||||
---
|
---
|
||||||
Ok(
|
Ok(
|
||||||
BinOp(
|
(("1" + "2") * "2"),
|
||||||
BinOp(
|
|
||||||
Literal(
|
|
||||||
"1",
|
|
||||||
),
|
|
||||||
Plus,
|
|
||||||
Literal(
|
|
||||||
"2",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Times,
|
|
||||||
Literal(
|
|
||||||
"2",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,24 +1,8 @@
|
||||||
---
|
---
|
||||||
source: src/lib.rs
|
source: src/lib.rs
|
||||||
expression: "p.parse(\"1 + true ? 2 : 5\")"
|
expression: "p.parse(Lexer::new(\"1 + true ? 2 : 5\"))"
|
||||||
|
|
||||||
---
|
---
|
||||||
Ok(
|
Ok(
|
||||||
IfElse(
|
(if ("1" + "true") then "2" else "5"),
|
||||||
BinOp(
|
|
||||||
Literal(
|
|
||||||
"1",
|
|
||||||
),
|
|
||||||
Plus,
|
|
||||||
Literal(
|
|
||||||
"true",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Literal(
|
|
||||||
"2",
|
|
||||||
),
|
|
||||||
Literal(
|
|
||||||
"5",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,30 +1,8 @@
|
||||||
---
|
---
|
||||||
source: src/lib.rs
|
source: src/lib.rs
|
||||||
expression: "p.parse(\"1 + true ? 2 : 5 + 2\")"
|
expression: "p.parse(Lexer::new(\"1 + true ? 2 : 5 + 2\"))"
|
||||||
|
|
||||||
---
|
---
|
||||||
Ok(
|
Ok(
|
||||||
IfElse(
|
(if ("1" + "true") then "2" else ("5" + "2")),
|
||||||
BinOp(
|
|
||||||
Literal(
|
|
||||||
"1",
|
|
||||||
),
|
|
||||||
Plus,
|
|
||||||
Literal(
|
|
||||||
"true",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Literal(
|
|
||||||
"2",
|
|
||||||
),
|
|
||||||
BinOp(
|
|
||||||
Literal(
|
|
||||||
"5",
|
|
||||||
),
|
|
||||||
Plus,
|
|
||||||
Literal(
|
|
||||||
"2",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,30 +1,8 @@
|
||||||
---
|
---
|
||||||
source: src/lib.rs
|
source: src/lib.rs
|
||||||
expression: "p.parse(\"1 + (if true then 2 else 5) + 2\")"
|
expression: "p.parse(Lexer::new(\"1 + (true ? 2 : 5) + 2\"))"
|
||||||
|
|
||||||
---
|
---
|
||||||
Ok(
|
Ok(
|
||||||
BinOp(
|
(("1" + (if "true" then "2" else "5")) + "2"),
|
||||||
BinOp(
|
|
||||||
Literal(
|
|
||||||
"1",
|
|
||||||
),
|
|
||||||
Plus,
|
|
||||||
IfElse(
|
|
||||||
Literal(
|
|
||||||
"true",
|
|
||||||
),
|
|
||||||
Literal(
|
|
||||||
"2",
|
|
||||||
),
|
|
||||||
Literal(
|
|
||||||
"5",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Plus,
|
|
||||||
Literal(
|
|
||||||
"2",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,18 +1,8 @@
|
||||||
---
|
---
|
||||||
source: src/lib.rs
|
source: src/lib.rs
|
||||||
expression: "p.parse(\"foo(1, 2)\")"
|
expression: "p.parse(Lexer::new(\"foo(1, 2)\"))"
|
||||||
|
|
||||||
---
|
---
|
||||||
Ok(
|
Ok(
|
||||||
FunctionCall(
|
foo("1", "2"),
|
||||||
"foo",
|
|
||||||
[
|
|
||||||
Literal(
|
|
||||||
"1",
|
|
||||||
),
|
|
||||||
Literal(
|
|
||||||
"2",
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
|
8
src/snapshots/simplexpr__tests__test-9.snap
Normal file
8
src/snapshots/simplexpr__tests__test-9.snap
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
---
|
||||||
|
source: src/lib.rs
|
||||||
|
expression: "p.parse(Lexer::new(\"! false || ! true\"))"
|
||||||
|
|
||||||
|
---
|
||||||
|
Ok(
|
||||||
|
(!"false" || !"true"),
|
||||||
|
)
|
|
@ -1,10 +1,8 @@
|
||||||
---
|
---
|
||||||
source: src/lib.rs
|
source: src/lib.rs
|
||||||
expression: "p.parse(\"1\")"
|
expression: "p.parse(Lexer::new(\"1\"))"
|
||||||
|
|
||||||
---
|
---
|
||||||
Ok(
|
Ok(
|
||||||
Literal(
|
"1",
|
||||||
"1",
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
|
Loading…
Add table
Reference in a new issue