Haskell 语法意义
我在happy官方网站上的happy解析器中有这个语法部分,但我需要对括号中规则的含义进行更深入的解释。下面是令牌定义Haskell 语法意义,haskell,happy,Haskell,Happy,我在happy官方网站上的happy解析器中有这个语法部分,但我需要对括号中规则的含义进行更深入的解释。下面是令牌定义 %token let { TokenLet } in { TokenIn } int { TokenInt $$ } var { TokenVar $$ } '=' { TokenEq }
%token
let { TokenLet }
in { TokenIn }
int { TokenInt $$ }
var { TokenVar $$ }
'=' { TokenEq }
'+' { TokenPlus }
'-' { TokenMinus }
'*' { TokenTimes }
'/' { TokenDiv }
'(' { TokenOB }
')' { TokenCB }
这里是语法部分
Exp : let var '=' Exp in Exp { Let $2 $4 $6 }
| Exp1 { Exp1 $1 }
Exp1 : Exp1 '+' Term { Plus $1 $3 }
| Exp1 '-' Term { Minus $1 $3 }
| Term { Term $1 }
Term : Term '*' Factor { Times $1 $3 }
| Term '/' Factor { Div $1 $3 }
| Factor { Factor $1 }
Factor
: int { Int $1 }
| var { Var $1 }
| '(' Exp ')' { Brack $2 }
我的理解是,下面在文件中定义的lexer应该只生成定义类型的标记,然后使用语法构建解析树。但是exactley是什么意思“{让2美元4美元6}”?我知道$2指的是第二个规则参数等等,但是如果有人能给我一个“人类阅读版本”的规则,我会非常高兴。希望我已经说清楚了
提前感谢。这一行是创建(解析)产品
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)
然后返回值让$2$4$6
。$n
参数将替换为每个子产品的值。因此,如果匹配此规则,则调用Let
函数(可能是某个数据构造函数):
标记的值作为第一个参数var
- 第一个
解析为($4)作为第二个参数Exp
- 第二个被解析的
($6)作为第三个参数Exp
我相信这里,
var
标记的值就是变量名。这一行是创建(解析)产品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)
然后返回值让$2$4$6
。$n
参数将替换为每个子产品的值。因此,如果匹配此规则,则调用Let
函数(可能是某个数据构造函数):
标记的值作为第一个参数var
- 第一个
解析为($4)作为第二个参数Exp
- 第二个被解析的
($6)作为第三个参数Exp
我相信这里
var
标记的值是变量名。在%token
部分,左栏是语法中其他地方使用的标记名,右栏是可以在case
语句中使用的模式。在您看到的地方,$
Happy将替换它自己的变量。因此,如果生成的解析器在某一点上需要一个整数,那么Happy将有一个case语句,该语句的模式包括TokenInt v1234
,其中v1234
位是Happy创建的变量名
“Let”是被识别语法表达式的构造函数。如果在示例页面中看得低一点,您将看到
data Exp
= Let String Exp Exp
| Exp1 Exp1
deriving Show
因此,
Let
构造函数接受一个字符串和两个子表达式(类型为“Exp”)。如果你看一下语法,你会发现let
规则中有六个元素。第一个是常量字符串“let”。生成的解析器使用它来确定它正在查看一个“let”子句,但生成的解析树不需要它。因此,$1
不会出现。相反,Let
构造函数的第一个参数必须是要绑定的变量的名称,这是语法规则中的第二项。因此这是$2
。另外还有两个子表达式,它们是$4
和$6
,逻辑相同。这两个表达式都可以是任意复杂的表达式:Happy找出它们的开始和结束位置,并根据表达式的其他组成规则对它们进行解析。在%token
部分,左列是语法中其他地方使用的标记名,右边是一个模式,可以在case
语句中使用。在您看到的地方,$
Happy将替换它自己的变量。因此,如果生成的解析器在某一点上需要一个整数,那么Happy将有一个case语句,该语句的模式包括TokenInt v1234
,其中v1234
位是Happy创建的变量名
“Let”是被识别语法表达式的构造函数。如果在示例页面中看得低一点,您将看到
data Exp
= Let String Exp Exp
| Exp1 Exp1
deriving Show
因此,
Let
构造函数接受一个字符串和两个子表达式(类型为“Exp”)。如果你看一下语法,你会发现let
规则中有六个元素。第一个是常量字符串“let”。生成的解析器使用它来确定它正在查看一个“let”子句,但生成的解析树不需要它。因此,$1
不会出现。相反,Let
构造函数的第一个参数必须是要绑定的变量的名称,这是语法规则中的第二项。因此这是$2
。另外还有两个子表达式,它们是$4
和$6
,逻辑相同。这两个表达式都可以是任意复杂的表达式:Happy找出它们的开始和结束位置,并按照表达式的其他组成规则对它们进行解析。您好,谢谢大家的回答。例如,在操作中,“Plus$1$3”不足以写入$$=$1+$3?Plus是您在Haskell中使用的构造函数,而“+”是您在已解析文档的语法中找到的东西。您的“$$=$1+$3”没有任何内容可以将文档中的“+”与解析树中的“加号”链接起来。您好,谢谢大家的回答。例如,在操作中,“Plus$1$3”不足以写入$$=$1+$3?Plus是您在Haskell中使用的构造函数,而“+”是您在已解析文档的语法中找到的东西。您的“$$=$1+$3”无法将文档中的“+”链接到解析树中的“加号”。