noob希望为一种小语言编写解析器

时间:2013-12-07 16:56:30

标签: parsing haskell happy

我想让一个解析器为let-in-expression语言感到高兴。例如,我想解析以下字符串:

let x = 4 in x*x

在大学里我们研究属性语法,我想用这个技巧直接计算解析后的let-in-expression的值。所以在happy文件中,我将解析函数的数据类型设置为Int,并创建了一个名为 env 的新属性。此属性是从String到Int的函数,它将变量名称与值相关联。参考我的例子:

env "x" = 4

现在我把这里放在快乐文件下面,那里有我的语法:

{
module Parser where

import Token
import Lexer
}

%tokentype { Token }

%token 
      let             { TLet }
      in              { TIn }
      int             { TInt $$ }
      var             { TVar $$ }
      '='             { TEq }
      '+'             { TPlus }
      '-'             { TMinus }
      '*'             { TMul }
      '/'             { TDiv }
      '('             { TOB }
      ')'             { TCB }

%name parse

%attributetype { Int }

%attribute env { String -> Int }

%error { parseError }

%%

Exp   : let var '=' Exp in Exp
            {
                $4.env = $$.env;
                $2.env = (\_ -> 0);
                $6.env = (\str -> if str == $2 then $4 else 0);
                $$ = $6;
            }
      | Exp1                    
            {
                $1.env = $$.env;
                $$ = $1;
            }

Exp1  : Exp1 '+' Term
            {
                $1.env = $$.env;
                $2.env = $$.env;
                $$ = $1 + $3;
            }
      | Exp1 '-' Term
            {
                $1.env = $$.env;
                $2.env = $$.env;
                $$ = $1 - $3;
            }
      | Term 
            {
                $1.env = $$.env;
                $$ = $1;
            }

Term  : Term '*' Factor
            {
                $1.env = $$.env;
                $2.env = $$.env;
                $$ = $1 * $3;
            }
      | Term '/' Factor
            {
                $1.env = $$.env;
                $2.env = $$.env;
                $$ = div $1 $3;
            }
      | Factor
            {
                $1.env = $$.env;
                $$ = $1;
            }

Factor            
      : int
            {
                $$ = $1;
            }
      | var
            {
                $$ = $$.env $1;
            }
      | '(' Exp ')'
            {
                $1.env = $$.env;
                $$ = $1;
            }

{
parseError :: [Token] -> a
parseError _ = error "Parse error"

}

当我加载从上面的快乐文件生成的haskell文件时,我收到以下错误:

    Ambiguous occurrence `Int'
It could refer to either `Parser.Int', defined at parser.hs:271:6
                      or `Prelude.Int',
                         imported from `Prelude' at parser.hs:2:8-13
                         (and originally defined in `GHC.Types')

我不知道为什么我得到这个,因为我没有在我喜欢的文件中定义类型Parser.Int。我试图用Prelude.Int替换Int,但是我得到了其他错误。

我该如何解决?如果我做的不是最佳的话,我还可以提供一些一般的提示吗?

1 个答案:

答案 0 :(得分:0)

请参阅属性类型的快乐解释:http://www.haskell.org/happy/doc/html/sec-AtrributeGrammarsInHappy.html

你的专栏:

%attributetype { Int }

声明名为Int的类型。这就是造成歧义的原因。