Resolves issue with parsing comments
This commit is contained in:
		| @ -4,8 +4,9 @@ import Parser | |||||||
| import Research | import Research | ||||||
|  |  | ||||||
| import Data.Map (Map) | import Data.Map (Map) | ||||||
| import qualified Data.Map as Map |  | ||||||
| import Data.List (foldl') | import Data.List (foldl') | ||||||
|  |  | ||||||
|  | import qualified Data.Map as Map | ||||||
| import qualified Data.Set as Set | import qualified Data.Set as Set | ||||||
|  |  | ||||||
| evalSingle :: Map String T -> TricuAST -> Map String T | evalSingle :: Map String T -> TricuAST -> Map String T | ||||||
| @ -51,6 +52,7 @@ evalAST env term = case term of | |||||||
|     SStr str -> ofString str |     SStr str -> ofString str | ||||||
|     SInt num -> ofNumber num |     SInt num -> ofNumber num | ||||||
|     SList elems -> ofList (map (evalAST Map.empty) elems) |     SList elems -> ofList (map (evalAST Map.empty) elems) | ||||||
|  |     SEmpty -> Leaf | ||||||
|     SFunc name args body -> |     SFunc name args body -> | ||||||
|         error $ "Unexpected function definition " ++ name |         error $ "Unexpected function definition " ++ name | ||||||
|         ++ " in evalAST; define via evalSingle." |         ++ " in evalAST; define via evalSingle." | ||||||
| @ -66,9 +68,8 @@ eliminateLambda (TFork l r) = TFork (eliminateLambda l) (eliminateLambda r) | |||||||
| eliminateLambda (SList xs) = SList (map eliminateLambda xs) | eliminateLambda (SList xs) = SList (map eliminateLambda xs) | ||||||
| eliminateLambda other = other | eliminateLambda other = other | ||||||
|  |  | ||||||
| -- This is my attempt to implement the lambda calculus elimination rules defined |  | ||||||
| -- in "Typed Program Analysis without Encodings" by Barry Jay. |  | ||||||
| -- https://github.com/barry-jay-personal/typed_tree_calculus/blob/main/typed_program_analysis.pdf | -- https://github.com/barry-jay-personal/typed_tree_calculus/blob/main/typed_program_analysis.pdf | ||||||
|  | -- Chapter 4: Lambda-Abstraction | ||||||
| lambdaToT :: String -> TricuAST -> TricuAST | lambdaToT :: String -> TricuAST -> TricuAST | ||||||
| lambdaToT x (SVar y) | lambdaToT x (SVar y) | ||||||
|   | x == y = tI |   | x == y = tI | ||||||
|  | |||||||
							
								
								
									
										51
									
								
								src/Lexer.hs
									
									
									
									
									
								
							
							
						
						
									
										51
									
								
								src/Lexer.hs
									
									
									
									
									
								
							| @ -2,10 +2,12 @@ module Lexer where | |||||||
|  |  | ||||||
| import Research | import Research | ||||||
| import Text.Megaparsec | import Text.Megaparsec | ||||||
| import Text.Megaparsec.Char | import Text.Megaparsec.Char hiding (space) | ||||||
|  | import Text.Megaparsec.Char.Lexer | ||||||
|  |  | ||||||
| import Control.Monad (void) | import Control.Monad (void) | ||||||
| import Data.Void | import Data.Void | ||||||
|  |  | ||||||
| import qualified Data.Set as Set | import qualified Data.Set as Set | ||||||
|  |  | ||||||
| type Lexer = Parsec Void String | type Lexer = Parsec Void String | ||||||
| @ -23,7 +25,6 @@ data LToken | |||||||
|   | LOpenBracket |   | LOpenBracket | ||||||
|   | LCloseBracket |   | LCloseBracket | ||||||
|   | LNewline |   | LNewline | ||||||
|   | LComment String |  | ||||||
|   deriving (Show, Eq, Ord) |   deriving (Show, Eq, Ord) | ||||||
|  |  | ||||||
| keywordT :: Lexer LToken | keywordT :: Lexer LToken | ||||||
| @ -75,30 +76,34 @@ closeBracket = char ']' *> pure LCloseBracket | |||||||
| lnewline :: Lexer LToken | lnewline :: Lexer LToken | ||||||
| lnewline = char '\n' *> pure LNewline | lnewline = char '\n' *> pure LNewline | ||||||
|  |  | ||||||
| comment :: Lexer LToken |  | ||||||
| comment = do |  | ||||||
|   string "--" |  | ||||||
|   content <- many (satisfy (/= '\n')) |  | ||||||
|   pure (LComment content) |  | ||||||
|  |  | ||||||
| sc :: Lexer () | sc :: Lexer () | ||||||
| sc = skipMany (void (char ' ') <|> void (char '\t') <|> void comment) | sc = space space1 (skipLineComment "--") (skipBlockComment "|-" "-|") | ||||||
|  |  | ||||||
| tricuLexer :: Lexer [LToken] | tricuLexer :: Lexer [LToken] | ||||||
| tricuLexer = many (sc *> choice | tricuLexer = do | ||||||
|   [ try identifier |   sc | ||||||
|   , try keywordT |   tokens <- many $ do | ||||||
|   , try integerLiteral |     tok <- choice tricuLexer' | ||||||
|   , try stringLiteral |     sc | ||||||
|   , assign |     pure tok | ||||||
|   , colon |   sc | ||||||
|   , backslash |   eof | ||||||
|   , openParen |   pure tokens | ||||||
|   , closeParen |     where | ||||||
|   , openBracket |       tricuLexer' =  | ||||||
|   , closeBracket |         [ try identifier | ||||||
|   , lnewline |         , try keywordT | ||||||
|   ] <* sc) <* eof |         , try integerLiteral | ||||||
|  |         , try stringLiteral | ||||||
|  |         , assign | ||||||
|  |         , colon | ||||||
|  |         , backslash | ||||||
|  |         , openParen | ||||||
|  |         , closeParen | ||||||
|  |         , openBracket | ||||||
|  |         , closeBracket | ||||||
|  |         ] | ||||||
|  |  | ||||||
|  |  | ||||||
| lexTricu :: String -> [LToken] | lexTricu :: String -> [LToken] | ||||||
| lexTricu input = case runParser tricuLexer "" input of | lexTricu input = case runParser tricuLexer "" input of | ||||||
|  | |||||||
							
								
								
									
										14
									
								
								src/Main.hs
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								src/Main.hs
									
									
									
									
									
								
							| @ -1,14 +1,14 @@ | |||||||
| module Main where | module Main where | ||||||
|  |  | ||||||
| import Eval | import Eval     (evalTricu, result) | ||||||
| import Lexer | import Library  (library) | ||||||
| import Library | import Parser   (parseTricu) | ||||||
| import Parser | import REPL     (repl) | ||||||
| import REPL (repl) | import Research (T) | ||||||
| import Research |  | ||||||
|  | import Text.Megaparsec (runParser) | ||||||
|  |  | ||||||
| import qualified Data.Map as Map | import qualified Data.Map as Map | ||||||
| import Text.Megaparsec (runParser) |  | ||||||
|  |  | ||||||
| main :: IO () | main :: IO () | ||||||
| main = do | main = do | ||||||
|  | |||||||
| @ -1,16 +1,16 @@ | |||||||
| module Parser where | module Parser where | ||||||
|  |  | ||||||
| import Debug.Trace |  | ||||||
| import Lexer | import Lexer | ||||||
| import Research hiding (toList) | import Research hiding (toList) | ||||||
| import Control.Exception (throw) |  | ||||||
| import Data.List.NonEmpty (toList) | import Data.List.NonEmpty (toList) | ||||||
| import qualified Data.Set as Set | import Data.Void (Void) | ||||||
| import Data.Void |  | ||||||
| import Text.Megaparsec | import Text.Megaparsec | ||||||
| import Text.Megaparsec.Char | import Text.Megaparsec.Char | ||||||
| import Text.Megaparsec.Error (errorBundlePretty, ParseErrorBundle) | import Text.Megaparsec.Error (errorBundlePretty, ParseErrorBundle) | ||||||
|  |  | ||||||
|  | import qualified Data.Set as Set | ||||||
|  |  | ||||||
| type Parser = Parsec Void [LToken] | type Parser = Parsec Void [LToken] | ||||||
|  |  | ||||||
| data TricuAST | data TricuAST | ||||||
| @ -24,17 +24,24 @@ data TricuAST | |||||||
|   | TStem TricuAST |   | TStem TricuAST | ||||||
|   | TFork TricuAST TricuAST |   | TFork TricuAST TricuAST | ||||||
|   | SLambda [String] TricuAST |   | SLambda [String] TricuAST | ||||||
|  |   | SEmpty | ||||||
|   deriving (Show, Eq, Ord) |   deriving (Show, Eq, Ord) | ||||||
|  |  | ||||||
| parseTricu :: String -> [TricuAST] | parseTricu :: String -> [TricuAST] | ||||||
| parseTricu input = | parseTricu input | ||||||
|   let nonEmptyLines = filter (not . null) (lines input) |   | null tokens = [] | ||||||
|   in map parseSingle nonEmptyLines |   | otherwise = map parseSingle tokens | ||||||
|  |   where | ||||||
|  |     tokens = case lexTricu input of | ||||||
|  |       [] -> [] | ||||||
|  |       tokens -> lines input | ||||||
|  |  | ||||||
| parseSingle :: String -> TricuAST | parseSingle :: String -> TricuAST | ||||||
| parseSingle input = case runParser parseExpression "" (lexTricu input) of | parseSingle input = case lexTricu input of | ||||||
|   Left  err -> error $ handleParseError err |   [] -> SEmpty | ||||||
|   Right ast -> ast |   tokens -> case runParser parseExpression "" tokens of | ||||||
|  |     Left err -> error $ handleParseError err | ||||||
|  |     Right ast -> ast | ||||||
|  |  | ||||||
| parseExpression :: Parser TricuAST | parseExpression :: Parser TricuAST | ||||||
| parseExpression = choice | parseExpression = choice | ||||||
|  | |||||||
							
								
								
									
										30
									
								
								src/REPL.hs
									
									
									
									
									
								
							
							
						
						
									
										30
									
								
								src/REPL.hs
									
									
									
									
									
								
							| @ -5,10 +5,12 @@ import Lexer | |||||||
| import Parser | import Parser | ||||||
| import Research | import Research | ||||||
|  |  | ||||||
|  | import Control.Exception         (SomeException, catch) | ||||||
|  | import Control.Monad.IO.Class    (liftIO) | ||||||
| import Data.List                 (intercalate) | import Data.List                 (intercalate) | ||||||
| import qualified Data.Map as Map |  | ||||||
| import System.Console.Haskeline | import System.Console.Haskeline | ||||||
| import System.IO                 (hFlush, stdout) |  | ||||||
|  | import qualified Data.Map as Map | ||||||
|  |  | ||||||
| repl :: Map.Map String T -> IO () | repl :: Map.Map String T -> IO () | ||||||
| repl env = runInputT defaultSettings (loop env) | repl env = runInputT defaultSettings (loop env) | ||||||
| @ -23,15 +25,25 @@ repl env = runInputT defaultSettings (loop env) | |||||||
|           outputStrLn "" |           outputStrLn "" | ||||||
|           loop env |           loop env | ||||||
|         Just input -> do |         Just input -> do | ||||||
|           let clearEnv = Map.delete "__result" env |           newEnv <- liftIO $ (processInput env input `catch` errorHandler env) | ||||||
|               newEnv   = evalSingle clearEnv (parseSingle input) |  | ||||||
|           case Map.lookup "__result" newEnv of |  | ||||||
|             Just r -> do |  | ||||||
|               outputStrLn $ "tricu > " ++ show r |  | ||||||
|               outputStrLn $ "DECODE -: \"" ++ decodeResult r ++ "\"" |  | ||||||
|             Nothing -> return () |  | ||||||
|           loop newEnv |           loop newEnv | ||||||
|  |  | ||||||
|  |     processInput :: Map.Map String T -> String -> IO (Map.Map String T) | ||||||
|  |     processInput env input = do | ||||||
|  |       let clearEnv = Map.delete "__result" env | ||||||
|  |           newEnv = evalSingle clearEnv (parseSingle input) | ||||||
|  |       case Map.lookup "__result" newEnv of | ||||||
|  |         Just r -> do | ||||||
|  |           putStrLn $ "tricu > " ++ show r | ||||||
|  |           putStrLn $ "READ -: \"" ++ decodeResult r ++ "\"" | ||||||
|  |         Nothing -> return () | ||||||
|  |       return newEnv | ||||||
|  |  | ||||||
|  |     errorHandler :: Map.Map String T -> SomeException -> IO (Map.Map String T) | ||||||
|  |     errorHandler env e = do | ||||||
|  |       putStrLn $ "Error: " ++ show e | ||||||
|  |       return env | ||||||
|  |  | ||||||
| decodeResult :: T -> String | decodeResult :: T -> String | ||||||
| decodeResult tc = case toNumber tc of | decodeResult tc = case toNumber tc of | ||||||
|   Right num -> show num |   Right num -> show num | ||||||
|  | |||||||
| @ -1,10 +1,11 @@ | |||||||
| module Research where | module Research where | ||||||
|  |  | ||||||
| import Data.List (intercalate) |  | ||||||
| import Control.Monad.State | import Control.Monad.State | ||||||
| import qualified Data.Map as Map | import Data.List (intercalate) | ||||||
| import Data.Map (Map) | import Data.Map (Map) | ||||||
|  |  | ||||||
|  | import qualified Data.Map as Map | ||||||
|  |  | ||||||
| data T = Leaf | Stem T | Fork T T | data T = Leaf | Stem T | Fork T T | ||||||
|   deriving (Show, Eq, Ord) |   deriving (Show, Eq, Ord) | ||||||
|  |  | ||||||
| @ -36,7 +37,7 @@ _K = Stem Leaf | |||||||
|  |  | ||||||
| -- Identity | -- Identity | ||||||
| -- We use the "point-free" style which drops a redundant node | -- We use the "point-free" style which drops a redundant node | ||||||
| -- Full _I form (SKK): Fork (Stem (Stem Leaf)) (Stem Leaf) | -- Full I form (SKK): Fork (Stem (Stem Leaf)) (Stem Leaf) | ||||||
| _I :: T | _I :: T | ||||||
| _I = Fork (Stem (Stem Leaf)) Leaf  | _I = Fork (Stem (Stem Leaf)) Leaf  | ||||||
|  |  | ||||||
|  | |||||||
							
								
								
									
										15
									
								
								test/Spec.hs
									
									
									
									
									
								
							
							
						
						
									
										15
									
								
								test/Spec.hs
									
									
									
									
									
								
							| @ -25,7 +25,6 @@ tests :: TestTree | |||||||
| tests = testGroup "Tricu Tests" | tests = testGroup "Tricu Tests" | ||||||
|   [ lexerTests |   [ lexerTests | ||||||
|   , parserTests |   , parserTests | ||||||
|   , integrationTests |  | ||||||
|   , evaluationTests |   , evaluationTests | ||||||
|   , lambdaEvalTests |   , lambdaEvalTests | ||||||
|   , libraryTests |   , libraryTests | ||||||
| @ -159,18 +158,6 @@ parserTests = testGroup "Parser Tests" | |||||||
| --      parseTricu input @?= expect | --      parseTricu input @?= expect | ||||||
|   ] |   ] | ||||||
|  |  | ||||||
| integrationTests :: TestTree |  | ||||||
| integrationTests = testGroup "Integration Tests" |  | ||||||
|   [ testCase "Combine lexer and parser" $ do |  | ||||||
|       let input = "x = t t t" |  | ||||||
|           expect = SFunc "x" [] (SApp (SApp TLeaf TLeaf) TLeaf) |  | ||||||
|       parseSingle input @?= expect |  | ||||||
|   , testCase "Complex Tree Calculus expression" $ do |  | ||||||
|       let input = "t (t t t) t" |  | ||||||
|           expect = SApp (SApp TLeaf (SApp (SApp TLeaf TLeaf) TLeaf)) TLeaf |  | ||||||
|       parseSingle input @?= expect |  | ||||||
|   ] |  | ||||||
|  |  | ||||||
| evaluationTests :: TestTree | evaluationTests :: TestTree | ||||||
| evaluationTests = testGroup "Evaluation Tests" | evaluationTests = testGroup "Evaluation Tests" | ||||||
|   [ testCase "Evaluate single Leaf" $ do |   [ testCase "Evaluate single Leaf" $ do | ||||||
| @ -317,7 +304,7 @@ libraryTests = testGroup "Library Tests" | |||||||
|       let input = "s (t) (t) (t)" |       let input = "s (t) (t) (t)" | ||||||
|           env = evalTricu library (parseTricu input) |           env = evalTricu library (parseTricu input) | ||||||
|       result env @?= Fork Leaf (Stem Leaf) |       result env @?= Fork Leaf (Stem Leaf) | ||||||
|   , testCase "SKK == I" $ do -- Tests for fully expanded I form |   , testCase "SKK == I (fully expanded)" $ do | ||||||
|       let input = "s k k" |       let input = "s k k" | ||||||
|           env = evalTricu library (parseTricu input) |           env = evalTricu library (parseTricu input) | ||||||
|       result env @?= Fork (Stem (Stem Leaf)) (Stem Leaf) |       result env @?= Fork (Stem (Stem Leaf)) (Stem Leaf) | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user
	 James Eversole
					James Eversole