Expression Parser and Parser Config

This commit is contained in:
VegOwOtenks 2025-01-18 22:23:43 +01:00
parent 839e278e43
commit 212eecfdf7
3 changed files with 115 additions and 4 deletions

16
src/Ubc/Parse/Config.hs Normal file
View file

@ -0,0 +1,16 @@
module Ubc.Parse.Config
( Config(..)
, defaultConfig
)
where
import Data.Set (Set)
import qualified Data.Set as Set
data Config = Config
{ includePaths :: Set FilePath
}
defaultConfig :: Config
defaultConfig = Config (Set.singleton ".")

View file

@ -0,0 +1,95 @@
module Ubc.Parse.Expression
( Expression(..)
, BinaryOperator(..)
, expressionParser
)
where
import Control.Monad ( (<$!>) )
import Data.Functor
import Text.Parsec.Expr (Operator(Infix), Assoc (AssocLeft), buildExpressionParser)
import qualified Ubc.Parse.Language as UbcLanguage
import Text.Parsec (ParsecT, (<|>), (<?>), choice, option)
data Expression = Binary BinaryOperator Expression Expression
| ConstantInteger Integer
| FunctionCall String [Expression]
| Variable String
| If Expression Expression (Maybe Expression)
deriving (Show)
data BinaryOperator = Plus
| Minus
| Multiply
| Divide
| Modulo
| ShiftLeft
| ShiftRight
| LessThan
| GreaterThan
| LessEqual
| GreaterEqual
| Equal
| NotEqual
| BitAnd
| BitOr
| BitXor
deriving (Show)
operatorTable :: Monad m => [[Operator String u m Expression]]
operatorTable =
[
[ Infix (UbcLanguage.reservedOperator "*" >> return (Binary Multiply)) AssocLeft
, Infix (UbcLanguage.reservedOperator "/" >> return (Binary Divide)) AssocLeft
, Infix (UbcLanguage.reservedOperator "%" >> return (Binary Modulo)) AssocLeft
]
,
[ Infix (UbcLanguage.reservedOperator "+" >> return (Binary Plus)) AssocLeft
, Infix (UbcLanguage.reservedOperator "-" >> return (Binary Minus)) AssocLeft
]
,
[ Infix (UbcLanguage.reservedOperator "<<" >> return (Binary ShiftLeft)) AssocLeft
, Infix (UbcLanguage.reservedOperator ">>" >> return (Binary ShiftRight)) AssocLeft
]
,
[ Infix (UbcLanguage.reservedOperator ">=" >> return (Binary GreaterEqual)) AssocLeft
, Infix (UbcLanguage.reservedOperator "<=" >> return (Binary LessEqual)) AssocLeft
, Infix (UbcLanguage.reservedOperator "<" >> return (Binary LessThan)) AssocLeft
, Infix (UbcLanguage.reservedOperator ">" >> return (Binary GreaterThan)) AssocLeft
]
,
[ Infix (UbcLanguage.reservedOperator "==" >> return (Binary Equal)) AssocLeft
, Infix (UbcLanguage.reservedOperator "!=" >> return (Binary NotEqual)) AssocLeft
]
,
[ Infix (UbcLanguage.reservedOperator "&" >> return (Binary BitAnd)) AssocLeft
, Infix (UbcLanguage.reservedOperator "|" >> return (Binary BitOr)) AssocLeft
, Infix (UbcLanguage.reservedOperator "^" >> return (Binary BitXor)) AssocLeft
]
]
expressionParser :: (Monad m) => ParsecT String u m Expression
expressionParser = buildExpressionParser operatorTable termParser <?> "expression"
termParser :: Monad m => ParsecT String u m Expression
termParser = UbcLanguage.parens expressionParser
<|> fmap ConstantInteger UbcLanguage.integer
<|> expressionIf
<|> functionCallOrVariable
expressionIf :: Monad m => ParsecT String u m Expression
expressionIf = do
_ <- UbcLanguage.reserved "if"
condition <- expressionParser
_ <- UbcLanguage.reserved "then"
then_ <- expressionParser
else_ <- option Nothing (UbcLanguage.reserved "else" >> expressionParser <&> Just)
return $ If condition then_ else_
functionCallOrVariable :: Monad m => ParsecT String u m Expression
functionCallOrVariable = do
name <- UbcLanguage.identifier
choice
[ FunctionCall name <$!> UbcLanguage.parens (UbcLanguage.commaSeparated expressionParser)
, return $ Variable name
]

View file

@ -53,10 +53,10 @@ languageDef = LanguageDef {
, nestedComments = True
, identStart = letter <|> char '_'
, identLetter = alphaNum <|> char '_'
, opStart = oneOf "+-*/"
, opLetter = oneOf "+-*/"
, reservedNames = [ "struct", "u32", "i32", "f32" ]
, reservedOpNames = [ "+", "-", "*", "/" ]
, opStart = oneOf "+-*/%"
, opLetter = oneOf "+-*/%"
, reservedNames = [ "struct", "u32", "i32", "f32", "if", "then", "else" ]
, reservedOpNames = [ "+", "-", "*", "/", "%" ]
, caseSensitive = True
}