use makeExprParser for parsing

This commit is contained in:
Patrick Aldis 2026-01-15 15:49:32 +00:00
parent cc3ed6a35d
commit e437fd82c4
3 changed files with 31 additions and 35 deletions

View File

@ -82,7 +82,7 @@ test-suite haskell-exps-test
Test.SimpleParserSpec
library langfeatures
build-depends: base, containers, megaparsec
build-depends: base, containers, megaparsec, parser-combinators
hs-source-dirs: src
exposed-modules: Ologs, SimpleParser
ghc-options: -Wall

View File

@ -15,13 +15,16 @@
{-# LANGUAGE NoMonomorphismRestriction #-}
{-# OPTIONS_GHC -Wno-unrecognised-pragmas #-}
module SimpleParser
( eval, Expr (..), BinaryOp (..), UnaryOp (..), parseExpr ) -- literalParser
module SimpleParser (eval, Expr (..), BinaryOp (..), UnaryOp (..), parseExpr) -- literalParser
where
import Text.Megaparsec
import Control.Monad.Combinators.Expr
import Data.Functor (($>))
import Data.Void (Void)
import Text.Megaparsec
import Text.Megaparsec.Byte.Lexer (lexeme)
import Text.Megaparsec.Char (char, space)
import Text.Megaparsec.Char.Lexer (decimal)
import Text.Megaparsec.Char (char)
type Parser = Parsec Void String
@ -29,10 +32,10 @@ data BinaryOp = Add | Subtract | Multiply | Divide deriving (Show, Eq)
data UnaryOp = Negate deriving (Show, Eq)
data Expr =
BinaryExpr BinaryOp Expr Expr |
UnaryExpr UnaryOp Expr |
Literal Int
data Expr
= BinaryExpr BinaryOp Expr Expr
| UnaryExpr UnaryOp Expr
| Literal Int
deriving (Show, Eq)
lookUpBinaryOp :: BinaryOp -> Int -> Int -> Int
@ -50,28 +53,18 @@ eval (BinaryExpr binOp a b) = lookUpBinaryOp binOp (eval a) (eval b)
eval (UnaryExpr unaryOp a) = lookUpUnaryOp unaryOp (eval a)
parseExpr :: Parser Expr
parseExpr = choice [
try parseBinaryExpr,
parseExpr =
makeExprParser
parseLiteral
-- bracketedExpParser,
-- negatedExp
[ [InfixL (char '/' $> BinaryExpr Divide)]
, [InfixL (char '*' $> BinaryExpr Multiply)]
, [InfixL (char '+' $> BinaryExpr Add)]
, [InfixL (char '-' $> BinaryExpr Subtract)]
]
parseLiteral :: Parser Expr
parseLiteral = Literal <$> decimal
parseBinaryExpr :: Parser Expr
parseBinaryExpr = do
lhs <- parseExpr
binOp <- parseOp
rhs <- parseExpr
pure (BinaryExpr binOp lhs rhs)
parseOp :: Parser BinaryOp
parseOp = choice [
char '+' >> pure Add,
char '-' >> pure Subtract,
char '/' >> pure Divide,
char '*' >> pure Multiply
parseLiteral =
choice
[ Literal <$> decimal
, between (char '(') (char ')') parseExpr
]

View File

@ -36,5 +36,8 @@ spec = do
checkParse "2" (Literal 2)
checkParse "2+3" (BinaryExpr Add (Literal 2) (Literal 3))
checkParse "2+3+5" (BinaryExpr Add (BinaryExpr Add (Literal 2) (Literal 3)) (Literal 5))
checkParse "2+3*5" (BinaryExpr Add (Literal 2) (BinaryExpr Multiply (Literal 3) (Literal 5)))
checkParse "(2+3)*5" (BinaryExpr Multiply (BinaryExpr Add (Literal 2) (Literal 3)) (Literal 5) )
checkParse "((2+3))*5" (BinaryExpr Multiply (BinaryExpr Add (Literal 2) (Literal 3)) (Literal 5) )