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
Based on the question, I think that you see
getContents
as a "prompt" that reads a line and then ends. ButgetContents
reads all lines until the stream closes. You can in most shells close the stream with Ctrl+D, so thengetContents
is finished.If you want to parse only a single line, you use
getLine :: IO String
: