0

I am stuck at a point in converting a expression entered by the user to my own datatype

I did it using biuldExpressionParser , but using simple parser and recursion I did as follows

 openBrace = char '('

 closeBrace :: GenParser Char st Char
 closeBrace = char ')'

bracketExpr = do
            spaces >> openBrace
            expr <- expressionParser
            spaces >> closeBrace
            return expr

bracketExpr will return the entered expression in my own datatype

to convert it into my datatype I did for negation,if expression is a number or a variable as follows:

 expressionParser = negate1
                 <|> number
                 <|> variable
                 --<|> addition
                 <?> "simple expression"

 negate1 :: Parser Expr
 negate1 = do{ char '-'
             ;ds <-  number
             ;return (ExprNeg (ds) )
             }
        <?> "negate"

variable :: Parser Expr
variable = do{ ds<- many1 (letter <|> digit)
             ; return (ExprVar ds)}
         <?> "variable"

number :: Parser Expr
number = do{ ds<- many1 digit
           ; return (ExprNum (read ds))}
          <?> "number"

To do the same for addtion I tried by seperating the expression using sepBy but I am encountering several issues.

If the extered expreesion is 1+2 Then I should getExprAdd (ExprNum 1) (ExprNum 2)

I am unable to proceed further from here .Help would be great.

Thank you.

1

1 Answer 1

1

If you want to be writing a parser with parser combinators you need to think in terms of high-level rules first. Here's a skeleton parser in Parsec; it does not 100% meet your needs because all of the operators are same-precedence and right-associative, whereas you probably want different precedences and left-associativity. Still, this is the basic way to write a parser:

import Text.Parsec
import Text.Parsec.Char
import Data.Char (isDigit)

-- basic data type
data Expr = Op Char Expr Expr | N Integer deriving (Show)
type Parser x = Parsec String () x

-- reverse-sequenced >>, used to implement `parenthesized` and `whitespaced`
(<<) :: Monad m => m x -> m y -> m x
mx << my = mx >>= \x -> my >> return x
infixl 1 <<

parenthesized :: Parser e -> Parser e
parenthesized e = char '(' >> e << char ')'

whitespaced :: Parser e -> Parser e
whitespaced e = spaces >> e << spaces

number :: Parser Expr
number = do
    c <- oneOf "123456789" -- leading 0's can be reserved for octal/hexadecimal
    cs <- many digit
    return (N (read (c:cs)))

operator :: Parser Expr
operator = do
    e1 <- expr_no_op
    o <- whitespaced (oneOf "+*/-")
    e2 <- expression
    return (Op o e1 e2)

expr_no_op :: Parser Expr
expr_no_op = whitespaced (try number <|> parenthesized expression)

expression :: Parser Expr
expression = whitespaced (try operator <|> try number <|> parenthesized expression)

Notice that you define tokens (above, just 'number') and then combine them with a "try this <|> try that <|> otherwise..." syntax. Notice also that you have to stop operator from taking an expression as its first argument otherwise you'll get a operator -> expression -> operator loop in the parsing. This is called "left factoring."

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.