From 9f55bef23818c54aa4ca53ec7481ea5bdb5734b3 Mon Sep 17 00:00:00 2001 From: Lewis Dale Date: Mon, 2 Jan 2023 18:46:20 +0000 Subject: [PATCH] Parse escape characters properly --- src/basic.rs | 56 ++++++++++++++++++++++++++++++---------------------- src/main.rs | 2 +- 2 files changed, 33 insertions(+), 25 deletions(-) diff --git a/src/basic.rs b/src/basic.rs index 23bb8d6..04d8555 100644 --- a/src/basic.rs +++ b/src/basic.rs @@ -1,26 +1,34 @@ use nom::{ - bytes::complete::{tag, take_until, escaped}, - character::{complete::{u32 as ccu32, one_of}, streaming::none_of}, - combinator::map, + branch::alt, + bytes::complete::{escaped_transform, tag, take_until}, + character::{ + complete::{u32 as ccu32}, + streaming::none_of, + }, + combinator::{map, value}, sequence::{delimited, terminated, tuple}, IResult, }; -pub type Line<'a> = (u32, Command<'a>); +pub type Line = (u32, Command); #[derive(Debug, PartialEq, Eq)] -pub enum Command<'a> { - Print(&'a str), +pub enum Command { + Print(String), None, } -fn read_string(i: &str) -> IResult<&str, &str> { +fn read_string(i: &str) -> IResult<&str, String> { // take_until("\"")(i) - delimited( - tag("\""), - escaped(none_of("\\\""), '\\', one_of("\"\\")), - tag("\"") - )(i) + delimited( + tag("\""), + escaped_transform( + none_of("\\\""), + '\\', + alt((value("\\", tag("\\")), value("\"", tag("\"")))), + ), + tag("\""), + )(i) } fn parse_command(i: &str) -> IResult<&str, Command> { @@ -45,25 +53,25 @@ mod tests { #[test] fn it_parses_a_print_command() { let input = "10 PRINT \"Hello, world\""; - let expected = (10, super::Command::Print("Hello, world")); + let expected = (10, super::Command::Print(String::from("Hello, world"))); let (_, result) = super::parse_line(input).unwrap(); assert_eq!(expected, result); } - #[test] - fn it_reads_a_string() { - let input = r#""Hello, \"World\"""#; - let (_, output) = super::read_string(input).unwrap(); - assert_eq!(r#"Hello, \"World\""#, output); - } + #[test] + fn it_reads_a_string() { + let input = r#""Hello, \"World\"""#; + let (_, output) = super::read_string(input).unwrap(); + assert_eq!(r#"Hello, "World""#, output); + } - #[test] - fn it_parses_a_print_command_with_escaped_quotes() { - let input = r#"10 PRINT "Hello, \"world\"""#; - let expected = (10, super::Command::Print(r#"Hello, \"world\""#)); + #[test] + fn it_parses_a_print_command_with_escaped_quotes() { + let input = r#"10 PRINT "Hello, \"world\"""#; + let expected = (10, super::Command::Print(String::from(r#"Hello, "world""#))); let (_, result) = super::parse_line(input).unwrap(); assert_eq!(expected, result); - } + } } diff --git a/src/main.rs b/src/main.rs index c6cd6e9..6afda37 100644 --- a/src/main.rs +++ b/src/main.rs @@ -8,7 +8,7 @@ fn main() { let (_, (_, command)) = basic::parse_line(lines).unwrap(); match command { basic::Command::Print(input) => { - println!("{}", input.replace("\\", "")); + println!("{}", input); } _ => { panic!("Command not recognised");