替代版本的语法无法正常工作
Alternate version of grammar not working as I'd prefer
此代码按我的意愿解析 $string
:
#! /usr/bin/env raku
my $string = q:to/END/;
aaa bbb # this has trailing spaces which I want to keep
kjkjsdf
kjkdsf
END
grammar Markdown {
token TOP { ^ ([ <blank> | <text> ])+ $ }
token blank { [ \h* <.newline> ] }
token text { <indent> <content> }
token indent { \h* }
token newline { \n }
token content { \N*? <trailing>* <.newline> }
token trailing { \h+ }
}
my $match = Markdown.parse($string);
$match.say;
输出
「aaa bbb
kjkjsdf
kjkdsf
」
0 => 「aaa bbb
」
text => 「aaa bbb
」
indent => 「」
content => 「aaa bbb
」
trailing => 「 」
0 => 「
」
blank => 「
」
0 => 「 kjkjsdf
」
text => 「 kjkjsdf
」
indent => 「 」
content => 「kjkjsdf
」
0 => 「kjkdsf
」
text => 「kjkdsf
」
indent => 「」
content => 「kjkdsf
」
现在,我遇到的唯一问题是我希望 <trailing>
级别与 <indent>
和 <content
> 捕获处于同一层次结构级别.
所以我尝试了这个语法:
grammar Markdown {
token TOP { ^ ([ <blank> | <text> ])+ $ }
token blank { [ \h* <.newline> ] }
token text { <indent> <content> <trailing>* <.newline> }
token indent { \h* }
token newline { \n }
token content { \N*? }
token trailing { \h+ }
}
但是,它破坏了解析。所以我尝试了这个:
token TOP { ^ ([ <blank> | <text> ])+ $ }
token blank { [ \h* <.newline> ] }
token text { <indent> <content>*? <trailing>* <.newline> }
token indent { \h* }
token newline { \n }
token content { \N }
token trailing { \h+ }
并得到:
0 => 「aaa bbb
」
text => 「aaa bbb
」
indent => 「」
content => 「a」
content => 「a」
content => 「a」
content => 「 」
content => 「b」
content => 「b」
content => 「b」
trailing => 「 」
0 => 「
」
blank => 「
」
0 => 「 kjkjsdf
」
text => 「 kjkjsdf
」
indent => 「 」
content => 「k」
content => 「j」
content => 「k」
content => 「j」
content => 「s」
content => 「d」
content => 「f」
0 => 「kjkdsf
」
text => 「kjkdsf
」
indent => 「」
content => 「k」
content => 「j」
content => 「k」
content => 「d」
content => 「s」
content => 「f」
这与我想要的非常接近,但它具有将 <content>
分解成单个字母的不良效果,这并不理想。我可以在事后通过按摩 $match
对象很容易地解决这个问题,但我想尝试提高我的语法技能。
我能够通过否定的先行断言实现我想要的:
token TOP { ^ ([ <blank> | <text> ])+ $ }
token blank { [ \h* <.newline> ] }
token text { <indent>? <content> <trailing>? <.newline> }
token indent { \h+ }
token newline { \n }
token content { <.non_trailing> }
token non_trailing { ( . <!before \w \h* \n>)+ \S* }
token trailing { \h+ }
<.non_trailing>
禁止单个字符出现在匹配对象中,. <!before \w \h* \n>)+ \S*
位将匹配任何不后跟白色 space 和新行的字符,\S*
位获取负前瞻留下的字符。
输出
「aaa bbb
kjkjsdf
kjkdsf
」
0 => 「aaa bbb
」
text => 「aaa bbb
」
content => 「aaa bbb」
trailing => 「 」
0 => 「
」
blank => 「
」
0 => 「 kjkjsdf
」
text => 「 kjkjsdf
」
indent => 「 」
content => 「kjkjsdf」
0 => 「kjkdsf
」
text => 「kjkdsf
」
content => 「kjkdsf」
快速而肮脏
my $string = q:to/END/;
aaa bbb
kjkjsdf
kjkdsf
END
grammar Markdown {
token TOP { ^ ([ <blank> | <text> ])+ $ }
token blank { [ \h* <.newline> ] }
token text { <indent>? $<content>=\N*? <trailing>? <.newline> }
token indent { \h+ }
token newline { \n }
token trailing { \h+ }
}
my $match = Markdown.parse($string);
$match.say;
前瞻断言
my $string = q:to/END/;
aaa bbb
kjkjsdf
kjkdsf
END
grammar Markdown {
token TOP { ^ ([ <blank> | <text> ])+ $ }
token blank { [ \h* <.newline> ] }
token text { <indent>? <content> <trailing>? <.newline> }
token indent { \h+ }
token newline { \n }
token content { [<!before <trailing>> \N]+ }
token trailing { \h+ $$ }
}
my $match = Markdown.parse($string);
$match.say;
一点重构
my $string = q:to/END/;
aaa bbb
kjkjsdf
kjkdsf
END
grammar Markdown {
token TOP { ( <blank> | <text> )+ %% \n }
token blank { ^^ \h* $$ }
token text { <indent>? <content> <trailing>? }
token indent { ^^ \h+ }
token content { [<!before <trailing>> \N]+ }
token trailing { \h+ $$ }
}
my $match = Markdown.parse($string);
$match.say;
此代码按我的意愿解析 $string
:
#! /usr/bin/env raku
my $string = q:to/END/;
aaa bbb # this has trailing spaces which I want to keep
kjkjsdf
kjkdsf
END
grammar Markdown {
token TOP { ^ ([ <blank> | <text> ])+ $ }
token blank { [ \h* <.newline> ] }
token text { <indent> <content> }
token indent { \h* }
token newline { \n }
token content { \N*? <trailing>* <.newline> }
token trailing { \h+ }
}
my $match = Markdown.parse($string);
$match.say;
输出
「aaa bbb
kjkjsdf
kjkdsf
」
0 => 「aaa bbb
」
text => 「aaa bbb
」
indent => 「」
content => 「aaa bbb
」
trailing => 「 」
0 => 「
」
blank => 「
」
0 => 「 kjkjsdf
」
text => 「 kjkjsdf
」
indent => 「 」
content => 「kjkjsdf
」
0 => 「kjkdsf
」
text => 「kjkdsf
」
indent => 「」
content => 「kjkdsf
」
现在,我遇到的唯一问题是我希望 <trailing>
级别与 <indent>
和 <content
> 捕获处于同一层次结构级别.
所以我尝试了这个语法:
grammar Markdown {
token TOP { ^ ([ <blank> | <text> ])+ $ }
token blank { [ \h* <.newline> ] }
token text { <indent> <content> <trailing>* <.newline> }
token indent { \h* }
token newline { \n }
token content { \N*? }
token trailing { \h+ }
}
但是,它破坏了解析。所以我尝试了这个:
token TOP { ^ ([ <blank> | <text> ])+ $ }
token blank { [ \h* <.newline> ] }
token text { <indent> <content>*? <trailing>* <.newline> }
token indent { \h* }
token newline { \n }
token content { \N }
token trailing { \h+ }
并得到:
0 => 「aaa bbb
」
text => 「aaa bbb
」
indent => 「」
content => 「a」
content => 「a」
content => 「a」
content => 「 」
content => 「b」
content => 「b」
content => 「b」
trailing => 「 」
0 => 「
」
blank => 「
」
0 => 「 kjkjsdf
」
text => 「 kjkjsdf
」
indent => 「 」
content => 「k」
content => 「j」
content => 「k」
content => 「j」
content => 「s」
content => 「d」
content => 「f」
0 => 「kjkdsf
」
text => 「kjkdsf
」
indent => 「」
content => 「k」
content => 「j」
content => 「k」
content => 「d」
content => 「s」
content => 「f」
这与我想要的非常接近,但它具有将 <content>
分解成单个字母的不良效果,这并不理想。我可以在事后通过按摩 $match
对象很容易地解决这个问题,但我想尝试提高我的语法技能。
我能够通过否定的先行断言实现我想要的:
token TOP { ^ ([ <blank> | <text> ])+ $ }
token blank { [ \h* <.newline> ] }
token text { <indent>? <content> <trailing>? <.newline> }
token indent { \h+ }
token newline { \n }
token content { <.non_trailing> }
token non_trailing { ( . <!before \w \h* \n>)+ \S* }
token trailing { \h+ }
<.non_trailing>
禁止单个字符出现在匹配对象中,. <!before \w \h* \n>)+ \S*
位将匹配任何不后跟白色 space 和新行的字符,\S*
位获取负前瞻留下的字符。
输出
「aaa bbb
kjkjsdf
kjkdsf
」
0 => 「aaa bbb
」
text => 「aaa bbb
」
content => 「aaa bbb」
trailing => 「 」
0 => 「
」
blank => 「
」
0 => 「 kjkjsdf
」
text => 「 kjkjsdf
」
indent => 「 」
content => 「kjkjsdf」
0 => 「kjkdsf
」
text => 「kjkdsf
」
content => 「kjkdsf」
快速而肮脏
my $string = q:to/END/;
aaa bbb
kjkjsdf
kjkdsf
END
grammar Markdown {
token TOP { ^ ([ <blank> | <text> ])+ $ }
token blank { [ \h* <.newline> ] }
token text { <indent>? $<content>=\N*? <trailing>? <.newline> }
token indent { \h+ }
token newline { \n }
token trailing { \h+ }
}
my $match = Markdown.parse($string);
$match.say;
前瞻断言
my $string = q:to/END/;
aaa bbb
kjkjsdf
kjkdsf
END
grammar Markdown {
token TOP { ^ ([ <blank> | <text> ])+ $ }
token blank { [ \h* <.newline> ] }
token text { <indent>? <content> <trailing>? <.newline> }
token indent { \h+ }
token newline { \n }
token content { [<!before <trailing>> \N]+ }
token trailing { \h+ $$ }
}
my $match = Markdown.parse($string);
$match.say;
一点重构
my $string = q:to/END/;
aaa bbb
kjkjsdf
kjkdsf
END
grammar Markdown {
token TOP { ( <blank> | <text> )+ %% \n }
token blank { ^^ \h* $$ }
token text { <indent>? <content> <trailing>? }
token indent { ^^ \h+ }
token content { [<!before <trailing>> \N]+ }
token trailing { \h+ $$ }
}
my $match = Markdown.parse($string);
$match.say;