Inspired by the following project, I am working with linear expressions and I have defined the following structure and parser.
data AExp
= Lit Rational
| Var String
| AExp : : AExp
| Rational :*: AExp
deriving (Eq)
import Text.Parsec
import Text.Parsec.Char
import Text.Parsec.Expr
import Text.Parsec.Language (javaStyle)
import Text.Parsec.String
import Control.Monad (void, ap)
import qualified Text.Parsec.Token as Token
Token.TokenParser {..} = Token.makeTokenParser javaStyle
binary name fun = Infix (fun <$ reservedOp name) AssocLeft
whitespace :: Parser ()
whitespace = void $ many $ oneOf " \n\t"
regularParse :: Parser a -> String -> Either ParseError a
regularParse p = parse p ""
rational :: Parser Rational
rational = do
whitespace
num <- many1 digit
void $ char '/'
den <- many1 digit
whitespace
return $ toRational $ (read num)/ (read den)
aexp :: Parser AExp
aexp = buildExpressionParser table term
where term = Lit <$> rational
<|> Var <$> identifier
<|> try ((:*:) <$> (rational <* reservedOp "*") <*> aexp)
<|> try (parens aexp)
table = [ [ binary " " (: :)]]
My problem is multiplication (:*:) and in general binary operations between two different types (Rational - AExp). The following example shows my result.
Main>regularParse aexp "10/1 * x"
Right (Lit 10 % 1)
That is, it does not match with multiplication (*), it matches with the literal variable Lit.
I have looked for some examples of parser of expressions, but in which I always found the multiplication is a binary operation between AExp, that is, the structure and parser are of this style:
data AExp
= Lit Rational
| Var String
| AExp: : AExp
| AExp:*: AExp
deriving (Eq)
aexp :: Parser AExp
aexp = buildExpressionParser table term
where term = Lit <$> rational
<|> Var <$> identifier
<|> try ((:*:) <$> (rational <* reservedOp "*") <*> aexp)
<|> try (parens aexp)
table = [[binary " " (: :)],
[binary "*" (:*:)]]
The project I am following is defined in this way.
I could try to take another focus for the parser, but for me it is easier to follow the project guide, since many of my structures are very similar.
How could I define the multiplication parser (:*:) or is there any example with to guide me?
Thanks in advance
CodePudding user response:
The problem is here:
term = Lit <$> rational
<|> ...
<|> try ((:*:) <$> (rational <* reservedOp "*") <*> aexp)
<|> ...
This will try parsing a lone rational
first; if that succeeds, the remaining branches will not be attempted. This policy of committing to the first successful parse was chosen for efficiency. Just changing the order will get you over this hump and to whatever your next problem will be (there's always one, isn't there??).
term = try ((:*:) <$> (rational <* reservedOp "*") <*> aexp)
<|> Lit <$> rational
<|> ...
CodePudding user response:
I thought a bit more about my original problem. I want to make a parser for linear expressions. A limited, but sufficient solution is:
varAExp :: Parser AExp
varAExp = do
x <- identifier
return $ Var x
aexp :: Parser AExp
aexp = buildExpressionParser table term
where term = try ((:*:) <$> (rational <* reservedOp "*") <*> varAExp)
<|> Lit <$> rational
<|> Var <$> identifier
<|> try (parens aexp)
table = [[binary " " (: :) ]]
With this parser I can work with expressions of this type:
arit_1 = regularParse aexp "10/1*x 3/2*y 1/1 3/1"
I cannot express the multiplication of numbers, but as I said before it is enough for me. thanks for your help