sinoTrinity
sinoTrinity

Reputation: 1195

How to overload operator in Parsec/Megaparsec?

I am implementing a compiler using Parsec/Megaparsec as parser. I can't find a way to overload operator +, which I want to use for both integer addition and string concatenation. Is it possible?

Upvotes: 0

Views: 102

Answers (1)

K. A. Buhr
K. A. Buhr

Reputation: 50864

Start by writing your compiler to use a different operator for string concatenation, like @. When you've got it running and well tested, take a look at your code. You'll probably discover that one of two things has happened, depending on the language you're parsing and the compiler architecture you've used.

The first possibility is that the part of your parser that parses + is completely separate from the part of the parser that parses @ (e.g., they are in two different parser functions, one for parsing numeric expressions and a separate one for parsing string expressions). If this has happened, congratulations, you just need to replace "@" with "+", run a few tests, and you should be good to go.

The second possibility is that + and @ are parsed in the same place and produce AST nodes with different constructors:

data Expr ... =
  ...
  | Plus Expr Expr     -- the '+' operator
  | Concat Expr Expr   -- the '@' operator
  ...

In this case, you probably also have some part of your compiler that's generating code (and hopefully some type information):

codeGen (Plus e1 e2)
  = do (code1, typ1) <- codeGen e1
       (code2, typ2) <- codeGen e2
       if (typ1 == Num && typ2 == Num)
         then genPlus code1 code2
         else typeError "'+' needs numbers"
codeGen (Concat e1 e2)
  = do (code1, typ1) <- codeGen e1
       (code2, typ2) <- codeGen e2
       if (typ1 == Str && typ2 == Str)
         then genConcat code1 code2
         else typeError "'@' needs strings"

In this case, you should modify the parser/AST to collapse the AST to just one shared constructor:

data Expr ... =
  ...
  | ConcatPlus Expr Expr     -- the '+' operator for numbers and strings
  ...

and handle both cases in the code generator, depending on available type information:

codeGen (ConcatPlus e1 e2)
  = do (code1, typ1) <- codeGen e1
       (code2, typ2) <- codeGen e2
       case (typ1, typ2) of
           (Num, Num) -> genPlus code1 code2
           (Str, Str) -> genConcat code1 code2
           _ -> typeError "'+' arguments must have same type (numbers or strings)"

If your compiler doesn't look like these examples, you'll have to post some code so we know what it does look like.

Upvotes: 1

Related Questions