diff options
| author | Eugen Wissner <belka@caraus.de> | 2024-07-24 01:22:20 +0200 |
|---|---|---|
| committer | Eugen Wissner <belka@caraus.de> | 2024-07-24 01:22:20 +0200 |
| commit | 947c5aa7efba507a849463fcf813b3cc61042845 (patch) | |
| tree | e10fe357e91389325ddd647b79c71b0b69cabc38 /lib/Language/Elna/Parser.hs | |
| parent | 9d1f0385945e926e7084e60fc72fe5846e7139b2 (diff) | |
| download | elna-947c5aa7efba507a849463fcf813b3cc61042845.tar.gz | |
Parse expressions
Diffstat (limited to 'lib/Language/Elna/Parser.hs')
| -rw-r--r-- | lib/Language/Elna/Parser.hs | 79 |
1 files changed, 71 insertions, 8 deletions
diff --git a/lib/Language/Elna/Parser.hs b/lib/Language/Elna/Parser.hs index cd8f927..f387f60 100644 --- a/lib/Language/Elna/Parser.hs +++ b/lib/Language/Elna/Parser.hs @@ -4,22 +4,27 @@ module Language.Elna.Parser ) where import Control.Monad (void) +import Control.Monad.Combinators.Expr (Operator(..), makeExprParser) import Data.Text (Text) import qualified Data.Text as Text import Data.Void (Void) import Language.Elna.AST ( Declaration(..) + , Expression(..) , Identifier(..) + , Literal(..) , Parameter(..) , Program(..) + , Statement(..) , TypeExpression(..) , VariableDeclaration(..) ) -import Text.Megaparsec (Parsec, (<?>), optional, between, sepBy) -import Text.Megaparsec.Char (alphaNumChar, letterChar, space1) +import Text.Megaparsec (Parsec, (<?>), optional, between, sepBy, choice) +import Text.Megaparsec.Char (alphaNumChar, char, letterChar, space1, asciiChar) import qualified Text.Megaparsec.Char.Lexer as Lexer import Control.Applicative (Alternative(..)) import Data.Maybe (isJust) +import Data.Functor (($>)) type Parser = Parsec Void Text @@ -42,11 +47,8 @@ procedureP = void $ symbol "proc" parensP :: forall a. Parser a -> Parser a parensP = between (symbol "(") (symbol ")") -openBracketP :: Parser () -openBracketP = void $ symbol "[" - -closingBracketP :: Parser () -closingBracketP = void $ symbol "]" +bracketsP :: forall a. Parser a -> Parser a +bracketsP = between (symbol "[") (symbol "]") colonP :: Parser () colonP = void $ symbol ":" @@ -65,7 +67,7 @@ typeExpressionP = arrayTypeExpression <?> "type expression" where arrayTypeExpression = flip ArrayType - <$> (symbol "array" *> openBracketP *> lexeme Lexer.decimal <* closingBracketP) + <$> (symbol "array" *> bracketsP (lexeme Lexer.decimal)) <*> (symbol "of" *> typeExpressionP) typeDefinitionP :: Parser Declaration @@ -92,6 +94,67 @@ parameterP = paramCons parametersP :: Parser [Parameter] parametersP = parensP $ sepBy parameterP (symbol ",") +literalP :: Parser Literal +literalP + = HexadecimalLiteral <$> Lexer.hexadecimal + <|> IntegerLiteral <$> Lexer.decimal + <|> CharacterLiteral <$> charP + <|> BooleanLiteral <$> (symbol "true" $> True) + <|> BooleanLiteral <$> (symbol "false" $> False) + where + -- TODO: Escape characters. + charP = fromIntegral . fromEnum + <$> between (char '\'') (char '\'') asciiChar + +termP :: Parser Expression +termP = choice + [ parensP expressionP + , VariableExpression <$> identifierP + , LiteralExpression <$> literalP + ] + +operatorTable :: [[Operator Parser Expression]] +operatorTable = + [ [Postfix (ArrayExpression <$> bracketsP expressionP)] + , unaryOperator + , factoryOperator + , termOperator + , comparisonOperator + ] + where + unaryOperator = + [ prefix "-" NegationExpression + , prefix "+" id + ] + factoryOperator = + [ binary "*" ProductExpression + , binary "/" DivisionExpression + ] + termOperator = + [ binary "+" SumExpression + , binary "-" SubtractionExpression + ] + comparisonOperator = + [ binary "<" LessExpression + , binary "<=" LessOrEqualExpression + , binary ">" GreaterExpression + , binary ">=" GreaterOrEqualExpression + , binary "=" EqualExpression + , binary "#" NonEqualExpression + ] + prefix name f = Prefix (f <$ symbol name) + binary name f = InfixL (f <$ symbol name) + +expressionP :: Parser Expression +expressionP = makeExprParser termP operatorTable + +statementP :: Parser Statement +statementP + = EmptyStatement <$ semicolonP + <|> AssignmentStatement <$> expressionP <* symbol ":=" <*> expressionP + <|> CompoundStatement <$> blockP (many statementP) + <?> "statement" -- TODO: further statements + procedureDefinitionP :: Parser Declaration procedureDefinitionP = ProcedureDefinition <$> (procedureP *> identifierP) |
