我正在尝试使用Perl6语法实现Markdown解析器,并被块引用卡住了。 blockquote段落不能用嵌套的大括号表示,因为它是特定格式的行的列表。但是从语义上讲,这是一个嵌套的markdown。
基本上,所有这些都归结为以下定义:
token mdBlockquote {
<mdBQLine>+ {
my $quoted = [~] $m<mdBQLine>.map: { $_<mdBQLineBody> };
}
}
mdBQLine
令牌的实际实现与此处无关。要注意的唯一重要的事情是,mdBQLineBody
键包含实际上已被引号括起来的行,其中>
已经被去除。毕竟,对于一个块:
> # quote1
> quote2
>
> quote3
quote3.1
$quoted
标量将包含:
# quote1
quote2
quote3
quote3.1
现在,最重要的是要解析以上数据并将其注入回Match
对象$/
中。这就是我完全不知所措的地方。最明显的解决方案:
token mdBlockquote {
<mdBQLine>+ {
my $quoted = [~] $m<mdBQLine>.map: { $_<mdBQLineBody> };
$<mdBQParsed> = self.parse( $quoted, actions => self.actions );
}
}
一次失败有两个原因:首先,$/
是只读对象;其次,.parse
是只读对象。其次,import pandas as pd
import numpy as np
df= pd.DataFrame(np.nan, columns =["A","B","C"], index =np.arange(5))
对其进行了有效的修改,使得无法将任何东西注入原始树。
有什么解决方案,然后对解析的数据进行后分析,提取并重新解析块引用,重复...吗?
答案 0 :(得分:6)
扩展@HåkonHægland的评论...
$/
是一个只读对象,有效地使其无法向原始树中注入任何东西。
不太清楚:
从本质上讲,$/
是一个符号,而不是一个对象,无论它是否绑定到一个对象。像P6中的任何其他符号一样,它始终可以自由反弹。 ($/ := 42
将始终有效。)
但是您指的是分配。分配的语义由要分配给的项目确定。如果它们是不是容器的普通对象,则它们将不支持lvalue语义,如果尝试为其分配它们,则会出现Cannot modify an immutable ...
错误。在这种意义上,Match
对象是不可变的。
您可以做的是通过使用Match
方法将任意数据挂在任何.make
对象上。 (make
例程在$/
上调用此方法。)这是将自定义数据存储在解析树中的方式。
要访问在解析树/ Match
对象的给定节点中所做的操作,请在该节点上调用.made
(或.ast
,这是同义词)。
make
通常用于解析树中的较高节点,其中包括针对较低层节点所做的。
请尝试以下未经测试的代码,看看能得到什么,然后注释一下它是否失败了,您无法找到使之运行的方法,或者从上面的最后两段考虑到那里,评论其效果:
token mdBlockquote {
<mdBQLine>+ {
make .parse: [~] $m<mdBQLine>.map: { $_<mdBQLineBody> };
}
}
答案 1 :(得分:5)
好的,这是我使用的最终解决方案。语法规则如下:
token mdBlockquote {
<mdBQLine>+ {
my $m = $/;
my $bq-body = [~] $m<mdBQLine>.map( { $_<mdBQLineBody> } );
$m.make(
self.WHAT.parse(
$bq-body,
actions => self.actions.clone,
)
);
}
}
这里的重要技巧是备份$/
中的$m
,因为.parse
将取代它。
在调用$bq-body
之前,Blockquote主体已预取到.parse
中,因为如果将表达式直接作为参数传递,则会产生令人困惑的副作用。
.parse
上调用 self.WHAT
以避免弄乱当前的语法对象。
此规则将以$m.ast
结尾,其中包含一个Match
对象,该对象又将包含操作生成的数据。然后,相应的动作方法将执行以下操作:
method mdBlockquote ($m) {
my $bq = self.makeNode( "Blockquote" );
$bq.push( $m.ast.ast );
$m.make( $bq );
}
由于action对象构建了适用于将markdown轻松转换为其他格式的简化AST,因此此处发生的事情是,它获取由递归.parse
生成的那棵树的分支并将其移植到主树中。 / p>
很棒的是,该代码支持开箱即用的嵌套块引用,不需要特殊处理。不好的是,它仍然是很多额外的代码,而类似:
token mdBlockquote {
<mdBQLine>+ $<mdBQBody>={
my $bq-body = [~] $<mdBQLine>.map( { $_<mdBQLineBody> } );
self.WHAT.parse(
$bq-body,
actions => self.actions.clone,
);
}
}
看起来会更好,并且不需要采取超出正常职责范围的干预行动。