Split out Syntax types;
Parsed functions, returns, identifiers, types, conditionals, assignments, and bools; Fixed import and comment parsers;
This commit is contained in:
17
app/Main.hs
17
app/Main.hs
@@ -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 ()
|
||||
|
||||
166
src/Parser.hs
166
src/Parser.hs
@@ -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
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user