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 Test.SimpleParserSpec
library langfeatures library langfeatures
build-depends: base, containers, megaparsec build-depends: base, containers, megaparsec, parser-combinators
hs-source-dirs: src hs-source-dirs: src
exposed-modules: Ologs, SimpleParser exposed-modules: Ologs, SimpleParser
ghc-options: -Wall ghc-options: -Wall

View File

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

View File

@ -36,5 +36,8 @@ spec = do
checkParse "2" (Literal 2) checkParse "2" (Literal 2)
checkParse "2+3" (BinaryExpr Add (Literal 2) (Literal 3)) 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 (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) )