我在Happy官方网站上给出了一个快乐解析器中的这个语法部分,但是我需要对括号中规则的含义进行更深入的解释。这是令牌定义
<snip>
<!-- OutlineGroupNode is not supported --><br>
<ul>
<li>
<p lang="en-GB" style="margin-top:0pt;margin-bottom:0pt">
Top level no tag</p>
<ul>
<li style="list-style-type:circle"><span lang="en-GB"
data-tag="to-do">Sub level with tag</span></li>
<li style="list-style-type:circle"><span lang="en-GB">Sub
level no tag</span></li>
</ul>
</li>
<li style="list-style: none"><br></li>
</ul>
</snip>
这里是语法部分
%token
let { TokenLet }
in { TokenIn }
int { TokenInt $$ }
var { TokenVar $$ }
'=' { TokenEq }
'+' { TokenPlus }
'-' { TokenMinus }
'*' { TokenTimes }
'/' { TokenDiv }
'(' { TokenOB }
')' { TokenCB }
我理解的是,文件中下面定义的词法分析器应该只生成定义类型的标记,然后使用语法构建解析树。但究竟是什么意思&#34; {让$ 2 $ 4 $ 6}&#34;?我知道$ 2指的是第二个规则参数,依此类推,但如果有人能给我一个&#34;人类阅读版本&#34;规则我会非常高兴。希望我已经清楚了。
提前致谢。
答案 0 :(得分:1)
此行是创建(解析)生产Exp
的一条规则:
Exp : let var '=' Exp in Exp { Let $2 $4 $6 }
它对应于规则:
if you see "let" ($1)
followed by a variable name ($2)
followed by "=" ($3)
followed by an Exp ($4)
followed by "in" ($5)
followed by another Exp ($6)
然后返回值Let $2 $4 $6
。 $n
参数将替换为每个子生产的值。因此,如果匹配此规则,将调用Let
函数(可能是某些数据构造函数):
var
标记的值作为第一个参数Exp
($ 4)作为第二个参数Exp
($ 6)作为第三个参数。我相信var
令牌的值是变量名。
答案 1 :(得分:1)
在%token
部分中,左列是语法中其他位置使用的令牌名称,右侧是可以在case
语句中使用的模式。在哪里看到$$
Happy会替换自己的变量。因此,如果生成的解析器在某个时刻期望一个Integer,则Happy将有一个包含TokenInt v1234
模式的case语句,其中v1234
位是Happy创建的变量名。
&#34;让&#34;是被识别的语法表达式的构造函数。如果你在示例页面中看起来稍微低一些,你会看到
data Exp
= Let String Exp Exp
| Exp1 Exp1
deriving Show
因此Let
构造函数接受一个字符串和两个子表达式(类型为&#39; Exp&#39;)。如果查看语法,可以看到let
规则中有六个元素。第一个是常量字符串&#34; let&#34;。生成的解析器使用它来确定它正在查看&#34; let&#34;子句,但生成的解析树不需要它。所以$1
没有出现。相反,Let
构造函数的第一个参数必须是绑定变量的名称,这是语法规则中的第二个项目。因此这是$2
。其他的是两个子表达式,它们是$4
和$6
的相同逻辑。这两个都可以是任意复杂的表达式:快乐计算它们开始和结束的位置,并通过遵循构成表达式的其他规则来解析它们。