Split out Syntax types;

Parsed functions, returns, identifiers, types, conditionals, assignments, and bools;
Fixed import and comment parsers;
This commit is contained in:
2024-02-25 00:39:30 -06:00
parent 2fba34b93c
commit 5b94711e65
3 changed files with 198 additions and 49 deletions

View File

@@ -65,6 +65,23 @@ importStatement =
\ HashMap,\n\
\}"
function :: Text
function =
"fn fizz-buzz(i: Num): Str {\n\
\ --- This is technically a legal comment ---\n\
\ let fb = \"\";\n\
\\n\
\ if i % 3 == 0 {\n\
\ fb = fb ++ \"fizz\";\n\
\ }\n\
\\n\
\ if i % 5 == 0 {\n\
\ fb ++= \"buzz\";\n\
\ }\n\
\\n\
\ return i if Str.is-empty(fb) else fb;\n\
\}"
-- Runners
printParser :: (Show s) => Parser s -> Text -> IO ()

View File

@@ -3,70 +3,85 @@
module Parser where
import Control.Applicative hiding (many, some)
import Control.Monad
import Control.Applicative hiding (Const, many, some)
import Control.Monad (void)
import Data.Kind (Type)
import Data.Text (Text)
import qualified Data.Text as T
import Data.Void
import Data.Void (Void)
import Syntax
import Text.Megaparsec hiding (State)
import Text.Megaparsec.Char
import qualified Text.Megaparsec.Char.Lexer as L
type Parser = Parsec Void Text
newtype Program = Program
{ statements :: [Statement]
}
deriving (Show)
data Statement
= Import [Identifier] [Identifier]
| Expr Expression
| Function Identifier [Identifier] Block
| Return Expression
| Conditional Expression Block (Maybe Block)
deriving (Show)
data Expression = E deriving (Show)
type Block = [Statement]
type Identifier = String
parseProgram :: Parser Program
parseProgram = program <* eof
where
program = do
void $ many space
statements <- parseStatements
statements <- parseTopLevelStatements
return Program {..}
parseStatements :: Parser [Statement]
parseStatements =
many $ do
void parseComment
parseTopLevelStatements :: Parser [Statement]
parseTopLevelStatements = many . try $ do
choice
[ parseImport,
parseStatement
]
parseStatement :: Parser Statement
parseStatement = do
space
try $
choice
[ try parseImport
-- try parseExpression,
-- try parseFunction,
-- try parseReturn,
-- try parseConditional
[ parseFunction,
parseComment,
parseDeclaration,
parseReturn
-- try parseConditional
-- try parseExpression,
]
-- Misc
parseIdentifier :: Parser Identifier
parseIdentifier = some alphaNumChar
parseIdentifier = do
initial <- letterChar
rest <- many $ choice [try alphaNumChar, try $ char '-']
return $ initial : rest
parseIdentifierWithType :: Parser IdentifierWithType
parseIdentifierWithType = do
name <- parseIdentifier
typeAnnotation <- optional $ try parseType
return $ IdentifierWithType name typeAnnotation
parseType :: Parser Identifier
parseType = space *> char ':' *> space *> parseIdentifier
parseList :: Parser a -> Parser b -> Parser c -> Parser d -> Parser [d]
parseList start end sep parser = between start end $ sepEndBy parser sep
parseList' :: Parser a -> Parser b -> Parser c -> Parser d -> Parser [d]
parseList' start end sep = parseList (start <* space) (space *> end) (space *> sep <* space)
parseBlock :: Parser Block
parseBlock = between (char '{' <* space) (space *> char '}') $ many parseStatement
-- Comments
parseComment :: Parser Text
parseComment = choice [try parseBlockComment, try parseSingleComment]
parseComment :: Parser Statement
parseComment = do
comment <- choice [try parseBlockComment, try parseSingleComment]
return . Comment $ T.strip comment
parseSingleComment :: Parser Text
parseSingleComment = do
_ <- string "--"
takeWhileP Nothing (/= '\n')
body <- manyTill anySingle newline
return $ T.pack body
parseBlockComment :: Parser Text
parseBlockComment = do
@@ -82,21 +97,74 @@ parseImport = do
space1
modulePath <- sepBy1 parseIdentifier (char '.')
space1
importedItems <- between startBlock endBlock $ sepEndBy parseIdentifier itemSep
importedItems <- parseList' (char '{') (char '}') (char ',') parseIdentifier
return $ Import modulePath importedItems
where
startBlock = char '{' <* space
endBlock = space *> char '}'
itemSep = space *> char ',' <* space
-- parseExpression :: Parser Statement
-- parseExpression = undefined
-- Functions
-- parseFunction :: Parser Statement
-- parseFunction = undefined
parseFunction :: Parser Statement
parseFunction = do
void $ string "fn"
space1
name <- parseIdentifier
space
params <- between (char '(') (char ')') $ sepEndBy parseIdentifierWithType (char ',')
typeAnnotation <- optional $ try parseType
space
Function (IdentifierWithType name typeAnnotation) params <$> parseBlock
-- parseReturn :: Parser Statement
-- parseReturn = undefined
parseReturn :: Parser Statement
parseReturn = do
expr <- string "return" *> space1 *> parseExpression
return $ Return expr
-- parseConditional :: Parser Statement
-- parseConditional = undefined
-- Conditionals
parseConditional :: Parser Statement
parseConditional = do
void $ string "if"
space1
condition <- parseExpression
space
thenBlock <- parseBlock
elseBlock <- optional . try $ do
void $ string "else"
space
parseBlock
return $ Conditional condition thenBlock elseBlock
-- Variable declarations
parseDeclaration :: Parser Statement
parseDeclaration =
choice
[ try $ parseDeclaration' "let" Let,
try $ parseDeclaration' "const" Const
]
parseDeclaration' :: Text -> (IdentifierWithType -> Expression -> Statement) -> Parser Statement
parseDeclaration' keyword constructor = do
name <- string keyword *> space *> parseIdentifierWithType
space
void $ char '='
space
constructor name <$> parseExpression
-- Expressions
parseExpression :: Parser Expression
parseExpression = undefined
-- Literals
parseBool :: Text -> Bool -> Parser Expression
parseBool text literal =
do
void $ string text
return $ LiteralBool literal
parseTrue :: Parser Expression
parseTrue = parseBool "true" True
parseFalse :: Parser Expression
parseFalse = parseBool "false" False

View File

@@ -1 +1,65 @@
{-# LANGUAGE OverloadedStrings #-}
module Syntax where
import Data.Text (Text)
newtype Program = Program
{ statements :: [Statement]
}
deriving (Show)
data Statement
= Import [Identifier] [Identifier]
| Function IdentifierWithType [IdentifierWithType] Block
| Return Expression
| Let IdentifierWithType Expression
| Const IdentifierWithType Expression
| Expr Expression
| Conditional Expression Block (Maybe Block)
| Comment Text
deriving (Show)
type Identifier = String
data IdentifierWithType = IdentifierWithType Identifier (Maybe Identifier) deriving (Show)
type Block = [Statement]
data Expression
= LiteralInt Integer -- Integer literal, e.g., 42
| LiteralFloat Float -- Float literal, e.g., 0.123
| LiteralBool Bool -- Boolean literal, e.g., True
| LiteralChar Char -- Character literal, e.g., 'a'
| LiteralString String -- String literal, e.g., "Hello, World!"
| Variable Identifier -- Variable reference, e.g., x
| BinaryOperation BinaryOperator Expression Expression -- Binary operation, e.g., x + y
| UnaryOperation UnaryOperator Expression -- Unary operation, e.g., -x
| FunctionCall Identifier [Expression] -- Function call, e.g., f(x, y)
| Ternary Expression Expression Expression -- Conditional expression, e.g., if x then y else z
deriving (Show)
data BinaryOperator
= Add
| Subtract
| Multiply
| Divide
| Modulus
| Equal
| NotEqual
| LessThan
| LessThanOrEqual
| GreaterThan
| GreaterThanOrEqual
| LogicalAnd
| LogicalOr
-- | BitAnd
-- | BitOr
-- | ...
-- | Concat
deriving (Show)
data UnaryOperator
= Negate
| Not
deriving (Show)