title: Parsing arithmetic expression with Haskell Parsec
body: <p>I'm writing a arithmetic parser to treat expressions like "1+2-3". I use <a href="https://norasandler.com/2017/12/15/Write-a-Compiler-3.html#fn2" rel="nofollow noreferrer">this blog post</a> as reference. To treat left associativity and precedence, I write a parser with Parsec according to this BNF (from blog post).</p>
  
  <pre><code>&lt;exp&gt; ::= &lt;term&gt; { ("+" | "-") &lt;term&gt; }
  &lt;term&gt; ::= &lt;factor&gt; { ("*" | "/") &lt;factor&gt; }
  &lt;factor&gt; ::= "(" &lt;exp&gt; ")" | &lt;unary_op&gt; &lt;factor&gt; | &lt;int&gt;
  </code></pre>
  
  <p>This is my parser code.</p>
  
  <pre class="lang-hs prettyprint-override"><code>parseExp :: Parser Exp
  parseExp = do
    t1 &lt;- parseTerm
    loop t1
    where termSuffix t1 = do
            op &lt;- lexeme $ oneOf "+-"
            t2 &lt;- parseTerm
            case op of
              '+' -&gt; termSuffix (Binary Plus t1 t2)
              '-' -&gt; termSuffix (Binary Minus t1 t2)
          loop t = termSuffix t &lt;|&gt; return t
  
  parseTerm :: Parser Exp
  parseTerm = do
    f1 &lt;- parseFactor
    loop f1
    where factorSuffix f1 = do
            op &lt;- lexeme $ oneOf "*/"
            f2 &lt;- parseFactor
            case op of
              '*' -&gt; factorSuffix (Binary Mul f1 f2)
              '/' -&gt; factorSuffix (Binary Div f1 f2)
          loop t = factorSuffix t &lt;|&gt; return t
  
  parseFactor :: Parser Exp
  parseFactor = parseConst &lt;|&gt; parseParen &lt;|&gt; parseUnary
  
  parseParen = do
    void $ lexeme $ char '('
    e &lt;- parseExp
    void $ lexeme $ char ')'
    return e
  
  parseUnary :: Parser Exp
  parseUnary = do
    op &lt;- lexeme $ oneOf "!~-"
    f &lt;- parseFactor
    case op of
      '!' -&gt; return $ Unary LogNeg f
      '~' -&gt; return $ Unary BitCompl f
      '-' -&gt; return $ Unary ArithNeg f
  
  parseConst :: Parser Exp
  parseConst = do
    i &lt;- many1 digit
    return (Const $ read i)
  </code></pre>
  
  <p>I also used this tutorial code as reference. <a href="http://jakewheat.github.io/intro_to_parsing/#_simple_expr" rel="nofollow noreferrer">tutorial</a></p>
  
  <pre class="lang-hs prettyprint-override"><code>simpleExpr7 :: Parser SimpleExpr
  simpleExpr7 = do
      -- first parse a term
      e &lt;- term7
      -- then see if it is followed by an '+ expr' suffix
      maybeAddSuffix e
    where
      -- this function takes an expression, and parses a
      -- '+ expr' suffix, returning an Add expression
      -- it recursively calls itself via the maybeAddSuffix function
      addSuffix e0 = do
          void $ lexeme $ char '+'
          e1 &lt;- term7
          maybeAddSuffix (Add e0 e1)
      -- this is the wrapper for addSuffix, which adapts it so that if
      -- addSuffix fails, it returns just the original expression
      maybeAddSuffix e = addSuffix e &lt;|&gt; return e
  </code></pre>
  
  <p>My code doesn't work. This code works like this.</p>
  
  <pre><code>*Main CodeGen Parser&gt; parseWithEof parseExp "-2"
  Right (Unary ArithNeg (Const 2))
  *Main CodeGen Parser&gt; parseWithEof parseExp "(2)"
  Right (Const 2)
  *Main CodeGen Parser&gt; parseWithEof parseExp "-!(((2)))"
  Right (Unary ArithNeg (Unary LogNeg (Const 2)))
  *Main CodeGen Parser&gt; parseWithEof parseExp "1+2"
  Left (line 1, column 4):
  unexpected end of input
  expecting digit
  *Main CodeGen Parser&gt; parseWithEof parseExp "1+2+3"
  Left (line 1, column 6):
  unexpected end of input
  expecting digit
  *Main CodeGen Parser&gt; parseWithEof parseExp "1+2*3"
  Left (line 1, column 6):
  unexpected end of input
  expecting digit
  </code></pre>
  
  <p>I can't understand why this results <code>unexpected end of input</code>.</p>