Fix fields being parsed as idioms. (#4819)
This commit is contained in:
parent
5867ce95d9
commit
52aef7ccc4
13 changed files with 100 additions and 85 deletions
|
@ -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))
|
||||||
|
|
|
@ -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()))])
|
||||||
))]))
|
))]))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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") => {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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!(
|
||||||
|
|
|
@ -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()
|
|
||||||
)])))])),
|
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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();
|
||||||
|
|
Loading…
Reference in a new issue