Skip to content

Commit

Permalink
Merge pull request #23 from nLatt/16-cpt-and-ast-implementation
Browse files Browse the repository at this point in the history
16 cpt and ast implementation
  • Loading branch information
virgile-crtl authored Jan 30, 2023
2 parents 948f6b7 + 476de99 commit fbb3400
Show file tree
Hide file tree
Showing 32 changed files with 286 additions and 118 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,4 @@ cabal.project.local
cabal.project.local~
.HTF/
.ghc.environment.*
*.tix
19 changes: 14 additions & 5 deletions GLaDOS2023.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,21 @@ extra-source-files:
library
exposed-modules: Parsing,
Parsing.Args,
Parsing.Lang
hs-source-dirs: parsing
Parsing.Token,
Parsing.Ast,
Parsing.Cpt
hs-source-dirs: lib
build-depends: base >= 4.14.1.0
default-language: Haskell2010

executable glados
main-is: Main.hs

-- Modules included in this executable, other than Main.
other-modules: ParsingLangTests,
other-modules: Parsing.CptTests,
Parsing.AstTests,
Parsing.ArgsTests,
Parsing.TokenTests,
Builtins
-- LANGUAGE extensions used by modules in this package.
-- other-extensions:
Expand All @@ -45,7 +50,11 @@ test-suite test
default-language: Haskell2010
type: exitcode-stdio-1.0
hs-source-dirs: test
other-modules: ParsingLangTests,
ParseArgsTest
other-modules: Parsing.ArgsTests,
Parsing.TokenTests,
Parsing.CptTests,
Parsing.AstTests
ParsingTests

main-is: TestMain.hs
build-depends: base >=4.14.1.0, tasty >= 1.4.3, tasty-discover >= 5.0.0, tasty-hunit >= 0.10.0.3, GLaDOS2023
1 change: 1 addition & 0 deletions TestFiles/builtins1.scm
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
(+ (* 2 3) (div 10 2))
1 change: 1 addition & 0 deletions TestFiles/builtins2.scm
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
(eq? (* 2 5) (- 11 1))
1 change: 1 addition & 0 deletions TestFiles/builtins3.scm
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
(< 1 (mod 10 3))
1 change: 1 addition & 0 deletions TestFiles/call.scm
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
(div 10 2)
1 change: 1 addition & 0 deletions TestFiles/error.scm
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
(* foo 2)
5 changes: 5 additions & 0 deletions TestFiles/factorial.scm
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
(define (fact x)
(if (eq? x 1)
1
(* x (fact (- x 1)))))
(fact 10)
2 changes: 2 additions & 0 deletions TestFiles/foo.scm
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
(define foo 21)
(* foo 2)
3 changes: 3 additions & 0 deletions TestFiles/function1.scm
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
(define (add a b)
(+ a b))
(add 3 4)
1 change: 1 addition & 0 deletions TestFiles/if1.scm
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
(if #t 1 2)
1 change: 1 addition & 0 deletions TestFiles/if2.scm
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
(if #f 1 2)
4 changes: 4 additions & 0 deletions TestFiles/if3.scm
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
(define foo 42)
(if (< foo 10)
(* foo 3)
(div foo 2))
1 change: 1 addition & 0 deletions TestFiles/lambda1.scm
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
(lambda (a b) (+ a b))
1 change: 1 addition & 0 deletions TestFiles/lambda2.scm
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
((lambda (a b) (+ a b)) 1 2)
4 changes: 4 additions & 0 deletions TestFiles/lambda3.scm
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
(define add
(lambda (a b)
(+ a b)))
(add 3 4)
File renamed without changes.
File renamed without changes.
7 changes: 7 additions & 0 deletions TestFiles/superior.scm
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
(define (> a b)
(if (eq? a b)
#f
(if (< a b)
#f
#t)))
(> 10 -2)
5 changes: 3 additions & 2 deletions app/Main.hs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ module Main where

-- Our modules
import Parsing
import Parsing.Lang
import Parsing.Token
import Parsing.Cpt
import Parsing.Args

main :: IO ()
Expand All @@ -13,7 +14,7 @@ main = do
-- For the time being since we don't know how to pass args with cabal
-- we use tokenizeFile immediately

tokenizedcode <- tokenizeFile "./TestFiles/2"
tokenizedcode <- tokenizeFile "./TestFiles/sample1.scm"

print tokenizedcode
print (parseTokenList tokenizedcode)
2 changes: 1 addition & 1 deletion hie.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
cradle:
cabal:
- path: "./parsing"
- path: "./lib"
component: "lib:GLaDOS2023"

- path: "./app/Main.hs"
Expand Down
File renamed without changes.
File renamed without changes.
54 changes: 54 additions & 0 deletions lib/Parsing/Ast.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
module Parsing.Ast where

import Parsing.Cpt

-- ─── Abstract Syntaxe Tree ───────────────────────────────────────────────────────────────────────

data Expr = ExprList [Expr]
| Num Integer
| Symbole String
| Call String [Expr] -- Will also be used for the boolean expression
deriving (Eq, Show)

-- This function parses lists of expressions, ignoring function calls
-- AT LEAST at first level
-- This means it will only parse function calls in sublists thanks to parseExpr
parseExprList :: [Cpt] -> [Expr]
parseExprList [] = []
parseExprList (x : xs) = case x of
Sym str -> Symbole str : parseExprList xs
Val i -> Num i : parseExprList xs
List ls -> parseExpr ls : parseExprList xs

-- Parses a CPT into a single Expr value
parseExpr :: [Cpt] -> Expr
parseExpr (Sym str : xs) = if isValidBuiltin str then
Call str (parseExprList xs) else ExprList (parseExprList (Sym str : xs))
parseExpr ls = ExprList (parseExprList ls)

-- Utility function for execution
-- Converts cpt list to Expr Call
-- IMPORTANT : Returns nothing in case of error
exprListToCall :: [Expr] -> Maybe Expr
exprListToCall [] = Nothing
exprListToCall (Symbole name : xs) = Just (Call name xs)
exprListToCall _ = Nothing

-- DEFINITIONS
-- Expression = Anything that ends up a value
-- Function Call = When first element of list is symbol

-- NOTES
-- DID NOT implement ternary (if else) statement for the time being
-- At execution : if list is deemed to be a function call, create function to convert it

-- This is where we put builtins
isValidBuiltin :: String -> Bool
isValidBuiltin "define" = True
isValidBuiltin "lambda" = True
isValidBuiltin "add" = True
isValidBuiltin "sub" = True
isValidBuiltin "div" = True
isValidBuiltin "mul" = True
isValidBuiltin "noop" = True
isValidBuiltin _ = False
63 changes: 3 additions & 60 deletions parsing/Parsing/Lang.hs → lib/Parsing/Cpt.hs
Original file line number Diff line number Diff line change
@@ -1,58 +1,8 @@
module Parsing.Lang where
module Parsing.Cpt where

import Text.Read
import Data.Char
import Parsing.Token
import Data.Maybe

-- ─── Tokenization ────────────────────────────────────────────────────────────────────────────────

-- Token Datatype
data Token = OpenScope -- Opening parenthesis
| CloseScope -- Closing parenthesis
| Num Integer
| Keyword String
deriving (Show, Eq)

-- Parse token from string
parseToken :: String -> Token
parseToken "(" = OpenScope
parseToken ")" = CloseScope
parseToken input = case readMaybe input :: Maybe Integer of
Just x -> Num x
Nothing -> Keyword input

-- Function that tokenizes string
--
-- Tokens are : ' ', '\n', '(', ')'
-- Args are : Input -> Temp Str -> Output List
tokenize' :: String -> String -> [Token]
tokenize' [] "" = []
tokenize' [] str = [parseToken str]
tokenize' (' ':xs) "" = tokenize' xs ""
tokenize' (' ':xs) str = parseToken str : tokenize' xs ""
tokenize' ('\n':xs) "" = tokenize' xs ""
tokenize' ('\n':xs) str = parseToken str : tokenize' xs ""
tokenize' ('(':xs) "" = OpenScope : tokenize' xs ""
tokenize' ('(':xs) str = parseToken str : tokenize' ('(':xs) ""
tokenize' (')':xs) "" = CloseScope : tokenize' xs ""
tokenize' (')':xs) str = parseToken str : tokenize' (')':xs) ""
tokenize' (x:xs) str = tokenize' xs (str <> [x])

-- Utility entry point function
tokenize :: String -> [Token]
tokenize str = tokenize' str ""

-- Function to tokenize a given file
--
-- Args : path
tokenizeFile :: String -> IO [Token]
tokenizeFile path = do
-- Read file and Tokenize
fileStr <- readFile path

-- Return tokenization result
return (tokenize fileStr)

-- ─── Concrete Parsing Tree ───────────────────────────────────────────────────────────────────────

-- Basic concrete parsing tree structure
Expand Down Expand Up @@ -122,10 +72,6 @@ getCloseScope (x:xs) = getCloseScope' xs 1 0 1 -- index starts at 1 since first

-- ─── Utilities ───────────────────────────────────────────────────────────────────────────────────

isNum :: String -> Bool
isNum [] = True
isNum (x:xs) = if isDigit x then isNum xs else False

getSymbol :: Cpt -> Maybe String
getSymbol (Sym s) = Just s
getSymbol _ = Nothing
Expand All @@ -136,7 +82,4 @@ getInteger _ = Nothing

getList :: Cpt -> Maybe [Cpt]
getList (List ls) = Just ls
getList _ = Nothing

-- Refactor ideas :
-- Add list comprehension for list slicing in parseTokenList
getList _ = Nothing
53 changes: 53 additions & 0 deletions lib/Parsing/Token.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
module Parsing.Token where

import Data.Maybe
import Text.Read

-- ─── Tokenization ────────────────────────────────────────────────────────────────────────────────

-- Token Datatype
data Token = OpenScope -- Opening parenthesis
| CloseScope -- Closing parenthesis
| Num Integer
| Keyword String
deriving (Show, Eq)

-- Parse token from string
parseToken :: String -> Token
parseToken "(" = OpenScope
parseToken ")" = CloseScope
parseToken input = case readMaybe input :: Maybe Integer of
Just x -> Num x
Nothing -> Keyword input

-- Function that tokenizes string
--
-- Tokens are : ' ', '\n', '(', ')'
-- Args are : Input -> Temp Str -> Output List
tokenize' :: String -> String -> [Token]
tokenize' [] "" = []
tokenize' [] str = [parseToken str]
tokenize' (' ':xs) "" = tokenize' xs ""
tokenize' (' ':xs) str = parseToken str : tokenize' xs ""
tokenize' ('\n':xs) "" = tokenize' xs ""
tokenize' ('\n':xs) str = parseToken str : tokenize' xs ""
tokenize' ('(':xs) "" = OpenScope : tokenize' xs ""
tokenize' ('(':xs) str = parseToken str : tokenize' ('(':xs) ""
tokenize' (')':xs) "" = CloseScope : tokenize' xs ""
tokenize' (')':xs) str = parseToken str : tokenize' (')':xs) ""
tokenize' (x:xs) str = tokenize' xs (str <> [x])

-- Utility entry point function
tokenize :: String -> [Token]
tokenize str = tokenize' str ""

-- Function to tokenize a given file
--
-- Args : path
tokenizeFile :: String -> IO [Token]
tokenizeFile path = do
-- Read file and Tokenize
fileStr <- readFile path

-- Return tokenization result
return (tokenize fileStr)
10 changes: 5 additions & 5 deletions test/ParseArgsTest.hs → test/Parsing/ArgsTests.hs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
module ParseArgsTest where
module Parsing.ArgsTests where

import Parsing
import Parsing.Args
Expand All @@ -12,9 +12,9 @@ parseArgsTest arr restest testName = testCase testName $ do

argsSuite :: TestTree
argsSuite = testGroup "Parsing.Args Test Suite" [
parseArgsTest ["binaryName", "", "", ""] (ParsedArgs False "") "No file",
parseArgsTest ["binaryName", "-h"] (ParsedArgs True "") "Only -h",
parseArgsTest ["binaryName", "test", "-h"] (ParsedArgs True "test") "File with -h",
parseArgsTest ["binaryName", "", ""] (ParsedArgs False "") "Empty Args",
parseArgsTest ["binaryName"] (ParsedArgs False "") "No Args",
parseArgsTest ["binaryName", "filename"] (ParsedArgs False "filename") "Only filename"
parseArgsTest ["binaryName", "-h"] (ParsedArgs True "") "Only -h",
parseArgsTest ["binaryName", "filename"] (ParsedArgs False "filename") "Only filename",
parseArgsTest ["binaryName", "filename", "-h"] (ParsedArgs True "filename") "File with -h"
]
Loading

0 comments on commit fbb3400

Please sign in to comment.