Skip to content

Commit

Permalink
add examples
Browse files Browse the repository at this point in the history
  • Loading branch information
antonkesy committed Mar 7, 2024
1 parent ec4adc9 commit b843083
Show file tree
Hide file tree
Showing 10 changed files with 80 additions and 20 deletions.
31 changes: 30 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,36 @@ int main() {
}
```

## Running
## Syntax

C-Style

```
void main() {
print("Hello, World!");
}
```

## Usage

```bash
> stack run -- --help
Usage: peter-exe [-i|--inline STRING] [PATH]

Available options:
-i,--inline STRING Inline string to parse and interpret
-h,--help Show this help text
```

```bash
stack run -- ./examples/main_hello_world.mmm
stack run -- -i "int main() { print(\"Hello, World\"); }"

stack run -- ./examples/short_hello_world.mmm
stack run -- -i "print(\"Hello, World\");"
```

### Tests

`stack test`

Expand Down
40 changes: 32 additions & 8 deletions app/Main.hs
Original file line number Diff line number Diff line change
@@ -1,22 +1,46 @@
module Main (main) where

import Interpreter.Interpreter
import Options.Applicative
import Parser.Program
import Text.Parsec (parse)

developProgram :: String
developProgram =
-- "int i = 1; int j = 2; int l = 3 + 4; int k = i + j + l; k = k * 0;"
-- "void test(int i, int k) { }"
-- "print()"
"int main() { print(\"Test\"); }"
-- TODO: replace with either
data Options = Options (Maybe String) (Maybe FilePath)

parseOptions :: Parser Options
parseOptions =
Options
<$> optional
( strOption
( long "inline"
<> short 'i'
<> metavar "STRING"
<> help "Inline string to parse and interpret"
)
)
<*> optional (argument str (metavar "PATH"))

main :: IO ()
main = do
let result = parse parseProgram "" developProgram
opts <- execParser $ info (parseOptions <**> helper) fullDesc
processOptions opts

processOptions :: Options -> IO ()
processOptions (Options Nothing (Just path)) = do
contents <- readFile path
runPeter contents
processOptions (Options (Just inlineSourceCode) Nothing) =
runPeter inlineSourceCode
processOptions _ =
putStrLn "Arguments: provided file path OR inline source code"

runPeter :: String -> IO ()
runPeter sourceCode = do
let result = parse parseProgram "" sourceCode
case result of
Left err -> putStrLn $ "Parse error: " ++ show err
Right program -> do
putStrLn "Parsed program:"
-- putStrLn "Parsed program:"
print program
interpret program
3 changes: 3 additions & 0 deletions examples/main_hello_world.mmm
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
void main() {
print("Hello, World!");
}
1 change: 1 addition & 0 deletions examples/short_hello_world.mmm
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
print("Hello, World!");
9 changes: 5 additions & 4 deletions src/Interpreter/Interpreter.hs
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,16 @@ interpret (Program statements) = do
isValid <- validate (Program statements)
if isValid
then do
putStrLn "Valid program"
endState <- foldM interpretStatement (ProgramState empty allFunctions) (addMainFunctionCall ++ statements)
putStrLn $ "End state: " ++ show endState
-- putStrLn "Valid program"
_ <- foldM interpretStatement (ProgramState empty allFunctions) (addMainFunctionCall ++ statements)
-- putStrLn $ "End state: " ++ show endState
return ()
else do
putStrLn "Invalid program"
where
addMainFunctionCall = if hasMainFunction then mainFunctionCall else []
mainFunctionCall = [ExpressionStatement (AtomicExpression (FunctionCallAtomic "main" []))]
hasMainFunction = Prelude.filter isMainFunction statements /= []
hasMainFunction = any isMainFunction statements
isMainFunction (FunctionDefinitionStatement (Function "main" _ _ _)) = True
isMainFunction _ = False
isFunctionDefinition (FunctionDefinitionStatement _) = True
Expand Down
6 changes: 3 additions & 3 deletions src/Interpreter/Validator.hs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ module Interpreter.Validator (module Interpreter.Validator) where
import AST

validate :: Program -> IO Bool
validate (program) = do
validate program = do
allChecks <- sequence [hasStatements program, hasEntryPoint program]
return (and allChecks)

hasStatements :: Program -> IO Bool
hasStatements (Program statements) =
if length statements > 0
if not (null statements)
then return True
else do
putStrLn "Program has no statements"
Expand All @@ -21,7 +21,7 @@ hasEntryPoint :: Program -> IO Bool
hasEntryPoint (Program statements) =
let countMainFunctions = length $ filter isMainFunction statements
countStatements = length $ filter isGlobalStatement statements
in if (countMainFunctions == 1 && countStatements == 0) || (countMainFunctions == 0 && countStatements > 0)
in if countMainFunctions == 1 && countStatements == 0 || countMainFunctions == 0 && countStatements > 0
then return True
else do
putStrLn "Program has no entry point or has multiple entry points. A program must have a single entry point."
Expand Down
2 changes: 1 addition & 1 deletion src/Parser/EndOfLine.hs
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ import Text.Parsec
import Text.Parsec.String

eol :: Parser ()
eol = void (char '\n') <|> eof
eol = void endOfLine <|> eof
3 changes: 2 additions & 1 deletion src/Parser/Program.hs
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,6 @@ import Text.Parsec.String
parseProgram :: Parser Program
parseProgram = do
statements <- many (try parseStatement)
_ <- eof
-- _ <- eof -- TODO: ensure no tokens left -> EOF not working becuase already consumed
_ <- optional eof
return $ Program statements
2 changes: 1 addition & 1 deletion src/Parser/Statement.hs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ parseStatement =
<|> (FunctionDefinitionStatement <$> try (spaces' *> try parseFunction))
<|> ExpressionStatement <$> try (spaces' *> try parseExpression)
)
<* spaces
<* spaces'
<* endOfStatement

endOfStatement :: Parser ()
Expand Down
3 changes: 2 additions & 1 deletion test/Unit/Parser/Atomic.hs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ module Unit.Parser.Atomic (allTests) where

import AST
import Data.Either (fromRight, isRight)
import Parser.Atomic
-- import Parser.Atomic
import Parser.Expression
import Test.HUnit
import Text.Parsec (parse)

Expand Down

0 comments on commit b843083

Please sign in to comment.