Fix inconsitent numeric object key (#4851)
This commit is contained in:
parent
8cca86028b
commit
eff4936dc3
3 changed files with 28 additions and 15 deletions
|
@ -79,15 +79,12 @@ pub fn escape_ident(s: &str) -> Cow<'_, str> {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn escape_normal<'a>(s: &'a str, l: char, r: char, e: &str) -> Cow<'a, str> {
|
pub fn escape_normal<'a>(s: &'a str, l: char, r: char, e: &str) -> Cow<'a, str> {
|
||||||
// Loop over each character
|
// Is there no need to escape the value?
|
||||||
for x in s.bytes() {
|
if s.bytes().all(|x| x.is_ascii_alphanumeric() || x == b'_') {
|
||||||
// Check if character is allowed
|
return Cow::Borrowed(s);
|
||||||
if !(x.is_ascii_alphanumeric() || x == b'_') {
|
|
||||||
return Cow::Owned(format!("{l}{}{r}", s.replace(r, e)));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// Output the value
|
// Output the value
|
||||||
Cow::Borrowed(s)
|
Cow::Owned(format!("{l}{}{r}", s.replace(r, e)))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn escape_reserved_keyword(s: &str) -> Option<String> {
|
pub fn escape_reserved_keyword(s: &str) -> Option<String> {
|
||||||
|
|
|
@ -3,9 +3,10 @@ use std::collections::BTreeMap;
|
||||||
use reblessive::Stk;
|
use reblessive::Stk;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
sql::{Block, Geometry, Number, Object, Strand, Value},
|
sql::{Block, Geometry, Object, Strand, Value},
|
||||||
syn::{
|
syn::{
|
||||||
error::bail,
|
error::bail,
|
||||||
|
lexer::compound,
|
||||||
parser::{enter_object_recursion, mac::expected, ParseResult, Parser},
|
parser::{enter_object_recursion, mac::expected, ParseResult, Parser},
|
||||||
token::{t, Glued, Span, TokenKind},
|
token::{t, Glued, Span, TokenKind},
|
||||||
},
|
},
|
||||||
|
@ -602,10 +603,8 @@ impl Parser<'_> {
|
||||||
match token.kind {
|
match token.kind {
|
||||||
x if Self::kind_is_keyword_like(x) => {
|
x if Self::kind_is_keyword_like(x) => {
|
||||||
self.pop_peek();
|
self.pop_peek();
|
||||||
let str = self.lexer.reader.span(token.span);
|
let str = self.lexer.span_str(token.span);
|
||||||
// Lexer should ensure that the token is valid utf-8
|
Ok(str.to_string())
|
||||||
let str = std::str::from_utf8(str).unwrap().to_owned();
|
|
||||||
Ok(str)
|
|
||||||
}
|
}
|
||||||
TokenKind::Identifier => {
|
TokenKind::Identifier => {
|
||||||
self.pop_peek();
|
self.pop_peek();
|
||||||
|
@ -616,9 +615,16 @@ impl Parser<'_> {
|
||||||
let str = self.next_token_value::<Strand>()?.0;
|
let str = self.next_token_value::<Strand>()?.0;
|
||||||
Ok(str)
|
Ok(str)
|
||||||
}
|
}
|
||||||
TokenKind::Digits | TokenKind::Glued(Glued::Number) => {
|
TokenKind::Digits => {
|
||||||
let number = self.next_token_value::<Number>()?.to_string();
|
self.pop_peek();
|
||||||
Ok(number)
|
let span = self.lexer.lex_compound(token, compound::number)?.span;
|
||||||
|
let str = self.lexer.span_str(span);
|
||||||
|
Ok(str.to_string())
|
||||||
|
}
|
||||||
|
TokenKind::Glued(Glued::Number) => {
|
||||||
|
self.pop_peek();
|
||||||
|
let str = self.lexer.span_str(token.span);
|
||||||
|
Ok(str.to_string())
|
||||||
}
|
}
|
||||||
_ => unexpected!(self, token, "an object key"),
|
_ => unexpected!(self, token, "an object key"),
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,6 +38,16 @@ fn parse_coordinate() {
|
||||||
assert_eq!(x.y(), -18.0);
|
assert_eq!(x.y(), -18.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn parse_numeric_object_key() {
|
||||||
|
let v = test_parse!(parse_value_table, "{ 00: 0 }").unwrap();
|
||||||
|
let Value::Object(object) = v else {
|
||||||
|
panic!("not an object");
|
||||||
|
};
|
||||||
|
assert!(object.len() == 1);
|
||||||
|
assert_eq!(object.get("00").cloned(), Some(Value::Number(Number::Int(0))));
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn parse_like_operator() {
|
fn parse_like_operator() {
|
||||||
test_parse!(parse_value_field, "a ~ b").unwrap();
|
test_parse!(parse_value_field, "a ~ b").unwrap();
|
||||||
|
|
Loading…
Reference in a new issue