noob wants make a parser for a small language

207 views Asked by At

I want make a parser in happy for the let-in-expression language. For example, i want parse the following string:

let x = 4 in x*x

At the university we study attribute grammars, and i want use this tricks to calculate directly the value of the parsed let-in-expression. So in the happy file, i set the data type of the parsing function to Int, and i created a new attribute called env. This attribute is a function from String to Int that associates variable name to value. Referring to my example:

env "x" = 4

Now i put here below the happy file, where there is my grammar:

{
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"

}

When i load the haskell file generated from the happy file above, i get the following error:

    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')

I don't know why i get this, because i don't define the type Parser.Int in my happy file. I tried to replace Int with Prelude.Int, but i get other errors.

How can i resolve? Can i have also some general tips if I'm doing something not optimal?

1

There are 1 answers

0
Thomas M. DuBuisson On BEST ANSWER

See the happy explaination of attributetype: http://www.haskell.org/happy/doc/html/sec-AtrributeGrammarsInHappy.html

Your line:

%attributetype { Int }

Is declaring a type named Int. This is what causes the ambiguity.