Distinguish string literals from identifiers in custom syntax parser.

This commit is contained in:
Stephen Chung 2022-09-24 16:59:01 +08:00
parent f2b1184805
commit def1a683ef
4 changed files with 26 additions and 14 deletions

View File

@ -1,6 +1,14 @@
Rhai Release Notes Rhai Release Notes
================== ==================
Version 1.11.0
==============
Enhancements
* The look-ahead symbol for custom syntax now renders a string literal in quotes (instead of the generic term `string`). This facilitates more accurate parsing by separating strings and identifiers.
Version 1.10.1 Version 1.10.1
============== ==============

View File

@ -2461,7 +2461,7 @@ impl Engine {
use crate::api::custom_syntax::markers::*; use crate::api::custom_syntax::markers::*;
let mut settings = settings; let mut settings = settings;
let mut inputs = StaticVec::<Expr>::new(); let mut inputs = StaticVec::new_const();
let mut segments = StaticVec::new_const(); let mut segments = StaticVec::new_const();
let mut tokens = StaticVec::new_const(); let mut tokens = StaticVec::new_const();

View File

@ -699,7 +699,7 @@ impl Token {
FloatConstant(f) => f.to_string().into(), FloatConstant(f) => f.to_string().into(),
#[cfg(feature = "decimal")] #[cfg(feature = "decimal")]
DecimalConstant(d) => d.to_string().into(), DecimalConstant(d) => d.to_string().into(),
StringConstant(..) => "string".into(), StringConstant(s) => format!("\"{s}\"").into(),
InterpolatedString(..) => "string".into(), InterpolatedString(..) => "string".into(),
CharConstant(c) => c.to_string().into(), CharConstant(c) => c.to_string().into(),
Identifier(s) => s.to_string().into(), Identifier(s) => s.to_string().into(),

View File

@ -256,10 +256,18 @@ fn test_custom_syntax_raw() -> Result<(), Box<EvalAltResult>> {
engine.register_custom_syntax_with_state_raw( engine.register_custom_syntax_with_state_raw(
"hello", "hello",
|stream, _, state| match stream.len() { |stream, look_ahead, state| match stream.len() {
0 => unreachable!(), 0 => unreachable!(),
1 => Ok(Some("$ident$".into())), 1 if look_ahead == "\"world\"" => {
*state = Dynamic::TRUE;
Ok(Some("$string$".into()))
}
1 => {
*state = Dynamic::FALSE;
Ok(Some("$ident$".into()))
}
2 => match stream[1].as_str() { 2 => match stream[1].as_str() {
"world" if state.as_bool().unwrap_or(false) => Ok(Some("$$world".into())),
"world" => Ok(Some("$$hello".into())), "world" => Ok(Some("$$hello".into())),
"kitty" => { "kitty" => {
*state = (42 as INT).into(); *state = (42 as INT).into();
@ -276,16 +284,11 @@ fn test_custom_syntax_raw() -> Result<(), Box<EvalAltResult>> {
context.scope_mut().push("foo", 999 as INT); context.scope_mut().push("foo", 999 as INT);
Ok(match inputs[0].get_string_value().unwrap() { Ok(match inputs[0].get_string_value().unwrap() {
"world" "world" => match inputs.last().unwrap().get_string_value().unwrap_or("") {
if inputs "$$hello" => 0 as INT,
.last() "$$world" => 123456 as INT,
.unwrap() _ => 123 as INT,
.get_string_value() },
.map_or(false, |s| s == "$$hello") =>
{
0 as INT
}
"world" => 123 as INT,
"kitty" if inputs.len() > 1 => 999 as INT, "kitty" if inputs.len() > 1 => 999 as INT,
"kitty" => state.as_int().unwrap(), "kitty" => state.as_int().unwrap(),
_ => unreachable!(), _ => unreachable!(),
@ -294,6 +297,7 @@ fn test_custom_syntax_raw() -> Result<(), Box<EvalAltResult>> {
}, },
); );
assert_eq!(engine.eval::<INT>(r#"hello "world""#)?, 123456);
assert_eq!(engine.eval::<INT>("hello world")?, 0); assert_eq!(engine.eval::<INT>("hello world")?, 0);
assert_eq!(engine.eval::<INT>("hello kitty")?, 42); assert_eq!(engine.eval::<INT>("hello kitty")?, 42);
assert_eq!( assert_eq!(