Skip to content

Instantly share code, notes, and snippets.

@osa1
Created September 13, 2012 19:33
Show Gist options
  • Save osa1/3716984 to your computer and use it in GitHub Desktop.
Save osa1/3716984 to your computer and use it in GitHub Desktop.
left-recursion ;-(
var :: Parser Var
var = buildVar <$> namePart <*> funcalls <*> selectors
where namePart :: Parser (Either Name Exp)
namePart = (Right <$> between (spChar '(') (spChar ')') exp)
<|> (Left <$> name)
funcalls :: Parser [(Maybe Name, FunArg)]
funcalls = many argPart
selectors :: Parser [(Either Exp Name)]
selectors = many $
(Left <$> between (spChar '[') (spChar ']') exp)
<|> (Right <$> (spChar '.' >> name))
methodName :: Parser Name
methodName = spChar ':' >> name
argPart :: Parser (Maybe Name, FunArg)
argPart = (,) <$> optionMaybe methodName <*> funArg
buildVar :: Either Name Exp -> [(Maybe Name, FunArg)] -> [(Either Exp Name)] -> Var
buildVar (Left name) ((Just methodName, args):rest) selectors =
buildVar' (PEFunCall (MethodCall (PEVar (Name name)) methodName args)) rest selectors
buildVar (Left name) ((Nothing, args):rest) selectors =
buildVar' (PEFunCall (NormalFunCall (PEVar (Name name)) args)) rest selectors
buildVar (Right exp) ((Just methodName, args):rest) selectors =
buildVar' (PEFunCall (MethodCall (Paren exp) methodName args)) rest selectors
buildVar (Right exp) ((Nothing, args):rest) selectors =
buildVar' (PEFunCall (NormalFunCall (Paren exp) args)) rest selectors
buildVar (Left name) [] ((Left exp):rest) =
buildVar'' (Select (PEVar (Name name)) exp) rest
buildVar (Left name) [] ((Right name'):rest) =
buildVar'' (SelectName (PEVar (Name name)) name') rest
buildVar (Right exp) [] ((Left exp'):rest) =
buildVar'' (Select (Paren exp) exp') rest
buildVar (Right exp) [] ((Right name):rest) =
buildVar'' (SelectName (Paren exp) name) rest
buildVar (Left name) [] [] = Name name
buildVar (Right _) [] [] = undefined -- this is an error
buildVar' :: PrefixExp -> [(Maybe Name, FunArg)] -> [(Either Exp Name)] -> Var
buildVar' pe ((Just name, args):rest) selectors =
buildVar' (PEFunCall (MethodCall pe name args)) rest selectors
buildVar' pe ((Nothing, args):rest) selectors =
buildVar' (PEFunCall (NormalFunCall pe args)) rest selectors
buildVar' pe [] ((Left exp):rest) =
buildVar'' (Select pe exp) rest
buildVar' pe [] ((Right name):rest) =
buildVar'' (SelectName pe name) rest
buildVar' _ [] [] = undefined -- error
buildVar'' :: Var -> [(Either Exp Name)] -> Var
buildVar'' var ((Left exp):rest) =
buildVar'' (Select (PEVar var) exp) rest
buildVar'' var ((Right name):rest) =
buildVar'' (SelectName (PEVar var) name) rest
buildVar'' var [] = var
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment