diff --git a/Cargo.lock b/Cargo.lock index 6a90f44..2395f7c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,7 +4,7 @@ version = 3 [[package]] name = "mtsyntax-plus" -version = "0.2.0" +version = "0.2.1" dependencies = [ "peg", ] diff --git a/Cargo.toml b/Cargo.toml index c4f2b17..853c601 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mtsyntax-plus" -version = "0.2.0" +version = "0.2.1" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/README.md b/README.md index c6f8144..34c09d3 100644 --- a/README.md +++ b/README.md @@ -97,6 +97,9 @@ MT管理器语法文件强化语法, 主要作用就是可以自动展开regexp 匹配器组里面使用`:`来定义match匹配器, 使用`::`来定义include匹配器 +拥有几个语法糖, 使用`(`来表示`/(/`, 使用`(?:`来表示`/(?:/`, +使用`)`来表示`/)/`, 使用`){1, 2}`来表示`/){1,2}/`, 使用`|`来表示`/|/` + # 如何使用 在拥有rust编译环境的情况下, 在项目目录下输入 diff --git a/src/parser.rs b/src/parser.rs index 3c6f96e..fe675a4 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -14,22 +14,33 @@ fn new_rule_data<'a>( .flatten() { colors.insert(1, first.into()); - match &mut exprs[..] { - [Expr::Literal(s, n), ..] => { - s.to_mut().insert(1, '('); - *n += 1; - }, - _ => exprs.insert(0, Expr::Literal("/(/".into(), 1)), - } - match &mut exprs[..] { - [.., Expr::Literal(s, _)] => { - let tail = s.to_mut().pop().unwrap(); - s.to_mut().push(')'); - s.to_mut().push(tail); - }, - _ => exprs.push(Expr::Literal("/)/".into(), 0)), - } + exprs.insert(0, Expr::Literal("/(/".into(), 1)); + exprs.push(Expr::Literal("/)/".into(), 0)) } + let len = exprs.len(); + let mut exprs = exprs.into_iter() + .fold(Vec::with_capacity(len), |mut acc, expr| { + let Some(Expr::Literal(last, lc)) + = acc.last_mut() + else { + acc.push(expr); + return acc; + }; + assert_ne!(last.len(), 0); + match expr { + Expr::Literal(lit, c) + if lit.chars().next() == last.chars().next() => { + last.to_mut().pop().unwrap(); + last.to_mut().push_str(&lit[1..]); + *lc += c; + }, + _ => { + acc.push(expr); + } + } + acc + }); + exprs.shrink_to_fit(); RuleData { exprs, colors, @@ -142,8 +153,25 @@ peg::parser!(grammar parser() for str { "\"" { s.len() as u32 } + rule expr_sugar() -> Expr<'input> + = "|" { Expr::Literal("/|/".into(), 0) } + / "(?:" { Expr::Literal("/(?:/".into(), 0) } + / "(" { Expr::Literal("/(/".into(), 1) } + / ")" + x:( "{" a:unum() _ "," _ b:unum() "}" + { Expr::Literal(format!("/){{{a},{b}}}/").into(), 0) } + / "{" a:unum() _ "," _ "}" + { Expr::Literal(format!("/){{{a},}}/").into(), 0) } + / "{" _ "," _ b:unum() "}" + { Expr::Literal(format!("/){{,{b}}}/").into(), 0) } + / "{" n:unum() "}" + { Expr::Literal(format!("/){{{n}}}/").into(), 0) } + / { Expr::Literal("/)/".into(), 1) } + ) { x } + pub rule expr() -> Expr<'input> = s:(regex() / string()) { Expr::Literal(s.into(), group_count(s).unwrap()) } + / expr_sugar() / "keywordsToRegex" "(" _ s:string() ++ (_ ("," _)?) _ ("," _)? ")" { Expr::KwdsToRegex(s) @@ -225,6 +253,7 @@ mod tests { $1: "red" // abc bar := @foo + /;|\// + @foo // ... + sugar = (&a) | (?: &b ) | (&c){2} | (&c){2 , 3} | (&d){, 3} | (&d){3 , } "#; println!("{src}");