parsinghaskelllexerhappyalex

Haskell parser created with Alex and Happy doesn't work because of main function, someone can tell me why?


Basically i just created a parser to print the derivation tree of a Reverse Polish Notation expression, which recognizes regular expression built in RPN, tokenizes them recognizes only the expressions RPN built-like and should return the derivation tree. The problem is that the main function doesn't do its work, but if i run manually what's inside the main function, then it just do what it is supposed to do!

--Alex lexer

Recognizes all the tokens which can be find in a RPN expression: int numbers and chars for basic operations +,-,*,/

{
    module Lexical (Token(..), lexer) where
}

%wrapper "basic"

$digit = [0-9]
@int = $digit+

tokens :-
    $white+     ;
    "--".*      ;
    \+          {\s -> TokenPlus}
    \-          {\s -> TokenMinus}
    \*          {\s -> TokenTimes}
    \/          {\s -> TokenDiv}
    @int        {\s -> TokenInt (read s)}

{
data Token
    = TokenPlus
    | TokenMinus
    | TokenTimes
    | TokenDiv
    | TokenInt Int
    deriving (Eq,Show)

            
lexer = alexScanTokens
}

--Happy parser

Recognizes all the expressions built in RPN and should print the equivalent derivation tree using the data constructor Exp. For the context, i know i could even use the Tree data constructor but Exp helps me understand better how i want my expressions to be printed.

{
module Main where
import Lexical
}

%name calc
%tokentype {Token}
%error {parseError}

%token
    '+'         {TokenPlus}
    '-'         {TokenMinus}
    '*'         {TokenTimes}
    '/'         {TokenDiv}
    int         {TokenInt $$}

%left '+' '-'
%left '*' '/'

%%

Exp : Exp Exp '+'       { Plus $1 $2 }
    | Exp Exp '-'       { Minus $1 $2 }
    | Exp Exp '*'       { Times $1 $2 }
    | Exp Exp '/'       { Div $1 $2 }
    | int               { Int $1 }

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

data Exp = Plus Exp Exp
         | Minus Exp Exp
         | Times Exp Exp
         | Div Exp Exp
         | Int Int 
         deriving (Eq, Show)

main = do
        s <- getContents
        print(calc (lexer s))
}

The problem is in the main function: if i just run for example

print (calc (lexer "3 4 5 + *"))

it just returns what i expect, which is:

Times (Int 3) (Plus (Int 4) (Int 5))

but if i execute "happy parser.y" and then "ghci parser.hs", it will compile fine but as soon as i call the main function, it lets me write the RPN expressions i want but it just does or prints nothing! If someone can help me i will be so grateful


Solution

  • Based on the question, I think that you see getContents as a "prompt" that reads a line and then ends. But getContents reads all lines until the stream closes. You can in most shells close the stream with Ctrl+D, so then getContents is finished.

    If you want to parse only a single line, you use getLine :: IO String:

    main = do
      s <- getLine
      print (calc (lexer s))