From 29df89d388d95d7dc3fd1d7360ee9630a82479de Mon Sep 17 00:00:00 2001 From: A4-Tacks Date: Wed, 22 Jan 2025 00:15:49 +0800 Subject: [PATCH] =?UTF-8?q?=E7=BB=99=E9=80=BB=E8=BE=91=E8=A7=A3=E6=9E=90?= =?UTF-8?q?=E5=99=A8=E9=9D=9E=E9=A6=96=E4=B8=AA=E5=8F=82=E6=95=B0=E6=94=AF?= =?UTF-8?q?=E6=8C=81=E5=86=92=E5=8F=B7=E7=BB=93=E5=B0=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Cargo.lock | 4 +- Cargo.toml | 2 +- tools/tag_code/Cargo.toml | 2 +- tools/tag_code/src/logic_parser.rs | 65 +++++++++++++++++++++++++----- 4 files changed, 60 insertions(+), 13 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 21e74d9..eeedc72 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -284,7 +284,7 @@ checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "mindustry_logic_bang_lang" -version = "0.17.14" +version = "0.17.15" dependencies = [ "display_source", "logic_lint", @@ -541,7 +541,7 @@ dependencies = [ [[package]] name = "tag_code" -version = "0.2.2" +version = "0.2.3" dependencies = [ "either", "peg", diff --git a/Cargo.toml b/Cargo.toml index 49e49c3..d911473 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mindustry_logic_bang_lang" -version = "0.17.14" +version = "0.17.15" edition = "2021" authors = ["A4-Tacks "] diff --git a/tools/tag_code/Cargo.toml b/tools/tag_code/Cargo.toml index 1532e38..115637d 100644 --- a/tools/tag_code/Cargo.toml +++ b/tools/tag_code/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tag_code" -version = "0.2.2" +version = "0.2.3" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/tools/tag_code/src/logic_parser.rs b/tools/tag_code/src/logic_parser.rs index ee04da2..5e60ab6 100644 --- a/tools/tag_code/src/logic_parser.rs +++ b/tools/tag_code/src/logic_parser.rs @@ -22,11 +22,11 @@ peg::parser!(pub grammar parser() for str { / expected!("string") rule norm_arg_ch() = [^' ' | '\t' | '\r' | '\n' | '"' | '#' | ';'] - rule norm_arg_inner() - = norm_arg_ch() norm_arg_inner() - / !":" norm_arg_ch() rule norm_arg() -> &'input str - = quiet!{ $(norm_arg_inner()) } + = quiet!{ $(norm_arg_ch()+) } + / expected!("norm-arg") + pub rule nonlabel_arg() -> &'input str + = quiet!{ $((!":" norm_arg_ch() / ":"+ !":" norm_arg_ch())+) } / expected!("norm-arg") pub rule arg() -> &'input str @@ -37,7 +37,7 @@ peg::parser!(pub grammar parser() for str { = args:(arg:arg() { Var::from(arg) }) ++ _ { args.try_into().unwrap() } pub rule label() -> &'input str - = quiet!{ s:arg() ":" { s } / $(":" arg()) } + = quiet!{ s:nonlabel_arg() ":" { s } / $(":" nonlabel_arg()) } / expected!("label") pub rule line() -> ParseLine<'input> @@ -58,7 +58,7 @@ peg::parser!(pub grammar parser() for str { /// # use tag_code::{args, logic_parser::Args}; /// # use std::borrow::Cow; /// assert_eq!( -/// args!("a", "b"), +/// args!["a", "b"], /// Args::try_from( /// Cow::Owned(vec!["a".into(), "b".into()]) /// ).unwrap(), @@ -148,6 +148,13 @@ impl<'a> TryFrom> for Args<'a> { Ok(Self(Cow::Owned(args))) } } +impl<'a> TryFrom<&'a [Var]> for Args<'a> { + type Error = (); + + fn try_from(value: &'a [Var]) -> Result { + Cow::Borrowed(value).try_into() + } +} impl<'a> TryFrom> for Args<'a> { type Error = (); @@ -579,6 +586,13 @@ mod tests { use crate::TagCodes; use super::*; + fn chain(a: A, b: B) -> iter::Chain + where A: IntoIterator, + B: IntoIterator, + { + a.into_iter().chain(b) + } + #[test] fn newline_test() { let datas = [ @@ -635,6 +649,8 @@ mod tests { "ab", "x", "A", + ]; + let strings = [ "\"\"", "\"x\"", "\"foo\"", @@ -660,10 +676,13 @@ mod tests { ]; for src in datas { + assert_eq!(parser::nonlabel_arg(src), Ok(src)); + } + for src in chain(datas, strings) { assert_eq!(parser::arg(src), Ok(src)); } for src in fails { - assert!(parser::arg(src).is_err()); + assert!(parser::nonlabel_arg(src).is_err(), "{src}"); } } @@ -676,19 +695,47 @@ mod tests { (":foo", ":foo"), (":f:oo", ":f:oo"), ("fo:o:", "fo:o"), + ("fo::o:", "fo::o"), (":a:", ":a"), + ("::a:", "::a"), ]; let fails = [ ":", "::", ":::", + "a::", + "a:::", + ":a:::", + "::a:::", ]; for (src, dst) in datas { assert_eq!(parser::label(src), Ok(dst), "{src}"); + assert_eq!(parser::line(src), Ok( + ParseLine::Label(Cow::Borrowed(dst))), "{src}"); } for src in fails { - assert!(parser::label(src).is_err()); + let result = parser::label(src); + assert!(result.is_err(), "{src} : {result:?}"); + } + } + + #[test] + fn line_test() { + let datas = [ + ("foo", args!["foo"]), + ("foo bar", args!["foo", "bar"]), + ("foo bar:", args!["foo", "bar:"]), + ("fo:o bar:", args!["fo:o", "bar:"]), + ("fo::o bar:", args!["fo::o", "bar:"]), + ("foo b:ar:", args!["foo", "b:ar:"]), + ("foo \"b:ar:\"", args!["foo", "\"b:ar:\""]), + ("foo author: foo", args!["foo", "author:", "foo"]), + ("foo :author: foo", args!["foo", ":author:", "foo"]), + ]; + + for (src, dst) in datas { + assert_eq!(parser::line(src), Ok(dst.into()), "{src}"); } } @@ -745,7 +792,7 @@ mod tests { #[test] fn line_fmt_test() { let datas: [(ParseLine, _); 5] = [ - (args!("read").into(), "read"), + (args!["read"].into(), "read"), (args!["read", "foo"].into(), "read foo"), (args!["read", "foo", "bar"].into(), "read foo bar"), (args!["read", "\"foo\"", "bar"].into(), "read \"foo\" bar"),