Skip to content

Commit

Permalink
添加在捕获组处声明颜色的幽灵颜色组
Browse files Browse the repository at this point in the history
  • Loading branch information
A4-Tacks committed Jun 16, 2024
1 parent a084bd0 commit 314384a
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 13 deletions.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,9 @@ MT管理器语法文件强化语法, 主要作用就是可以自动展开regexp
拥有几个语法糖, 使用`(`来表示`/(/`, 使用`(?:`来表示`/(?:/`,
使用`)`来表示`/)/`, 使用`){1, 2}`来表示`/){1,2}/`, 使用`|`来表示`/|/`

使用`($color`表示一个幽灵颜色组,
它的颜色定义来源于组声明处写的`color`而非后续本地定义如`$1: color`


# 如何使用
在拥有rust编译环境的情况下, 在项目目录下输入
Expand Down
54 changes: 45 additions & 9 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ pub enum Expr<'a> {
/// regexp or string literal, and group count.
/// e.g /ab/ "abi"
Literal(Cow<'a, str>, u32),
/// like Literal, but not consume local color and output is capture group open
ColorGroup(Cow<'a, str>),
/// e.g keywordsToRegex("ab cd", "ef gh")
KwdsToRegex(Vec<&'a str>),
/// rule reference, e.g @foo
Expand All @@ -72,6 +74,7 @@ impl<'a> fmt::Display for Expr<'a> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Expr::Literal(lit, _) => f.write_str(lit),
Expr::ColorGroup(_) => f.write_str("/(/"),
Expr::KwdsToRegex(kwds) => {
write!(f, "keywordsToRegex(")?;
if let Some(first) = kwds.first() {
Expand All @@ -93,6 +96,7 @@ impl Expr<'_> {
where F: FnOnce(&str) -> Option<u32>,
{
Ok(match self {
| &Expr::ColorGroup(_) => 1,
| &Expr::Include(_, c)
| &Expr::Literal(_, c) => c,
| &Expr::KwdsToRegex(_) => 0,
Expand Down Expand Up @@ -121,6 +125,12 @@ impl Expr<'_> {
})?;
rule.build_colors(octx, ctx)?
},
| &Expr::ColorGroup(ref color) => {
let id = ctx.current_color.get();
octx.newline()?;
octx.output(fa!("{id}: {color}"))?;
ctx.current_color.set(id + 1);
},
| &Expr::Literal(_, count)
| &Expr::Include(_, count) => {
let cur_color = ctx.current_color.get();
Expand All @@ -143,7 +153,7 @@ impl Expr<'_> {
#[derive(Debug)]
pub struct RuleData<'a> {
exprs: Vec<Expr<'a>>,
colors: Vec<Option<&'a str>>,
colors: Vec<Option<Cow<'a, str>>>,
group_count: Option<u32>,
regexp: bool,
attrs: Vec<(&'a str, &'a str)>,
Expand Down Expand Up @@ -193,17 +203,15 @@ impl<'a> RuleData<'a> {
where F: FnMut(std::fmt::Arguments<'_>) -> io::Result<()>,
{
if self.regexp {
for expr in self.exprs.iter().take(self.exprs.len() - 1) {
octx.output(fa!("{expr} + "))?;
}
octx.output(fa!("{}", self.exprs.last().unwrap()))?;
out_exprs(&self.exprs, |args| {
octx.output(args)
})?;
} else {
octx.with_block(['{', '}'], |octx| {
octx.output(fa!("match: "))?;
for expr in self.exprs.iter().take(self.exprs.len() - 1) {
octx.output(fa!("{expr} + "))?;
}
octx.output(fa!("{}", self.exprs.last().unwrap()))?;
out_exprs(&self.exprs, |args| {
octx.output(args)
})?;

for &(attr, val) in &self.attrs {
octx.newline()?;
Expand Down Expand Up @@ -389,6 +397,34 @@ impl Default for OutputContext<'static> {
}
}

/// 融合相邻项并输出结果
fn out_exprs<'a, F, I>(exprs: I, mut f: F) -> io::Result<()>
where F: FnMut(std::fmt::Arguments<'_>) -> io::Result<()>,
I: IntoIterator<Item = &'a Expr<'a>>,
{
let exprs = exprs.into_iter()
.map(ToString::to_string)
.collect::<Vec<_>>();

let mut iter = exprs.into_iter();
let first = iter.next().unwrap();
let end = iter.try_fold(first, |mut a, b| {
io::Result::Ok(if let Some('/' | '"') = a.chars()
.next_back()
.zip(b.chars().next())
.and_then(|(a, b)| (a == b).then_some(a))
{
a.pop().unwrap();
a.push_str(&b[1..]);
a
} else {
f(fa!("{a} + "))?;
b
})
})?;
f(fa!("{}", end))
}

pub fn build<'a, I, F>(
rules: I,
octx: &mut OutputContext<'_, F>,
Expand Down
11 changes: 7 additions & 4 deletions src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ fn new_rule_data<'a>(
regexp: bool,
mut exprs: Vec<Expr<'a>>,
attrs: Vec<(&'a str, &'a str)>,
mut colors: Vec<Option<&'a str>>,
mut colors: Vec<Option<Cow<'a, str>>>,
) -> RuleData<'a> {
if let Some(first) = colors.first_mut()
.and_then(|color| color.take())
Expand Down Expand Up @@ -102,11 +102,11 @@ peg::parser!(grammar parser() for str {
}
/ expected!("number(0..100000)")

rule color() -> (u32, &'input str)
= "$" n:unum() _ ":" _ name:string()
rule color() -> (u32, Cow<'input, str>)
= "$" n:unum() _ ":" _ name:eident()
{ (n, name) }

pub rule colors() -> Vec<Option<&'input str>>
pub rule colors() -> Vec<Option<Cow<'input, str>>>
= colors:color() ** _
{
let mut res = Vec::new();
Expand Down Expand Up @@ -158,6 +158,7 @@ peg::parser!(grammar parser() for str {
rule expr_sugar() -> Expr<'input>
= "|" { Expr::Literal("/|/".into(), 0) }
/ "(?:" { Expr::Literal("/(?:/".into(), 0) }
/ "($" color:eident() { Expr::ColorGroup(color) }
/ "(" { Expr::Literal("/(/".into(), 1) }
/ ")"
x:( "{" a:unum() _ "," _ b:unum() "}"
Expand Down Expand Up @@ -256,6 +257,8 @@ mod tests {
bar := @foo + /;|\// + @foo // ...
sugar = (&a) | (?: &b ) | (&c){2} | (&c){2 , 3} | (&d){, 3} | (&d){3 , }
x := ($red /a/) /(b)/
$1: blue
"#;
println!("{src}");

Expand Down

0 comments on commit 314384a

Please sign in to comment.