语法快乐解析器意义

syntax happy parser meaning

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

%token 
      let             { TokenLet }
      in              { TokenIn }
      int             { TokenInt $$ }
      var             { TokenVar $$ }
      '='             { TokenEq }
      '+'             { TokenPlus }
      '-'             { TokenMinus }
      '*'             { TokenTimes }
      '/'             { TokenDiv }
      '('             { TokenOB }
      ')'             { TokenCB }

这里是语法部分

Exp   : let var '=' Exp in Exp  { Let    }
          | Exp1                    { Exp1  }

Exp1  : Exp1 '+' Term           { Plus   }
      | Exp1 '-' Term           { Minus   }
      | Term                    { Term  }

Term  : Term '*' Factor         { Times   }
      | Term '/' Factor         { Div   }
      | Factor                  { Factor  }

Factor            
      : int                     { Int  }
      | var                     { Var  }
      | '(' Exp ')'             { Brack  }

我的理解是,在文件下面定义的词法分析器应该只生成定义类型的标记,然后使用语法构建解析树。但是“{Let $2 $4 $6}”到底是什么意思呢?我知道 $2 指的是第二个规则参数等等,但如果有人能给我一个 "human read version" 的规则,我会非常高兴。希望我已经清楚了。

提前致谢。

这一行是创建(解析)产生式的一条规则Exp:

Exp   : let var '=' Exp in Exp  { Let    }

对应规则:

if you see "let"        ()
followed by a variable name  ()
followed by "="         ()
followed by an Exp      ()
followed by "in"        ()
followed by another Exp ()

然后 return 值 Let $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" 子句,但生成的解析树不需要它。所以 </code> 没有出现。 <code>Let 构造函数的第一个参数必须是被绑定变量的名称,这是语法规则中的第二项。因此这是 </code>。其他的是两个子表达式,按相同的逻辑是<code>。这两个表达式都可以是任意复杂的表达式:Happy 找出它们的开始和结束位置,并按照构成表达式的其他规则解析它们。