Fix fields being parsed as idioms. (#4819)

This commit is contained in:
Mees Delzenne 2024-09-18 17:50:44 +02:00 committed by GitHub
parent 5867ce95d9
commit 52aef7ccc4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
13 changed files with 100 additions and 85 deletions

View file

@ -64,7 +64,7 @@ pub fn value(input: &str) -> Result<Value, Error> {
.with_query_recursion_limit(*MAX_QUERY_PARSING_DEPTH as usize); .with_query_recursion_limit(*MAX_QUERY_PARSING_DEPTH as usize);
let mut stack = Stack::new(); let mut stack = Stack::new();
stack stack
.enter(|stk| parser.parse_value_table(stk)) .enter(|stk| parser.parse_value_field(stk))
.finish() .finish()
.and_then(|e| parser.assert_finished().map(|_| e)) .and_then(|e| parser.assert_finished().map(|_| e))
.map_err(|e| e.render_on(input)) .map_err(|e| e.render_on(input))
@ -211,7 +211,7 @@ pub fn value_legacy_strand(input: &str) -> Result<Value, Error> {
let mut stack = Stack::new(); let mut stack = Stack::new();
parser.allow_legacy_strand(true); parser.allow_legacy_strand(true);
stack stack
.enter(|stk| parser.parse_value_table(stk)) .enter(|stk| parser.parse_value_field(stk))
.finish() .finish()
.and_then(|e| parser.assert_finished().map(|_| e)) .and_then(|e| parser.assert_finished().map(|_| e))
.map_err(|e| e.render_on(input)) .map_err(|e| e.render_on(input))

View file

@ -188,6 +188,7 @@ impl Parser<'_> {
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use crate::sql::{Ident, Part};
#[test] #[test]
fn identifiers() { fn identifiers() {
@ -206,8 +207,8 @@ mod test {
assert_eq!( assert_eq!(
r, r,
sql::Query(sql::Statements(vec![sql::Statement::Value(sql::Value::Table( sql::Query(sql::Statements(vec![sql::Statement::Value(sql::Value::Idiom(
sql::Table(ident.to_string()) sql::Idiom(vec![Part::Field(Ident(ident.to_string()))])
))])) ))]))
) )
} }

View file

@ -134,7 +134,7 @@ impl<'a> Parser<'a> {
last_span: Span::empty(), last_span: Span::empty(),
token_buffer: TokenBuffer::new(), token_buffer: TokenBuffer::new(),
glued_value: GluedValue::None, glued_value: GluedValue::None,
table_as_field: false, table_as_field: true,
legacy_strands: false, legacy_strands: false,
flexible_record_id: true, flexible_record_id: true,
object_recursion: 100, object_recursion: 100,
@ -180,7 +180,7 @@ impl<'a> Parser<'a> {
pub fn reset(&mut self) { pub fn reset(&mut self) {
self.last_span = Span::empty(); self.last_span = Span::empty();
self.token_buffer.clear(); self.token_buffer.clear();
self.table_as_field = false; self.table_as_field = true;
self.lexer.reset(); self.lexer.reset();
} }

View file

@ -335,12 +335,12 @@ impl Parser<'_> {
t!("SIGNUP") => { t!("SIGNUP") => {
self.pop_peek(); self.pop_peek();
ac.signup = ac.signup =
Some(stk.run(|stk| self.parse_value_table(stk)).await?); Some(stk.run(|stk| self.parse_value_field(stk)).await?);
} }
t!("SIGNIN") => { t!("SIGNIN") => {
self.pop_peek(); self.pop_peek();
ac.signin = ac.signin =
Some(stk.run(|stk| self.parse_value_table(stk)).await?); Some(stk.run(|stk| self.parse_value_field(stk)).await?);
} }
_ => break, _ => break,
} }
@ -375,7 +375,7 @@ impl Parser<'_> {
} }
t!("AUTHENTICATE") => { t!("AUTHENTICATE") => {
self.pop_peek(); self.pop_peek();
res.authenticate = Some(stk.run(|stk| self.parse_value_table(stk)).await?); res.authenticate = Some(stk.run(|stk| self.parse_value_field(stk)).await?);
} }
t!("DURATION") => { t!("DURATION") => {
self.pop_peek(); self.pop_peek();
@ -581,11 +581,11 @@ impl Parser<'_> {
} }
t!("SIGNUP") => { t!("SIGNUP") => {
self.pop_peek(); self.pop_peek();
ac.signup = Some(stk.run(|stk| self.parse_value_table(stk)).await?); ac.signup = Some(stk.run(|stk| self.parse_value_field(stk)).await?);
} }
t!("SIGNIN") => { t!("SIGNIN") => {
self.pop_peek(); self.pop_peek();
ac.signin = Some(stk.run(|stk| self.parse_value_table(stk)).await?); ac.signin = Some(stk.run(|stk| self.parse_value_field(stk)).await?);
} }
_ => break, _ => break,
} }
@ -619,7 +619,7 @@ impl Parser<'_> {
match self.peek_kind() { match self.peek_kind() {
t!("VALUE") => { t!("VALUE") => {
self.pop_peek(); self.pop_peek();
res.value = ctx.run(|ctx| self.parse_value_table(ctx)).await?; res.value = ctx.run(|ctx| self.parse_value_field(ctx)).await?;
} }
t!("COMMENT") => { t!("COMMENT") => {
self.pop_peek(); self.pop_peek();
@ -758,13 +758,13 @@ impl Parser<'_> {
match self.peek_kind() { match self.peek_kind() {
t!("WHEN") => { t!("WHEN") => {
self.pop_peek(); self.pop_peek();
res.when = ctx.run(|ctx| self.parse_value_table(ctx)).await?; res.when = ctx.run(|ctx| self.parse_value_field(ctx)).await?;
} }
t!("THEN") => { t!("THEN") => {
self.pop_peek(); self.pop_peek();
res.then = Values(vec![ctx.run(|ctx| self.parse_value_table(ctx)).await?]); res.then = Values(vec![ctx.run(|ctx| self.parse_value_field(ctx)).await?]);
while self.eat(t!(",")) { while self.eat(t!(",")) {
res.then.0.push(ctx.run(|ctx| self.parse_value_table(ctx)).await?) res.then.0.push(ctx.run(|ctx| self.parse_value_field(ctx)).await?)
} }
} }
t!("COMMENT") => { t!("COMMENT") => {

View file

@ -129,7 +129,7 @@ impl Parser<'_> {
let mut values = Vec::new(); let mut values = Vec::new();
let start = expected!(self, t!("(")).span; let start = expected!(self, t!("(")).span;
loop { loop {
values.push(self.parse_value_table(ctx).await?); values.push(self.parse_value_field(ctx).await?);
if !self.eat(t!(",")) { if !self.eat(t!(",")) {
break; break;

View file

@ -214,7 +214,7 @@ impl Parser<'_> {
} }
_ => { _ => {
// TODO: Provide information about keywords. // TODO: Provide information about keywords.
let value = ctx.run(|ctx| self.parse_value_table(ctx)).await?; let value = ctx.run(|ctx| self.parse_value_field(ctx)).await?;
Ok(Self::refine_stmt_value(value)) Ok(Self::refine_stmt_value(value))
} }
} }

View file

@ -75,6 +75,14 @@ impl Parser<'_> {
} }
} }
pub async fn parse_relate_value(&mut self, ctx: &mut Stk) -> ParseResult<Value> { pub async fn parse_relate_value(&mut self, ctx: &mut Stk) -> ParseResult<Value> {
let old = self.table_as_field;
self.table_as_field = true;
let r = self.parse_relate_value_inner(ctx).await;
self.table_as_field = old;
r
}
async fn parse_relate_value_inner(&mut self, ctx: &mut Stk) -> ParseResult<Value> {
match self.peek_kind() { match self.peek_kind() {
t!("[") => { t!("[") => {
let start = self.pop_peek().span; let start = self.pop_peek().span;

View file

@ -1,5 +1,5 @@
use crate::{ use crate::{
sql::{self, Id, Statement, Thing, Value}, sql::{self, Id, Ident, Idiom, Part, Query, Statement, Statements, Thing, Value},
syn::parser::mac::test_parse, syn::parser::mac::test_parse,
}; };
@ -83,6 +83,20 @@ fn query_object() {
test_parse!(parse_query, src).inspect_err(|e| eprintln!("{}", e.render_on(src))).unwrap(); test_parse!(parse_query, src).inspect_err(|e| eprintln!("{}", e.render_on(src))).unwrap();
} }
#[test]
fn ident_is_field() {
let src = r#"foo"#;
let field =
test_parse!(parse_query, src).inspect_err(|e| eprintln!("{}", e.render_on(src))).unwrap();
assert_eq!(
field,
Query(Statements(vec![Statement::Value(Value::Idiom(Idiom(vec![Part::Field(Ident(
"foo".to_string()
))])))]))
);
}
#[test] #[test]
fn escaped_params_backtick() { fn escaped_params_backtick() {
test_parse!( test_parse!(

View file

@ -41,6 +41,10 @@ use crate::{
}; };
use chrono::{offset::TimeZone, NaiveDate, Offset, Utc}; use chrono::{offset::TimeZone, NaiveDate, Offset, Utc};
fn ident_field(name: &str) -> Value {
Value::Idiom(Idiom(vec![Part::Field(Ident(name.to_string()))]))
}
#[test] #[test]
pub fn parse_analyze() { pub fn parse_analyze() {
let res = test_parse!(parse_stmt, r#"ANALYZE INDEX b on a"#).unwrap(); let res = test_parse!(parse_stmt, r#"ANALYZE INDEX b on a"#).unwrap();
@ -205,7 +209,7 @@ fn parse_define_function() {
(Ident("b".to_string()), Kind::Array(Box::new(Kind::Bool), Some(3))) (Ident("b".to_string()), Kind::Array(Box::new(Kind::Bool), Some(3)))
], ],
block: Block(vec![Entry::Output(OutputStatement { block: Block(vec![Entry::Output(OutputStatement {
what: Value::Table(Table("a".to_string())), what: ident_field("a"),
fetch: None, fetch: None,
})]), })]),
comment: Some(Strand("test".to_string())), comment: Some(Strand("test".to_string())),
@ -1709,10 +1713,10 @@ fn parse_if() {
res, res,
Statement::Ifelse(IfelseStatement { Statement::Ifelse(IfelseStatement {
exprs: vec![ exprs: vec![
(Value::Table(Table("foo".to_owned())), Value::Table(Table("bar".to_owned()))), (ident_field("foo"), ident_field("bar")),
(Value::Table(Table("faz".to_owned())), Value::Table(Table("baz".to_owned()))) (ident_field("faz"), ident_field("baz")),
], ],
close: Some(Value::Table(Table("baq".to_owned()))) close: Some(ident_field("baq"))
}) })
) )
} }
@ -1726,21 +1730,15 @@ fn parse_if_block() {
Statement::Ifelse(IfelseStatement { Statement::Ifelse(IfelseStatement {
exprs: vec![ exprs: vec![
( (
Value::Table(Table("foo".to_owned())), ident_field("foo"),
Value::Block(Box::new(Block(vec![Entry::Value(Value::Table(Table( Value::Block(Box::new(Block(vec![Entry::Value(ident_field("bar"))]))),
"bar".to_owned()
)),)]))),
), ),
( (
Value::Table(Table("faz".to_owned())), ident_field("faz"),
Value::Block(Box::new(Block(vec![Entry::Value(Value::Table(Table( Value::Block(Box::new(Block(vec![Entry::Value(ident_field("baz"))]))),
"baz".to_owned()
)),)]))),
) )
], ],
close: Some(Value::Block(Box::new(Block(vec![Entry::Value(Value::Table(Table( close: Some(Value::Block(Box::new(Block(vec![Entry::Value(ident_field("baq"))])))),
"baq".to_owned()
)))])))),
}) })
) )
} }
@ -2193,10 +2191,8 @@ fn parse_return() {
assert_eq!( assert_eq!(
res, res,
Statement::Output(OutputStatement { Statement::Output(OutputStatement {
what: Value::Table(Table("RETRUN".to_owned())), what: ident_field("RETRUN"),
fetch: Some(Fetchs(vec![Fetch(Value::Idiom(Idiom(vec![Part::Field( fetch: Some(Fetchs(vec![Fetch(ident_field("RETURN"))]))
Ident("RETURN".to_owned()).to_owned()
)])))])),
}), }),
) )
} }

View file

@ -31,6 +31,10 @@ use crate::{
use chrono::{offset::TimeZone, NaiveDate, Offset, Utc}; use chrono::{offset::TimeZone, NaiveDate, Offset, Utc};
use reblessive::Stack; use reblessive::Stack;
fn ident_field(name: &str) -> Value {
Value::Idiom(Idiom(vec![Part::Field(Ident(name.to_string()))]))
}
static SOURCE: &str = r#" static SOURCE: &str = r#"
ANALYZE INDEX b on a; ANALYZE INDEX b on a;
BEGIN; BEGIN;
@ -192,7 +196,7 @@ fn statements() -> Vec<Statement> {
(Ident("b".to_string()), Kind::Array(Box::new(Kind::Bool), Some(3))), (Ident("b".to_string()), Kind::Array(Box::new(Kind::Bool), Some(3))),
], ],
block: Block(vec![Entry::Output(OutputStatement { block: Block(vec![Entry::Output(OutputStatement {
what: Value::Table(Table("a".to_string())), what: ident_field("a"),
fetch: None, fetch: None,
})]), })]),
comment: Some(Strand("test".to_string())), comment: Some(Strand("test".to_string())),
@ -440,29 +444,23 @@ fn statements() -> Vec<Statement> {
}), }),
Statement::Ifelse(IfelseStatement { Statement::Ifelse(IfelseStatement {
exprs: vec![ exprs: vec![
(Value::Table(Table("foo".to_owned())), Value::Table(Table("bar".to_owned()))), (ident_field("foo"), ident_field("bar")),
(Value::Table(Table("faz".to_owned())), Value::Table(Table("baz".to_owned()))), (ident_field("faz"), ident_field("baz")),
], ],
close: Some(Value::Table(Table("baq".to_owned()))), close: Some(ident_field("baq")),
}), }),
Statement::Ifelse(IfelseStatement { Statement::Ifelse(IfelseStatement {
exprs: vec![ exprs: vec![
( (
Value::Table(Table("foo".to_owned())), ident_field("foo"),
Value::Block(Box::new(Block(vec![Entry::Value(Value::Table(Table( Value::Block(Box::new(Block(vec![Entry::Value(ident_field("bar"))]))),
"bar".to_owned(),
)))]))),
), ),
( (
Value::Table(Table("faz".to_owned())), ident_field("faz"),
Value::Block(Box::new(Block(vec![Entry::Value(Value::Table(Table( Value::Block(Box::new(Block(vec![Entry::Value(ident_field("baz"))]))),
"baz".to_owned(),
)))]))),
), ),
], ],
close: Some(Value::Block(Box::new(Block(vec![Entry::Value(Value::Table(Table( close: Some(Value::Block(Box::new(Block(vec![Entry::Value(ident_field("baq"))])))),
"baq".to_owned(),
)))])))),
}), }),
Statement::Info(InfoStatement::Root(false)), Statement::Info(InfoStatement::Root(false)),
Statement::Info(InfoStatement::Ns(false)), Statement::Info(InfoStatement::Ns(false)),
@ -606,10 +604,8 @@ fn statements() -> Vec<Statement> {
id: Value::Uuid(Uuid(uuid::uuid!("e72bee20-f49b-11ec-b939-0242ac120002"))), id: Value::Uuid(Uuid(uuid::uuid!("e72bee20-f49b-11ec-b939-0242ac120002"))),
}), }),
Statement::Output(OutputStatement { Statement::Output(OutputStatement {
what: Value::Table(Table("RETRUN".to_owned())), what: ident_field("RETRUN"),
fetch: Some(Fetchs(vec![Fetch(Value::Idiom(Idiom(vec![Part::Field( fetch: Some(Fetchs(vec![Fetch(ident_field("RETURN"))])),
Ident("RETURN".to_owned()).to_owned(),
)])))])),
}), }),
Statement::Relate(RelateStatement { Statement::Relate(RelateStatement {
only: true, only: true,

View file

@ -12,7 +12,7 @@ use crate::{
#[test] #[test]
fn parse_index_expression() { fn parse_index_expression() {
let value = test_parse!(parse_value_table, "a[1 + 1]").unwrap(); let value = test_parse!(parse_value_field, "a[1 + 1]").unwrap();
let Value::Idiom(x) = value else { let Value::Idiom(x) = value else {
panic!("not the right value type"); panic!("not the right value type");
}; };
@ -29,7 +29,7 @@ fn parse_index_expression() {
#[test] #[test]
fn parse_coordinate() { fn parse_coordinate() {
let coord = test_parse!(parse_value_table, "(1.88, -18.0)").unwrap(); let coord = test_parse!(parse_value_field, "(1.88, -18.0)").unwrap();
let Value::Geometry(Geometry::Point(x)) = coord else { let Value::Geometry(Geometry::Point(x)) = coord else {
panic!("not the right value"); panic!("not the right value");
}; };
@ -39,12 +39,12 @@ fn parse_coordinate() {
#[test] #[test]
fn parse_like_operator() { fn parse_like_operator() {
test_parse!(parse_value_table, "a ~ b").unwrap(); test_parse!(parse_value_field, "a ~ b").unwrap();
} }
#[test] #[test]
fn parse_range_operator() { fn parse_range_operator() {
test_parse!(parse_value_table, "1..2").unwrap(); test_parse!(parse_value_field, "1..2").unwrap();
} }
#[test] #[test]
@ -116,7 +116,7 @@ fn parse_large_depth_record_id() {
#[test] #[test]
fn parse_recursive_record_string() { fn parse_recursive_record_string() {
let res = test_parse!(parse_value_table, r#" r"a:[r"b:{c: r"d:1"}"]" "#).unwrap(); let res = test_parse!(parse_value_field, r#" r"a:[r"b:{c: r"d:1"}"]" "#).unwrap();
assert_eq!( assert_eq!(
res, res,
Value::Thing(Thing { Value::Thing(Thing {
@ -137,7 +137,7 @@ fn parse_recursive_record_string() {
#[test] #[test]
fn parse_record_string_2() { fn parse_record_string_2() {
let res = test_parse!(parse_value_table, r#" r'a:["foo"]' "#).unwrap(); let res = test_parse!(parse_value_field, r#" r'a:["foo"]' "#).unwrap();
assert_eq!( assert_eq!(
res, res,
Value::Thing(Thing { Value::Thing(Thing {
@ -149,82 +149,82 @@ fn parse_record_string_2() {
#[test] #[test]
fn parse_i64() { fn parse_i64() {
let res = test_parse!(parse_value_table, r#" -9223372036854775808 "#).unwrap(); let res = test_parse!(parse_value_field, r#" -9223372036854775808 "#).unwrap();
assert_eq!(res, Value::Number(Number::Int(i64::MIN))); assert_eq!(res, Value::Number(Number::Int(i64::MIN)));
let res = test_parse!(parse_value_table, r#" 9223372036854775807 "#).unwrap(); let res = test_parse!(parse_value_field, r#" 9223372036854775807 "#).unwrap();
assert_eq!(res, Value::Number(Number::Int(i64::MAX))); assert_eq!(res, Value::Number(Number::Int(i64::MAX)));
} }
#[test] #[test]
fn constant_lowercase() { fn constant_lowercase() {
let out = test_parse!(parse_value_table, r#" math::pi "#).unwrap(); let out = test_parse!(parse_value_field, r#" math::pi "#).unwrap();
assert_eq!(out, Value::Constant(Constant::MathPi)); assert_eq!(out, Value::Constant(Constant::MathPi));
let out = test_parse!(parse_value_table, r#" math::inf "#).unwrap(); let out = test_parse!(parse_value_field, r#" math::inf "#).unwrap();
assert_eq!(out, Value::Constant(Constant::MathInf)); assert_eq!(out, Value::Constant(Constant::MathInf));
let out = test_parse!(parse_value_table, r#" math::neg_inf "#).unwrap(); let out = test_parse!(parse_value_field, r#" math::neg_inf "#).unwrap();
assert_eq!(out, Value::Constant(Constant::MathNegInf)); assert_eq!(out, Value::Constant(Constant::MathNegInf));
let out = test_parse!(parse_value_table, r#" time::epoch "#).unwrap(); let out = test_parse!(parse_value_field, r#" time::epoch "#).unwrap();
assert_eq!(out, Value::Constant(Constant::TimeEpoch)); assert_eq!(out, Value::Constant(Constant::TimeEpoch));
} }
#[test] #[test]
fn constant_uppercase() { fn constant_uppercase() {
let out = test_parse!(parse_value_table, r#" MATH::PI "#).unwrap(); let out = test_parse!(parse_value_field, r#" MATH::PI "#).unwrap();
assert_eq!(out, Value::Constant(Constant::MathPi)); assert_eq!(out, Value::Constant(Constant::MathPi));
let out = test_parse!(parse_value_table, r#" MATH::INF "#).unwrap(); let out = test_parse!(parse_value_field, r#" MATH::INF "#).unwrap();
assert_eq!(out, Value::Constant(Constant::MathInf)); assert_eq!(out, Value::Constant(Constant::MathInf));
let out = test_parse!(parse_value_table, r#" MATH::NEG_INF "#).unwrap(); let out = test_parse!(parse_value_field, r#" MATH::NEG_INF "#).unwrap();
assert_eq!(out, Value::Constant(Constant::MathNegInf)); assert_eq!(out, Value::Constant(Constant::MathNegInf));
let out = test_parse!(parse_value_table, r#" TIME::EPOCH "#).unwrap(); let out = test_parse!(parse_value_field, r#" TIME::EPOCH "#).unwrap();
assert_eq!(out, Value::Constant(Constant::TimeEpoch)); assert_eq!(out, Value::Constant(Constant::TimeEpoch));
} }
#[test] #[test]
fn constant_mixedcase() { fn constant_mixedcase() {
let out = test_parse!(parse_value_table, r#" MaTh::Pi "#).unwrap(); let out = test_parse!(parse_value_field, r#" MaTh::Pi "#).unwrap();
assert_eq!(out, Value::Constant(Constant::MathPi)); assert_eq!(out, Value::Constant(Constant::MathPi));
let out = test_parse!(parse_value_table, r#" MaTh::Inf "#).unwrap(); let out = test_parse!(parse_value_field, r#" MaTh::Inf "#).unwrap();
assert_eq!(out, Value::Constant(Constant::MathInf)); assert_eq!(out, Value::Constant(Constant::MathInf));
let out = test_parse!(parse_value_table, r#" MaTh::Neg_Inf "#).unwrap(); let out = test_parse!(parse_value_field, r#" MaTh::Neg_Inf "#).unwrap();
assert_eq!(out, Value::Constant(Constant::MathNegInf)); assert_eq!(out, Value::Constant(Constant::MathNegInf));
let out = test_parse!(parse_value_table, r#" TiME::ePoCH "#).unwrap(); let out = test_parse!(parse_value_field, r#" TiME::ePoCH "#).unwrap();
assert_eq!(out, Value::Constant(Constant::TimeEpoch)); assert_eq!(out, Value::Constant(Constant::TimeEpoch));
} }
#[test] #[test]
fn scientific_decimal() { fn scientific_decimal() {
let res = test_parse!(parse_value_table, r#" 9.7e-7dec "#).unwrap(); let res = test_parse!(parse_value_field, r#" 9.7e-7dec "#).unwrap();
assert!(matches!(res, Value::Number(Number::Decimal(_)))); assert!(matches!(res, Value::Number(Number::Decimal(_))));
assert_eq!(res.to_string(), "0.00000097dec") assert_eq!(res.to_string(), "0.00000097dec")
} }
#[test] #[test]
fn scientific_number() { fn scientific_number() {
let res = test_parse!(parse_value_table, r#" 9.7e-5"#).unwrap(); let res = test_parse!(parse_value_field, r#" 9.7e-5"#).unwrap();
assert!(matches!(res, Value::Number(Number::Float(_)))); assert!(matches!(res, Value::Number(Number::Float(_))));
assert_eq!(res.to_string(), "0.000097f") assert_eq!(res.to_string(), "0.000097f")
} }
#[test] #[test]
fn number_method() { fn number_method() {
let res = test_parse!(parse_value_table, r#" 9.7e-5.sin()"#).unwrap(); let res = test_parse!(parse_value_field, r#" 9.7e-5.sin()"#).unwrap();
let expected = Value::Idiom(Idiom(vec![ let expected = Value::Idiom(Idiom(vec![
Part::Start(Value::Number(Number::Float(9.7e-5))), Part::Start(Value::Number(Number::Float(9.7e-5))),
Part::Method("sin".to_string(), vec![]), Part::Method("sin".to_string(), vec![]),
])); ]));
assert_eq!(res, expected); assert_eq!(res, expected);
let res = test_parse!(parse_value_table, r#" 1.sin()"#).unwrap(); let res = test_parse!(parse_value_field, r#" 1.sin()"#).unwrap();
let expected = Value::Idiom(Idiom(vec![ let expected = Value::Idiom(Idiom(vec![
Part::Start(Value::Number(Number::Int(1))), Part::Start(Value::Number(Number::Int(1))),
Part::Method("sin".to_string(), vec![]), Part::Method("sin".to_string(), vec![]),
@ -234,10 +234,10 @@ fn number_method() {
#[test] #[test]
fn datetime_error() { fn datetime_error() {
test_parse!(parse_value_table, r#" d"2001-01-01T01:01:01.9999999999" "#).unwrap_err(); test_parse!(parse_value_field, r#" d"2001-01-01T01:01:01.9999999999" "#).unwrap_err();
} }
#[test] #[test]
fn empty_string() { fn empty_string() {
test_parse!(parse_value_table, "").unwrap_err(); test_parse!(parse_value_field, "").unwrap_err();
} }

View file

@ -125,7 +125,7 @@ impl Parser<'_> {
pub(crate) async fn parse_range(&mut self, ctx: &mut Stk) -> ParseResult<Range> { pub(crate) async fn parse_range(&mut self, ctx: &mut Stk) -> ParseResult<Range> {
// Check for beginning id // Check for beginning id
let beg = if Self::kind_is_identifier(self.peek_whitespace().kind) { let beg = if Self::kind_is_identifier(self.peek_whitespace().kind) {
let v = ctx.run(|ctx| self.parse_value_table(ctx)).await?; let v = ctx.run(|ctx| self.parse_value_inherit(ctx)).await?;
if self.eat_whitespace(t!(">")) { if self.eat_whitespace(t!(">")) {
Bound::Excluded(v) Bound::Excluded(v)
@ -142,7 +142,7 @@ impl Parser<'_> {
// parse ending id. // parse ending id.
let end = if Self::kind_is_identifier(self.peek_whitespace().kind) { let end = if Self::kind_is_identifier(self.peek_whitespace().kind) {
let v = ctx.run(|ctx| self.parse_value_table(ctx)).await?; let v = ctx.run(|ctx| self.parse_value_inherit(ctx)).await?;
if inclusive { if inclusive {
Bound::Included(v) Bound::Included(v)
} else { } else {

View file

@ -69,7 +69,7 @@ impl Parse<Self> for Expression {
let mut parser = Parser::new(val.as_bytes()); let mut parser = Parser::new(val.as_bytes());
let mut stack = Stack::new(); let mut stack = Stack::new();
let value = stack let value = stack
.enter(|ctx| parser.parse_value_table(ctx)) .enter(|ctx| parser.parse_value_field(ctx))
.finish() .finish()
.map_err(|e| e.render_on(val)) .map_err(|e| e.render_on(val))
.unwrap(); .unwrap();