view interps/rhotor/Parser.hs @ 12500:e48c08805365 draft default tip

<b_jonas> ` learn \'The password of the month is Cthulhuquagdonic Mothraquagdonic Narwhalicorn.\' # https://logs.esolangs.org/libera-esolangs/2024-04.html#lKE Infinite craft
author HackEso <hackeso@esolangs.org>
date Wed, 01 May 2024 06:39:10 +0000
parents 859f9b4339e6
children
line wrap: on
line source

module Parser (parse)
where

import Data.List
import Uniqs
import Node

data Token =	Variable String 			|
				NewVariable String 			|
				TFunction 					|
				Fail						|
				TCons						|
				TLT		| TGT				|
				String String				|
				Number Integer  			|
				SubExp [Token]  			|
				NCons Token Token			|
				NFunction Token Token Token	|
				NApplication Token Token	|
				TNil						


parse		:: String -> Node
parse x		= tokenToNode (parseIntern (tokenize x)) [] Root
			
{- Tokenizer -}			

tokenize									:: String -> [Token]
tokenize []									= []
tokenize ( '/' :t)							= (TFunction : tokenize t)
tokenize ( '\\':t)							= (Fail		: tokenize t)
tokenize ( ',' :t)							= (TCons		: tokenize t)
tokenize ( '<' :t)							= (TLT		: tokenize t)
tokenize ( '>' :t)							= (TGT		: tokenize t)
tokenize ( '%' :( '"' :t )) 				= (String text : tokenize q) 
											where (text,q) = (textTokenize t)
tokenize ( '%' :( '\'' :(c:t))) 			= (Number (toInteger (fromEnum c)) : tokenize t) 
tokenize ( '%' :t)							= (Number (read text) : tokenize q)
											where (text,q) = (numberTokenize t)
tokenize ( ':' :t)							= (NewVariable text : tokenize q)	
											where (text,q) = (varTokenize t)
tokenize y@( x  :t)             			
	| (x >= 'a' && x <= 'z') 				= (Variable text : tokenize q)								
	| elem x ". \n\t\r"						= tokenize t
	| (x >= 'A' && x <= 'Z') 				= tokenize t
	where (text,q) = (varTokenize y)
						

textTokenize						:: String -> (String,String)
textTokenize ( '\\' : ( 'n' :t) )	= (( '\n' :text), q)
									where (text,q) = (textTokenize t)
textTokenize ( '\\' : (  x  :t) )	= ((x:text), q)
									where (text,q) = (textTokenize t)
textTokenize ( '"' : t)				= ("",t)
textTokenize ( x   : t)				= ((x:text), q)
									where (text,q) = (textTokenize t)


numberTokenize						:: String -> (String,String)
numberTokenize	[]					= ("",[])
numberTokenize y@( x   : t)		
	| x >= '0' && x <= '9' 			= ((x:text), q)  									
	| otherwise				 		= ("",y)
	where (text,q) = (numberTokenize t)

	
varTokenize							:: String -> (String,String)
varTokenize	[]						= ("",[])
varTokenize y@( x   : t)		
	| x >= 'a' && x <= 'z' 			= ((x:text), q)								
	| otherwise				 		= ("",y)
	where (text,q) = (varTokenize t) 

									
instance Show Token where
	show (Variable x)		= "Variable " ++ (show x)
	show (NewVariable x)	= "NewVariable " ++ (show x)
	show (TFunction)		= "TFunction"
	show (Fail)				= "Fail"
	show (TCons)			= "TCons"
	show (TLT)				= "TLT"
	show (TGT)				= "TGT"
	show (String x)			= "String " ++ (show x)
	show (Number x)			= "Number " ++ (show x)
	show (SubExp x)			= "SubExp " ++ (show x)
	show (NCons x y)		= "NCons (" ++ (show x) ++ ") (" ++ (show y) ++ ")"
	show (NFunction x y z)	= "NFunction (" ++ (show x) ++ ") (" ++ (show y) ++ ") (" ++ (show z) ++ ")"
	show (NApplication x y)	= "NApplication (" ++ (show x) ++ ") (" ++ (show y) ++ ")"
	show (TNil)			= "TNil"

instance Eq Token where
	(==) TFunction TFunction		= True
	(==) Fail Fail					= True
	(==) _ _						= False
	
{- Parser -}

parseIntern		:: [Token] -> Token
parseIntern	x	= stripSubExp (head (parseApplication (parseCons (fst (parseFunctions (fst (parseTT (expandNumbers (expandStrings x)))))))))

onReverse		:: ([a] -> [a]) -> [a] -> [a]
onReverse x y	= (reverse (x (reverse y)))

expandStrings					:: [Token] -> [Token]
expandStrings []				= []
expandStrings ((String x):rest)	= (xtail (concatMap toNums x)) ++ (expandStrings rest)
								where
									toNums x	= [TCons,TLT,Number (toInteger (fromEnum x)),TGT]
									xtail []	= []
									xtail (h:t)	= t
expandStrings (h:rest)			= h:(expandStrings rest)

expandNumbers					:: [Token] -> [Token]
expandNumbers []				= []
expandNumbers ((Number x):rest)	= (toNils x) ++ (expandNumbers rest)
								where
									toNils 0   	= [TNil]
									toNils (n+1)	= TNil:(TCons:(toNils n))
expandNumbers (h:rest)			= h:(expandNumbers rest)

parseTT			:: [Token] -> ([Token],[Token])
parseTT []		= ([],[])
parseTT (TGT:y)	= ([],y)
parseTT (TLT:y)	= ((SubExp frst:snd),thrd)
				where
					(frst,lst) = parseTT y
					(snd,thrd) = parseTT lst
						
parseTT (x:y)	= ((x:frst),lst)
				where (frst,lst) = parseTT y

partitionWhen 			:: (a -> Bool) -> [a] -> Maybe ([a],[a])
partitionWhen f x@(h:t)	= 	if f h then
								Just ([],x)
							else case (partitionWhen f t) of
								Nothing		-> Nothing
								Just (q,r)	-> Just ((h:q),r)
partitionWhen f []		= Nothing

partitionWhen2			:: (a -> Bool) -> [a] -> Maybe ([a],a,[a])
partitionWhen2 f x		= case (partitionWhen f x) of
							Nothing		-> Nothing
							Just (q,h:t)-> Just (q,h,t)



parseFunctions		:: [Token] -> ([Token],[Token])
parseFunctions x	= case (partitionWhen2 (\y -> y == TFunction || y == Fail) x) of
						Nothing					-> ((parseSubFunctions x),[])
						Just (fl,Fail,frst)		-> (fl,frst)
						Just (a,TFunction,c) 	-> let
													(def,rst) = parseFunctions c
													(frst,lrst) = parseFunctions rst
													in ([NFunction (SubExp (fst (parseFunctions a))) (SubExp (fst (parseFunctions def))) (SubExp (fst (parseFunctions frst)))],lrst)
											
parseSubFunctions					:: [Token] -> [Token]
parseSubFunctions []				= []
parseSubFunctions ((SubExp x):t)	= (SubExp (fst (parseFunctions x))):(parseSubFunctions t)
parseSubFunctions (x:t)				= x:(parseSubFunctions t)

parseApplication					:: [Token] -> [Token]
parseApplication x					= foldr iteration [] (reverse x)
										where
											iteration itema (itemb:rest)	= (NApplication itemb (parseSubApplication itema)):rest
											iteration item []				= [parseSubApplication item]
											
parseSubApplication						:: Token -> Token
parseSubApplication (SubExp x)			= SubExp (parseApplication x)
parseSubApplication (NFunction x y z)	= NFunction (parseSubApplication x) (parseSubApplication y) (parseSubApplication z)
parseSubApplication (NCons x y)			= NCons (parseSubApplication x) (parseSubApplication y) 
parseSubApplication	x					= x

parseCons							:: [Token] -> [Token]
parseCons x							= foldr iteration [] x
										where
											iteration itema (TCons:(itemb:rest))	= (NCons (parseSubCons itema) itemb):rest
											iteration item list						= (parseSubCons item):list
											
parseSubCons					:: Token -> Token
parseSubCons (SubExp x)			= SubExp (parseCons x)
parseSubCons (NFunction x y z)	= NFunction (parseSubCons x) (parseSubCons y) (parseSubCons z)
parseSubCons x					= x


stripSubExp						:: Token -> Token
stripSubExp (SubExp [a])		= stripSubExp a
stripSubExp (SubExp [])			= TNil
stripSubExp (NCons a b)			= NCons (stripSubExp a) (stripSubExp b)
stripSubExp (NFunction a b c)	= NFunction (stripSubExp a) (stripSubExp b) (stripSubExp c)
stripSubExp (NApplication a b)	= NApplication (stripSubExp a) (stripSubExp b)
stripSubExp a					= a

tokenToNode								:: Token -> [(String,Uniqs)] -> Uniqs -> Node
tokenToNode TNil _ _					= Nil
tokenToNode (NCons a b) tab cn			= Cons (tokenToNode a tab (A cn)) (tokenToNode b tab (B cn))
tokenToNode (NApplication a b) tab cn	= Application (tokenToNode a tab (A cn)) (tokenToNode b tab (B cn))
tokenToNode (NFunction a b c) tab cn	= let (ac,ntab) = functionPtrnToNode a tab (C cn)
											in (Function ac (tokenToNode b ntab (A cn)) (tokenToNode c tab (B cn)))
tokenToNode (Variable n) tab _			= let Just a = (lookup n tab)
											in (Symbol a)

functionPtrnToNode								:: Token -> [(String,Uniqs)] -> Uniqs -> (Node,[(String,Uniqs)])
functionPtrnToNode TNil tab	_					= (Nil,tab)
functionPtrnToNode (NCons a b) tab cn 			= 	let
														(newa,tab2) = functionPtrnToNode a tab (A cn)
														(newb,tab3) = functionPtrnToNode b tab2 (B cn)
													in ((Cons newa newb),tab3)
functionPtrnToNode (NApplication a b) tab cn	= 	let
										   	 			(newa,tab2) = functionPtrnToNode a tab (A cn)
										   	 			(newb,tab3) = functionPtrnToNode b tab2 (B cn)
										   	 		in ((Application newa newb),tab3)
functionPtrnToNode a@(NFunction _ _ _) tab cn	= ((tokenToNode a tab cn),tab)

functionPtrnToNode (Variable n)	tab cn			= case (lookup n tab) of
													Just a -> (Symbol a,tab)
													Nothing -> (Symbol cn,((n,cn):tab))
																
functionPtrnToNode (NewVariable n) tab cn  		= (Symbol cn,((n,cn):(deleteBy filter (n,cn) tab)))
												where filter (a,_) (b,_) = a == b