Skip to content

Commit

Permalink
添加include匹配器和匹配器组的支持
Browse files Browse the repository at this point in the history
  • Loading branch information
A4-Tacks committed Jun 15, 2024
1 parent 762049d commit c2b9823
Show file tree
Hide file tree
Showing 7 changed files with 232 additions and 70 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "mtsyntax-plus"
version = "0.1.0"
version = "0.2.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
Expand Down
43 changes: 37 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,28 @@ MT管理器语法文件强化语法, 主要作用就是可以自动展开regexp
$1: "error"
string = /"(?:[^"\\]|/ @string-escape /)*"/
$0: "string"
string-def := @string
$recordAllGroups: true
$0: "string"
r-string-def := /r/ @string
$recordAllGroups: true
$0: "keyword2"
num = /\b\d+\b/
$0: "number"
value-def := {
::string-def
::r-string-def
: @num
}
//!includeEnd
]
contains: [
{include: "string-def"}
{include: "value-def"}
]
}
```
Expand All @@ -37,26 +50,42 @@ MT管理器语法文件强化语法, 主要作用就是可以自动展开regexp
defines: [
// Generated by mtsyntax-plus begin
"string-escape": /(\\(?:[nrt'"\\]|(.)))/
"string": /("(?:[^"\\]|/ + include("string-escape") + /)*")/
"string": /"(?:[^"\\]|/ + include("string-escape") + /)*"/
"string-def": {
match: include("string")
match: /(/ + include("string") + /)/
recordAllGroups: true
1: "string"
2: "strEscape"
3: "error"
}
"r-string-def": {
match: /(r/ + include("string") + /)/
recordAllGroups: true
1: "keyword2"
2: "strEscape"
3: "error"
}
"num": /(\b\d+\b)/
"value-def": [
{include: "string-def"}
{include: "r-string-def"}
{
match: include("num")
1: "number"
}
]
// Generated by mtsyntax-plus end
]
contains: [
{include: "string-def"}
{include: "value-def"}
]
}
```

# 语法

使用`=`来定义正则, 使用`:=`来定义匹配器
使用`=`来定义正则, 使用`:=`来定义匹配器, 使用`:= { ... }`来定义匹配器组

使用`@name`来引用定义的正则, 使用`&name`来引用外部定义的正则,
并且可以使用`&name(count)`标注外部的正则拥有多少个高亮组, 以避免组匹配歪掉
Expand All @@ -66,6 +95,8 @@ MT管理器语法文件强化语法, 主要作用就是可以自动展开regexp
在定义了匹配后, 可以跟上属性和颜色组,
属性例如`$name: "value"`, 颜色例如`$2: "xxx"`, 属性定义在颜色前面

匹配器组里面使用`:`来定义match匹配器, 使用`::`来定义include匹配器


# 如何使用
在拥有rust编译环境的情况下, 在项目目录下输入
Expand Down
17 changes: 15 additions & 2 deletions example.mtsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,27 @@
$1: "error"

string = /"(?:[^"\\]|/ @string-escape /)*"/
$0: "string"

string-def := @string
$recordAllGroups: true
$0: "string"

r-string-def := /r/ @string
$recordAllGroups: true
$0: "keyword2"

num = /\b\d+\b/
$0: "number"

value-def := {
::string-def
::r-string-def
: @num
}
//!includeEnd
]

contains: [
{include: "string-def"}
{include: "value-def"}
]
}
129 changes: 108 additions & 21 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ macro_rules! assert_match {
pub enum Error {
UndefineRef(String),
RepeatDefineName(String),
RefNotARegexp(String),
IOError(io::Error),
}
impl From<io::Error> for Error {
Expand Down Expand Up @@ -113,7 +114,11 @@ impl Expr<'_> {
| &Expr::KwdsToRegex(_) => (),
| &Expr::Ref(name) => {
let rule = ctx.rule_map.get(name)
.ok_or_else(|| Error::UndefineRef(name.into()))?;
.ok_or_else(|| Error::UndefineRef(name.into()))
.and_then(|data| {
data.regexp.then_some(data)
.ok_or_else(|| Error::RefNotARegexp(name.into()))
})?;
rule.build_colors(octx, ctx)?
},
| &Expr::Literal(_, count)
Expand All @@ -135,15 +140,15 @@ impl Expr<'_> {
}

#[derive(Debug)]
pub struct Rule<'a> {
name: &'a str,
pub struct RuleData<'a> {
exprs: Vec<Expr<'a>>,
colors: Vec<Option<&'a str>>,
group_count: Option<u32>,
hidden: bool,
regexp: bool,
attrs: Vec<(&'a str, &'a str)>,
}
impl<'a> Rule<'a> {

impl<'a> RuleData<'a> {
pub fn update_group_count<F>(&mut self, mut f: F) -> Result<()>
where F: FnMut(&str) -> Option<u32>
{
Expand Down Expand Up @@ -186,14 +191,13 @@ impl<'a> Rule<'a> {
) -> Result<()>
where F: FnMut(std::fmt::Arguments<'_>) -> io::Result<()>,
{
octx.output(fa!("\"{}\": ", self.name))?;
if self.hidden {
if self.regexp {
for expr in self.exprs.iter().take(self.exprs.len() - 1) {
octx.output(fa!("{expr} + "))?;
}
octx.outputln(fa!("{}", self.exprs.last().unwrap()))?;
octx.output(fa!("{}", self.exprs.last().unwrap()))?;
} else {
octx.with_block(|octx| {
octx.with_block(['{', '}'], |octx| {
octx.output(fa!("match: "))?;
for expr in self.exprs.iter().take(self.exprs.len() - 1) {
octx.output(fa!("{expr} + "))?;
Expand All @@ -215,10 +219,89 @@ impl<'a> Rule<'a> {
}
}

#[derive(Debug)]
pub enum Pattern<'a> {
Normal(RuleData<'a>),
IncludePattern(Cow<'a, str>),
}
impl<'a> From<RuleData<'a>> for Pattern<'a> {
fn from(value: RuleData<'a>) -> Self {
Self::Normal(value)
}
}
impl Pattern<'_> {
pub fn update_group_count<F>(&mut self, f: F) -> Result<()>
where F: FnMut(&str) -> Option<u32>
{
match self {
Pattern::Normal(data) => data.update_group_count(f),
Pattern::IncludePattern(_) => Ok(()),
}
}

pub fn build<F>(
&self,
ctx: &BuildContext<'_>,
octx: &mut OutputContext<'_, F>,
) -> Result<()>
where F: FnMut(std::fmt::Arguments<'_>) -> io::Result<()>,
{
Ok(match self {
Pattern::Normal(data) => data.build(ctx, octx)?,
Pattern::IncludePattern(name) => {
octx.output(fa!("{{include: {name}}}"))?;
},
})
}
}

#[derive(Debug)]
pub struct Rule<'a> {
name: &'a str,
pats: Vec<Pattern<'a>>,
}
impl<'a> Rule<'a> {
pub fn update_group_count<F>(&mut self, mut f: F) -> Result<()>
where F: FnMut(&str) -> Option<u32>
{
self.pats.iter_mut()
.try_for_each(|pat| {
pat.update_group_count(&mut f)
})
}

pub fn build<F>(
&self,
ctx: &BuildContext<'_>,
octx: &mut OutputContext<'_, F>,
) -> Result<()>
where F: FnMut(std::fmt::Arguments<'_>) -> io::Result<()>,
{
octx.output(fa!("\"{}\": ", self.name))?;
match &self.pats[..] {
[one] => {
one.build(ctx, octx)
},
pats => {
octx.with_block(['[', ']'], |octx| {
if let Some(pat) = pats.first() {
pat.build(ctx, octx)?;
}
for pat in pats.iter().skip(1) {
octx.newline()?;
pat.build(ctx, octx)?;
}
Ok(())
})?
},
}
}
}

#[derive(Debug)]
pub struct BuildContext<'a> {
current_color: Cell<u32>,
rule_map: HashMap<String, Rule<'a>>,
rule_map: HashMap<String, RuleData<'a>>,
}
impl Default for BuildContext<'static> {
fn default() -> Self {
Expand Down Expand Up @@ -279,19 +362,18 @@ where F: FnMut(fmt::Arguments<'_>) -> io::Result<()>,
res
}

pub fn with_block<F1, R>(&mut self, f: F1) -> io::Result<R>
pub fn with_block<F1, R>(&mut self, ch: [char; 2], f: F1) -> io::Result<R>
where F1: FnOnce(&mut Self) -> R,
{
self.indent_level += 1;
(self.output)(fa!("{{"))?;
self.newline()?;
let res = self.with_indent(|this| {
(this.output)(fa!("{}", ch[0]))?;
this.newline()?;

let res = f(self);
io::Result::Ok(f(this))
})?;

self.indent_level -= 1;
self.newline()?;
(self.output)(fa!("}}"))?;
self.newline()?;
(self.output)(fa!("{}", ch[1]))?;

Ok(res)
}
Expand Down Expand Up @@ -320,11 +402,16 @@ where I: IntoIterator<Item = Rule<'a>>,
})?;

rule.build(ctx, octx)?;
octx.newline()?;

if let Some(rule) = ctx.rule_map
.insert((*rule.name).into(), rule)
if let Some(Pattern::Normal(data))
= rule.pats.into_iter().next()
{
return Err(Error::RepeatDefineName((*rule.name).into()));
if let Some(_) = ctx.rule_map
.insert((*rule.name).into(), data)
{
return Err(Error::RepeatDefineName((*rule.name).into()));
}
}
}
Ok(())
Expand Down
7 changes: 5 additions & 2 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,13 @@ fn main() -> io::Result<()> {
println!();
match e {
Error::UndefineRef(name) => {
eprintln!("BuildError: undefine reference {name}");
eprintln!("BuildError: undefine reference `{name}`");
},
Error::RepeatDefineName(name) => {
eprintln!("BuildError: repeat define name {name}");
eprintln!("BuildError: repeat define name `{name}`");
},
Error::RefNotARegexp(name) => {
eprintln!("BuildError: reference `{name}` is not a regexp define");
},
Error::IOError(e) => Err(e)?,
}
Expand Down
Loading

0 comments on commit c2b9823

Please sign in to comment.