Mercurial > repo
diff interps/rhotor/Parser.hs @ 996:859f9b4339e6
<Gregor> tar xf egobot.tar.xz
author | HackBot |
---|---|
date | Sun, 09 Dec 2012 19:30:08 +0000 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/interps/rhotor/Parser.hs Sun Dec 09 19:30:08 2012 +0000 @@ -0,0 +1,220 @@ +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 + \ No newline at end of file