Haskell 语法意义

Haskell 语法意义,haskell,happy,Haskell,Happy,我在happy官方网站上的happy解析器中有这个语法部分,但我需要对括号中规则的含义进行更深入的解释。下面是令牌定义 %token let { TokenLet } in { TokenIn } int { TokenInt $$ } var { TokenVar $$ } '=' { TokenEq }

我在happy官方网站上的happy解析器中有这个语法部分,但我需要对括号中规则的含义进行更深入的解释。下面是令牌定义

%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
    标记的值作为第一个参数
  • 第一个
    Exp
    解析为($4)作为第二个参数
  • 第二个被解析的
    Exp
    ($6)作为第三个参数

我相信这里,
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
    标记的值作为第一个参数
  • 第一个
    Exp
    解析为($4)作为第二个参数
  • 第二个被解析的
    Exp
    ($6)作为第三个参数

我相信这里
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”无法将文档中的“+”链接到解析树中的“加号”。