Improve parsing to remove need for debrace everywhere.
This commit is contained in:
		
							parent
							
								
									f619aa4770
								
							
						
					
					
						commit
						f6486498f6
					
				@ -5,7 +5,7 @@ use itertools::{join, Itertools};
 | 
			
		||||
 | 
			
		||||
pub fn debrace(inp: &str) -> &str {
 | 
			
		||||
    let v = inp.trim();
 | 
			
		||||
    if v.starts_with("{") && v.ends_with("}") {
 | 
			
		||||
    if v.starts_with('{') && v.ends_with('}') {
 | 
			
		||||
        &v[1..(v.len() - 1)]
 | 
			
		||||
    } else {
 | 
			
		||||
        v
 | 
			
		||||
@ -26,7 +26,7 @@ fn reentrant_command_handler(
 | 
			
		||||
            Some((cmd, rest)) => {
 | 
			
		||||
                if let ("#", command_rest) = cmd.split_at(1) {
 | 
			
		||||
                    if cmd == "##" {
 | 
			
		||||
                        match lua_state.execute(debrace(&join(rest.arguments.iter(), " "))) {
 | 
			
		||||
                        match lua_state.execute(&rest.forget_guards().to_string()) {
 | 
			
		||||
                            Ok(()) => (),
 | 
			
		||||
                            Err(msg) => {
 | 
			
		||||
                                echo_to_term_frame(globals, term_frame, &format!("{}\r\n", msg))
 | 
			
		||||
@ -43,7 +43,7 @@ fn reentrant_command_handler(
 | 
			
		||||
                            );
 | 
			
		||||
                        }
 | 
			
		||||
                    } else {
 | 
			
		||||
                        match lua_state.execute_command(command_rest, &rest.arguments) {
 | 
			
		||||
                        match lua_state.execute_command(command_rest, &rest) {
 | 
			
		||||
                            Ok(()) => (),
 | 
			
		||||
                            Err(msg) => {
 | 
			
		||||
                                echo_to_term_frame(globals, term_frame, &format!("{}\r\n", msg))
 | 
			
		||||
 | 
			
		||||
@ -7,8 +7,9 @@ use piccolo::{
 | 
			
		||||
};
 | 
			
		||||
use yew::UseStateSetter;
 | 
			
		||||
 | 
			
		||||
use crate::{id_intern::intern_id, GlobalLayoutCell, GlobalMemoCell, TermFrame};
 | 
			
		||||
use std::collections::VecDeque;
 | 
			
		||||
use crate::{
 | 
			
		||||
    id_intern::intern_id, parsing::ParsedCommand, GlobalLayoutCell, GlobalMemoCell, TermFrame,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
pub struct LuaState {
 | 
			
		||||
    pub interp: Lua,
 | 
			
		||||
@ -63,7 +64,7 @@ impl LuaState {
 | 
			
		||||
    pub fn execute_command(
 | 
			
		||||
        &mut self,
 | 
			
		||||
        command: &str,
 | 
			
		||||
        arguments: &VecDeque<&str>,
 | 
			
		||||
        arguments: &ParsedCommand<'_>,
 | 
			
		||||
    ) -> Result<(), String> {
 | 
			
		||||
        self.interp
 | 
			
		||||
            .try_enter(|ctx| {
 | 
			
		||||
@ -78,8 +79,9 @@ impl LuaState {
 | 
			
		||||
                    command_fn,
 | 
			
		||||
                    Variadic(
 | 
			
		||||
                        arguments
 | 
			
		||||
                            .arguments
 | 
			
		||||
                            .iter()
 | 
			
		||||
                            .map(|s| ctx.intern(s.as_bytes()).into())
 | 
			
		||||
                            .map(|s| ctx.intern(s.text.as_bytes()).into())
 | 
			
		||||
                            .collect::<Vec<Value>>(),
 | 
			
		||||
                    ),
 | 
			
		||||
                );
 | 
			
		||||
 | 
			
		||||
@ -47,7 +47,7 @@ pub fn echo_frame<'gc>(
 | 
			
		||||
        let all_parts: Vec<String> = stack
 | 
			
		||||
            .consume::<Variadic<Vec<Value>>>(ctx)?
 | 
			
		||||
            .into_iter()
 | 
			
		||||
            .map(|v| format!("{:?}", v))
 | 
			
		||||
            .map(|v| format!("{}", v.display()))
 | 
			
		||||
            .collect();
 | 
			
		||||
        stack.push_front(frame_no);
 | 
			
		||||
        let message = ctx.intern((all_parts.join(" ") + "\r\n").as_bytes());
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										320
									
								
								src/parsing.rs
									
									
									
									
									
								
							
							
						
						
									
										320
									
								
								src/parsing.rs
									
									
									
									
									
								
							@ -1,11 +1,11 @@
 | 
			
		||||
use std::collections::VecDeque;
 | 
			
		||||
use std::{collections::VecDeque, fmt::Display};
 | 
			
		||||
 | 
			
		||||
use nom::{
 | 
			
		||||
    branch::alt,
 | 
			
		||||
    character::complete::{anychar, char, none_of},
 | 
			
		||||
    combinator::{eof, map, recognize, value},
 | 
			
		||||
    multi::{many0_count, separated_list0},
 | 
			
		||||
    sequence::{preceded, separated_pair},
 | 
			
		||||
    sequence::{delimited, preceded, separated_pair},
 | 
			
		||||
    IResult,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@ -14,9 +14,82 @@ pub struct ParseResult<'l> {
 | 
			
		||||
    pub commands: Vec<ParsedCommand<'l>>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(PartialEq, Eq, Debug)]
 | 
			
		||||
#[derive(PartialEq, Eq, Debug, Clone)]
 | 
			
		||||
pub enum ArgumentGuard {
 | 
			
		||||
    Paren,       // {}
 | 
			
		||||
    DoubleQuote, // ""
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(PartialEq, Eq, Debug, Clone)]
 | 
			
		||||
pub struct ParsedArgument<'l> {
 | 
			
		||||
    pub guard: Option<ArgumentGuard>,
 | 
			
		||||
    pub text: &'l str,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl<'l> ParsedArgument<'l> {
 | 
			
		||||
    pub fn forget_guard(&self) -> Self {
 | 
			
		||||
        Self {
 | 
			
		||||
            guard: None,
 | 
			
		||||
            ..self.clone()
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl<'a> Display for ParsedArgument<'a> {
 | 
			
		||||
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 | 
			
		||||
        match self.guard {
 | 
			
		||||
            None => {}
 | 
			
		||||
            Some(ArgumentGuard::Paren) => {
 | 
			
		||||
                f.write_str("{")?;
 | 
			
		||||
            }
 | 
			
		||||
            Some(ArgumentGuard::DoubleQuote) => {
 | 
			
		||||
                f.write_str("\"")?;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        f.write_str(self.text)?;
 | 
			
		||||
        match self.guard {
 | 
			
		||||
            None => {}
 | 
			
		||||
            Some(ArgumentGuard::Paren) => {
 | 
			
		||||
                f.write_str("}")?;
 | 
			
		||||
            }
 | 
			
		||||
            Some(ArgumentGuard::DoubleQuote) => {
 | 
			
		||||
                f.write_str("\"")?;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        Ok(())
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(PartialEq, Eq, Debug, Clone)]
 | 
			
		||||
pub struct ParsedCommand<'l> {
 | 
			
		||||
    pub arguments: VecDeque<&'l str>,
 | 
			
		||||
    pub arguments: VecDeque<ParsedArgument<'l>>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl<'l> ParsedCommand<'l> {
 | 
			
		||||
    pub fn forget_guards(&self) -> Self {
 | 
			
		||||
        Self {
 | 
			
		||||
            arguments: self.arguments.iter().map(|v| v.forget_guard()).collect(),
 | 
			
		||||
            ..self.clone()
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl<'a> Display for ParsedCommand<'a> {
 | 
			
		||||
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 | 
			
		||||
        let mut it = self.arguments.iter();
 | 
			
		||||
        match it.next() {
 | 
			
		||||
            None => {}
 | 
			
		||||
            Some(head) => {
 | 
			
		||||
                head.fmt(f)?;
 | 
			
		||||
 | 
			
		||||
                for v in it {
 | 
			
		||||
                    f.write_str(" ")?;
 | 
			
		||||
                    v.fmt(f)?;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        Ok(())
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl ParsedCommand<'_> {
 | 
			
		||||
@ -26,7 +99,7 @@ impl ParsedCommand<'_> {
 | 
			
		||||
            match tmp_arguments.pop_front() {
 | 
			
		||||
                None => return None,
 | 
			
		||||
                Some(head) => {
 | 
			
		||||
                    let trimmed_cmd = head.trim();
 | 
			
		||||
                    let trimmed_cmd = head.text.trim();
 | 
			
		||||
                    if !trimmed_cmd.is_empty() {
 | 
			
		||||
                        return Some((
 | 
			
		||||
                            trimmed_cmd,
 | 
			
		||||
@ -77,39 +150,60 @@ fn parse_parenthetical(input: &str) -> IResult<&str, ()> {
 | 
			
		||||
    )(input)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn parse_argument(input: &str) -> IResult<&str, ()> {
 | 
			
		||||
    value(
 | 
			
		||||
        (),
 | 
			
		||||
        many0_count(alt((
 | 
			
		||||
            value((), preceded(char('\\'), anychar)),
 | 
			
		||||
            value(
 | 
			
		||||
fn parse_argument(input: &str) -> IResult<&str, ParsedArgument> {
 | 
			
		||||
    alt((
 | 
			
		||||
        map(
 | 
			
		||||
            delimited(char('{'), recognize(parse_parenthetical), char('}')),
 | 
			
		||||
            |v| ParsedArgument {
 | 
			
		||||
                text: v,
 | 
			
		||||
                guard: Some(ArgumentGuard::Paren),
 | 
			
		||||
            },
 | 
			
		||||
        ),
 | 
			
		||||
        map(
 | 
			
		||||
            delimited(char('"'), recognize(parse_string), char('"')),
 | 
			
		||||
            |v| ParsedArgument {
 | 
			
		||||
                text: v,
 | 
			
		||||
                guard: Some(ArgumentGuard::DoubleQuote),
 | 
			
		||||
            },
 | 
			
		||||
        ),
 | 
			
		||||
        map(
 | 
			
		||||
            recognize(value(
 | 
			
		||||
                (),
 | 
			
		||||
                separated_pair(
 | 
			
		||||
                    char('{'),
 | 
			
		||||
                    parse_parenthetical,
 | 
			
		||||
                    alt((value((), eof), value((), char('}')))),
 | 
			
		||||
                ),
 | 
			
		||||
            ),
 | 
			
		||||
            value(
 | 
			
		||||
                (),
 | 
			
		||||
                separated_pair(
 | 
			
		||||
                    char('"'),
 | 
			
		||||
                    parse_string,
 | 
			
		||||
                    alt((value((), eof), value((), char('"')))),
 | 
			
		||||
                ),
 | 
			
		||||
            ),
 | 
			
		||||
            value((), none_of(" ;")),
 | 
			
		||||
        ))),
 | 
			
		||||
    )(input)
 | 
			
		||||
                many0_count(alt((
 | 
			
		||||
                    value((), preceded(char('\\'), anychar)),
 | 
			
		||||
                    value(
 | 
			
		||||
                        (),
 | 
			
		||||
                        separated_pair(
 | 
			
		||||
                            char('{'),
 | 
			
		||||
                            parse_parenthetical,
 | 
			
		||||
                            alt((value((), eof), value((), char('}')))),
 | 
			
		||||
                        ),
 | 
			
		||||
                    ),
 | 
			
		||||
                    value(
 | 
			
		||||
                        (),
 | 
			
		||||
                        separated_pair(
 | 
			
		||||
                            char('"'),
 | 
			
		||||
                            parse_string,
 | 
			
		||||
                            alt((value((), eof), value((), char('"')))),
 | 
			
		||||
                        ),
 | 
			
		||||
                    ),
 | 
			
		||||
                    value((), none_of(" ;")),
 | 
			
		||||
                ))),
 | 
			
		||||
            )),
 | 
			
		||||
            |v| ParsedArgument {
 | 
			
		||||
                text: v,
 | 
			
		||||
                guard: None,
 | 
			
		||||
            },
 | 
			
		||||
        ),
 | 
			
		||||
    ))(input)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn parse_command(input: &str) -> IResult<&str, ParsedCommand> {
 | 
			
		||||
    map(
 | 
			
		||||
        separated_list0(char(' '), recognize(parse_argument)),
 | 
			
		||||
        |arguments| ParsedCommand {
 | 
			
		||||
    map(separated_list0(char(' '), parse_argument), |arguments| {
 | 
			
		||||
        ParsedCommand {
 | 
			
		||||
            arguments: arguments.into(),
 | 
			
		||||
        },
 | 
			
		||||
    )(input)
 | 
			
		||||
        }
 | 
			
		||||
    })(input)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn parse_commands(input: &str) -> ParseResult {
 | 
			
		||||
@ -128,7 +222,11 @@ mod tests {
 | 
			
		||||
            parse_commands(""),
 | 
			
		||||
            ParseResult {
 | 
			
		||||
                commands: vec![ParsedCommand {
 | 
			
		||||
                    arguments: vec![""].into()
 | 
			
		||||
                    arguments: vec![ParsedArgument {
 | 
			
		||||
                        text: "",
 | 
			
		||||
                        guard: None
 | 
			
		||||
                    }]
 | 
			
		||||
                    .into()
 | 
			
		||||
                }]
 | 
			
		||||
            }
 | 
			
		||||
        );
 | 
			
		||||
@ -136,7 +234,11 @@ mod tests {
 | 
			
		||||
            parse_commands("north"),
 | 
			
		||||
            ParseResult {
 | 
			
		||||
                commands: vec![ParsedCommand {
 | 
			
		||||
                    arguments: vec!["north"].into()
 | 
			
		||||
                    arguments: vec![ParsedArgument {
 | 
			
		||||
                        text: "north",
 | 
			
		||||
                        guard: None
 | 
			
		||||
                    }]
 | 
			
		||||
                    .into()
 | 
			
		||||
                }]
 | 
			
		||||
            }
 | 
			
		||||
        );
 | 
			
		||||
@ -145,7 +247,17 @@ mod tests {
 | 
			
		||||
            ParseResult {
 | 
			
		||||
                commands: vec![ParsedCommand {
 | 
			
		||||
                    // This is deliberate, ensures we can reconstruct the input.
 | 
			
		||||
                    arguments: vec!["north", ""].into()
 | 
			
		||||
                    arguments: vec![
 | 
			
		||||
                        ParsedArgument {
 | 
			
		||||
                            text: "north",
 | 
			
		||||
                            guard: None
 | 
			
		||||
                        },
 | 
			
		||||
                        ParsedArgument {
 | 
			
		||||
                            text: "",
 | 
			
		||||
                            guard: None
 | 
			
		||||
                        }
 | 
			
		||||
                    ]
 | 
			
		||||
                    .into()
 | 
			
		||||
                }]
 | 
			
		||||
            }
 | 
			
		||||
        );
 | 
			
		||||
@ -154,10 +266,24 @@ mod tests {
 | 
			
		||||
            ParseResult {
 | 
			
		||||
                commands: vec![
 | 
			
		||||
                    ParsedCommand {
 | 
			
		||||
                        arguments: vec!["#blah", "{x = 1 + 2; y = 3}"].into()
 | 
			
		||||
                        arguments: vec![
 | 
			
		||||
                            ParsedArgument {
 | 
			
		||||
                                text: "#blah",
 | 
			
		||||
                                guard: None
 | 
			
		||||
                            },
 | 
			
		||||
                            ParsedArgument {
 | 
			
		||||
                                text: "x = 1 + 2; y = 3",
 | 
			
		||||
                                guard: Some(ArgumentGuard::Paren)
 | 
			
		||||
                            }
 | 
			
		||||
                        ]
 | 
			
		||||
                        .into()
 | 
			
		||||
                    },
 | 
			
		||||
                    ParsedCommand {
 | 
			
		||||
                        arguments: vec!["#home"].into()
 | 
			
		||||
                        arguments: vec![ParsedArgument {
 | 
			
		||||
                            text: "#home",
 | 
			
		||||
                            guard: None
 | 
			
		||||
                        }]
 | 
			
		||||
                        .into()
 | 
			
		||||
                    }
 | 
			
		||||
                ]
 | 
			
		||||
            }
 | 
			
		||||
@ -166,7 +292,17 @@ mod tests {
 | 
			
		||||
            parse_commands("#blah {x = 1 + 2"),
 | 
			
		||||
            ParseResult {
 | 
			
		||||
                commands: vec![ParsedCommand {
 | 
			
		||||
                    arguments: vec!["#blah", "{x = 1 + 2"].into()
 | 
			
		||||
                    arguments: vec![
 | 
			
		||||
                        ParsedArgument {
 | 
			
		||||
                            text: "#blah",
 | 
			
		||||
                            guard: None
 | 
			
		||||
                        },
 | 
			
		||||
                        ParsedArgument {
 | 
			
		||||
                            text: "{x = 1 + 2",
 | 
			
		||||
                            guard: None
 | 
			
		||||
                        }
 | 
			
		||||
                    ]
 | 
			
		||||
                    .into()
 | 
			
		||||
                },]
 | 
			
		||||
            }
 | 
			
		||||
        );
 | 
			
		||||
@ -174,7 +310,21 @@ mod tests {
 | 
			
		||||
            parse_commands("#blah {x = 1} {y = 1}"),
 | 
			
		||||
            ParseResult {
 | 
			
		||||
                commands: vec![ParsedCommand {
 | 
			
		||||
                    arguments: vec!["#blah", "{x = 1}", "{y = 1}"].into()
 | 
			
		||||
                    arguments: vec![
 | 
			
		||||
                        ParsedArgument {
 | 
			
		||||
                            text: "#blah",
 | 
			
		||||
                            guard: None
 | 
			
		||||
                        },
 | 
			
		||||
                        ParsedArgument {
 | 
			
		||||
                            text: "x = 1",
 | 
			
		||||
                            guard: Some(ArgumentGuard::Paren)
 | 
			
		||||
                        },
 | 
			
		||||
                        ParsedArgument {
 | 
			
		||||
                            text: "y = 1",
 | 
			
		||||
                            guard: Some(ArgumentGuard::Paren)
 | 
			
		||||
                        }
 | 
			
		||||
                    ]
 | 
			
		||||
                    .into()
 | 
			
		||||
                }]
 | 
			
		||||
            }
 | 
			
		||||
        );
 | 
			
		||||
@ -182,7 +332,21 @@ mod tests {
 | 
			
		||||
            parse_commands("#blah \"hello\" \"world\""),
 | 
			
		||||
            ParseResult {
 | 
			
		||||
                commands: vec![ParsedCommand {
 | 
			
		||||
                    arguments: vec!["#blah", "\"hello\"", "\"world\""].into()
 | 
			
		||||
                    arguments: vec![
 | 
			
		||||
                        ParsedArgument {
 | 
			
		||||
                            text: "#blah",
 | 
			
		||||
                            guard: None
 | 
			
		||||
                        },
 | 
			
		||||
                        ParsedArgument {
 | 
			
		||||
                            text: "hello",
 | 
			
		||||
                            guard: Some(ArgumentGuard::DoubleQuote)
 | 
			
		||||
                        },
 | 
			
		||||
                        ParsedArgument {
 | 
			
		||||
                            text: "world",
 | 
			
		||||
                            guard: Some(ArgumentGuard::DoubleQuote)
 | 
			
		||||
                        },
 | 
			
		||||
                    ]
 | 
			
		||||
                    .into()
 | 
			
		||||
                }]
 | 
			
		||||
            }
 | 
			
		||||
        );
 | 
			
		||||
@ -190,7 +354,21 @@ mod tests {
 | 
			
		||||
            parse_commands("#blah {x = \"}\"} {y = 1}"),
 | 
			
		||||
            ParseResult {
 | 
			
		||||
                commands: vec![ParsedCommand {
 | 
			
		||||
                    arguments: vec!["#blah", "{x = \"}\"}", "{y = 1}"].into()
 | 
			
		||||
                    arguments: vec![
 | 
			
		||||
                        ParsedArgument {
 | 
			
		||||
                            text: "#blah",
 | 
			
		||||
                            guard: None
 | 
			
		||||
                        },
 | 
			
		||||
                        ParsedArgument {
 | 
			
		||||
                            text: "x = \"}\"",
 | 
			
		||||
                            guard: Some(ArgumentGuard::Paren)
 | 
			
		||||
                        },
 | 
			
		||||
                        ParsedArgument {
 | 
			
		||||
                            text: "y = 1",
 | 
			
		||||
                            guard: Some(ArgumentGuard::Paren)
 | 
			
		||||
                        }
 | 
			
		||||
                    ]
 | 
			
		||||
                    .into()
 | 
			
		||||
                }]
 | 
			
		||||
            }
 | 
			
		||||
        );
 | 
			
		||||
@ -200,14 +378,27 @@ mod tests {
 | 
			
		||||
                commands: vec![
 | 
			
		||||
                    ParsedCommand {
 | 
			
		||||
                        arguments: vec![
 | 
			
		||||
                            "#blah",
 | 
			
		||||
                            "{x = \"}\"; a = \"{\"; y = {}; z = 1;}",
 | 
			
		||||
                            "{ q = 5 }"
 | 
			
		||||
                            ParsedArgument {
 | 
			
		||||
                                text: "#blah",
 | 
			
		||||
                                guard: None
 | 
			
		||||
                            },
 | 
			
		||||
                            ParsedArgument {
 | 
			
		||||
                                text: "x = \"}\"; a = \"{\"; y = {}; z = 1;",
 | 
			
		||||
                                guard: Some(ArgumentGuard::Paren)
 | 
			
		||||
                            },
 | 
			
		||||
                            ParsedArgument {
 | 
			
		||||
                                text: " q = 5 ",
 | 
			
		||||
                                guard: Some(ArgumentGuard::Paren)
 | 
			
		||||
                            }
 | 
			
		||||
                        ]
 | 
			
		||||
                        .into()
 | 
			
		||||
                    },
 | 
			
		||||
                    ParsedCommand {
 | 
			
		||||
                        arguments: vec![""].into()
 | 
			
		||||
                        arguments: vec![ParsedArgument {
 | 
			
		||||
                            text: "",
 | 
			
		||||
                            guard: None
 | 
			
		||||
                        }]
 | 
			
		||||
                        .into()
 | 
			
		||||
                    }
 | 
			
		||||
                ]
 | 
			
		||||
            }
 | 
			
		||||
@ -216,7 +407,21 @@ mod tests {
 | 
			
		||||
            parse_commands("#blah {\\}\\}\\}} {y = 1}"),
 | 
			
		||||
            ParseResult {
 | 
			
		||||
                commands: vec![ParsedCommand {
 | 
			
		||||
                    arguments: vec!["#blah", "{\\}\\}\\}}", "{y = 1}"].into()
 | 
			
		||||
                    arguments: vec![
 | 
			
		||||
                        ParsedArgument {
 | 
			
		||||
                            text: "#blah",
 | 
			
		||||
                            guard: None
 | 
			
		||||
                        },
 | 
			
		||||
                        ParsedArgument {
 | 
			
		||||
                            text: "\\}\\}\\}",
 | 
			
		||||
                            guard: Some(ArgumentGuard::Paren)
 | 
			
		||||
                        },
 | 
			
		||||
                        ParsedArgument {
 | 
			
		||||
                            text: "y = 1",
 | 
			
		||||
                            guard: Some(ArgumentGuard::Paren)
 | 
			
		||||
                        }
 | 
			
		||||
                    ]
 | 
			
		||||
                    .into()
 | 
			
		||||
                }]
 | 
			
		||||
            }
 | 
			
		||||
        );
 | 
			
		||||
@ -224,9 +429,28 @@ mod tests {
 | 
			
		||||
            parse_commands("#blah \"This is a \\\"test\\\"\""),
 | 
			
		||||
            ParseResult {
 | 
			
		||||
                commands: vec![ParsedCommand {
 | 
			
		||||
                    arguments: vec!["#blah", "\"This is a \\\"test\\\"\""].into()
 | 
			
		||||
                    arguments: vec![
 | 
			
		||||
                        ParsedArgument {
 | 
			
		||||
                            text: "#blah",
 | 
			
		||||
                            guard: None
 | 
			
		||||
                        },
 | 
			
		||||
                        ParsedArgument {
 | 
			
		||||
                            text: "This is a \\\"test\\\"",
 | 
			
		||||
                            guard: Some(ArgumentGuard::DoubleQuote)
 | 
			
		||||
                        }
 | 
			
		||||
                    ]
 | 
			
		||||
                    .into()
 | 
			
		||||
                }]
 | 
			
		||||
            }
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[test]
 | 
			
		||||
    fn test_parse_roundtrip() {
 | 
			
		||||
        let input = "#hello {to the} \"world\" I say! ";
 | 
			
		||||
        assert_eq!(
 | 
			
		||||
            parse_command(input).map(|c| c.1.to_string()),
 | 
			
		||||
            Ok(input.to_owned())
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user