diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright (c) 2015, L. Thomas van Binsbergen
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+    * Neither the name of L. Thomas van Binsbergen nor the names of other
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
diff --git a/changelog.txt b/changelog.txt
new file mode 100644
--- /dev/null
+++ b/changelog.txt
@@ -0,0 +1,70 @@
+0.3.0.7 -> 0.3.0.8
+  + export maximumPivots and maximumPivotAtNt
+0.3.0.8 -> 0.3.0.9
+  + include bit of the input string when showing an error message (without whitespace)
+  + exporting <multiple/some/many>SepBy2
+  + exporting within, parens, braces, brackets, angles, quotes and dquotes
+  + added character literals to Token type
+  + exporting <:=
+  + <<<**> and <**>>> for shortest and longest match, respectively
+    defined some/many and variants using <**>>> and <<<**>
+    disambiguation remains very experimental 
+0.3.0.9 -> 0.3.0.10
+  + exporting chooses
+0.3.0.10 -> 0.3.0.11
+  + parse option for disabling select test (lookahead)
+
+0.3.0.11 -> 0.4.0.1
+  + replaced parser by reduced descriptor GLL (RGLL)
+  + renamed GLL.Types.Grammar to GLL.Types.Derivations
+  + renamed GLL.Types.Abstract to GLL.Types.Grammar
+  + exporting GLL.Types.Grammar, GLL.Types.Derivations, GLL.Combinators.Options, GLL.Combinators.Memoisation, GLL.Flags
+
+0.4.0.1 -> 0.4.0.2
+  + generalised `within`
+  + different whitespace and comment handling in predefined lexer
+  + predefined lexer handles (nested) comment-blocks
+
+0.4.0.2 -> 0.4.0.3
+  M added hex, octal and binary representation to integer literals
+  + added float literals
+  + exporting `preferably` and `reluctantly`
+  M renamed `rassoc` to shortest_match
+  M renamed `lassoc` to longest_match
+  - removed `assoc`
+  + version of `chooses` that is left-biased (w.r.t. alternatives)
+  + generalised arguments of longest_match and shortest_match to IsAltExpr 
+  + exporting `optionalWithDef`
+
+0.4.0.3 -> 0.4.0.4
+  + `chooses` cannot be given an empty list (runtime error)
+  + updated `base` dependency
+
+0.4.0.4 -> 0.4.0.5
+  + relaxed cabal version constraint
+
+0.4.0.5 -> 0.4.0.6
+  + generalised the definition of `within` combinator with respect to token type
+
+0.4.0.6 -> 0.4.0.7
+  + simplified Ridge's "parsing context" in the semantic phase
+
+0.4.0.7 -> 0.4.0.8
+  + unified usage of input in both parser and combinators, speeding up initialisation of large files
+  + fixed 'noSelectTest' 'ParseOption'
+
+0.4.0.8 -> 0.4.0.9
+  + reinstated a "binarised version" of the interface 
+  + count number of successes in ParseResult, not just True/False
+
+0.4.0.9 -> 0.4.0.10
+  + build expression grammars from operator tables
+
+0.4.0.10 -> 0.4.0.11
+  + integer literals are now by default considered as natural numbers only, the 'signed_int_lits' flag of 'LexerSettings' can be used to turn on signed integers, restoring the behaviour of previous versions
+
+0.4.0.11 -> 0.4.0.12
+  + export 'grammarOf'
+  + let 'parse' throw errors by default
+  + changed priorities of operator tables to doubles 
+  + removed need to specify associativity of prefix operators in operator table
diff --git a/fungll-combinators.cabal b/fungll-combinators.cabal
new file mode 100644
--- /dev/null
+++ b/fungll-combinators.cabal
@@ -0,0 +1,50 @@
+-- Initial haskell-gll.cabal generated by cabal init.  For further 
+-- documentation, see http://haskell.org/cabal/users-guide/
+
+-- The name of the package.
+name:                fungll-combinators
+version:             0.1.0.1
+synopsis:            GLL parser with simple combinator interface 
+license:             BSD3
+license-file:        LICENSE
+author:              L. Thomas van Binsbergen
+maintainer:          L. Thomas van Binsbergen <ltvanbinsbergen@acm.org>
+category:            Compilers
+build-type:          Simple 
+cabal-version:       >=1.22
+tested-with:         GHC == 8.2.1
+copyright:           Copyright (C) 2019 L. Thomas van Binsbergen
+stability:           experimental
+description:         
+
+        The package fungll-combinators provides generalised top-down parsing combinators according to the 
+        FUNGLL parsing algorithm [Van Binsbergen et al. 2018].  
+        .
+        Please email any questions, comments and suggestions to the 
+        maintainer.
+
+extra-source-files: changelog.txt
+
+library
+    hs-source-dirs  :   src
+    build-depends   :     base >=4.3.1.0 && <= 5 
+                        , containers >= 0.4
+                        , array
+                        , TypeCompose
+                        , pretty
+                        , text
+                        , regex-applicative >= 0.3
+                        , time >= 1.8
+                        , gll >= 0.4.0.12
+    exposed-modules :     GLL.ParserCombinators
+                        , GLL.Types.BSR
+                        , GLL.Types.DataSets
+
+    other-modules   :     GLL.Combinators.Visit.FUNGLL
+                        , GLL.Combinators.Visit.Sem
+                        , GLL.Combinators.Visit.Join
+                        , GLL.Combinators.Interface
+    ghc-options:         -fwarn-incomplete-patterns -fwarn-monomorphism-restriction -fwarn-unused-imports
+    default-language:    Haskell2010
+    default-extensions:  TypeOperators, FlexibleInstances, ScopedTypeVariables, TypeSynonymInstances
+
diff --git a/src/GLL/Combinators/Interface.hs b/src/GLL/Combinators/Interface.hs
new file mode 100644
--- /dev/null
+++ b/src/GLL/Combinators/Interface.hs
@@ -0,0 +1,828 @@
+{-# LANGUAGE TypeOperators, FlexibleInstances #-}
+
+{-| 
+
+The user writes a combinator expression representing a grammar.
+The represented grammar is extracted and given, together with an input string,
+to a back-end parser.
+The derivations constructed by the parser act as a guide in the "semantic phase"
+in which the combinator expressions are evaluated to produce semantic results
+for all derivations. Infinitely many derivations would result in a loop. 
+This problem is avoided by discarding the derivations that would arise from such a loop.
+
+This library provides 
+"Control.Applicative"-like parser combinators: '<**>' for sequencing, '<||>' for 
+choice, '<$$>' for application, 'satisfy' instead of pure and derived 
+combinators '<**', '**>', '<$$', 'many', 'some' and 'optional'.
+
+The semantic phase might benefit from memoisation (see 'memo'). 
+Using memoisation voids pureness waranty". 
+
+=== Example usage
+This library differs from parser combinator libraries in that combinator expressions
+are used to describe a grammar rather than a parser.
+
+A rule is considered to be of the form X ::= a | .. | z, and represented by the combinator
+expression.
+
+@
+pX = \"X\" '<::=>' altA '<||>' ... '<||>' altZ
+@
+
+Alternates (\'a\' ... \'z\') start with the application of 
+a semantic action using '<$$>' (or variants '<$$' and 'satisfy'). 
+The alternate is extended with '<**>' (or variants '**>', '<**').
+
+@
+altA = action1 '<$$>' 'keychar' \'a\' '<**>' pX
+altZ = action2 '<$$>' 'keychar' \'z\'
+@
+
+Usability is improved by automatic lifting between expressions that represent symbols
+and alternates. The main difference with "Control.Applicative" style parser combinator
+libraries is that the user must use '<:=>' (or '<::=>') to represent all recursive 
+nonterminals and must use '<::=>' to represent all nonterminals that potentially lead
+to an infinite number of derivations. It is, however, possible to represent left-recursive
+nonterminals.
+
+=== Example
+
+In this example we define expressions for parsing (and evaluating) simple arithmetic 
+expressions for single digit integers. 
+
+The library is capable of parsing arbitrary token types that are 'Parseable', orderable
+and have a 'Show' instance.
+This example demonstrates the usage of the builtin 'Token' datatype and uses the
+elementary parsers 'keychar' and 'int_lit' to create parsers for character- and integer-terminals.
+
+We define a very simpler lexer first.
+
+@
+lexer :: String -> [Token]
+lexer [] = []
+lexer (x:xs)
+    | isDigit x = 'IntLit' (Just (read [x])) : lexer xs
+    | otherwise = 'Char' x                   : lexer xs
+@
+
+Note that the Char constructor of the 'Token' type is used for character-level parsing.
+Char contains no lexeme, unlike the Int constructor.
+
+Consider the following (highly ambiguous and left-recursive) grammar:
+
+@
+Expr ::= Expr \'-\' Expr
+       | Expr \'+\' Expr
+       | Expr \'*\' Expr
+       | Expr \'/\' Expr
+       | INT
+       | \'(\' Expr \')\'
+@
+
+The grammar is translated to the following combinator expression, adding the expected
+evaluation functions as semantic actions.
+
+@
+pExpr :: BNF Token Int
+pExpr = \"Expr\" '<::=>' (-) '<$$>' pExpr '<**' 'keychar' \'-\' '<**>' pExpr
+                 '<||>' (+) '<$$>' pExpr '<**' 'keychar' \'+\' '<**>' pExpr
+                 '<||>' (*) '<$$>' pExpr '<**' 'keychar' \'*\' '<**>' pExpr
+                 '<||>' div '<$$>' pExpr '<**' 'keychar' \'/\' '<**>' pExpr
+                 '<||>' 'int_lit'
+                 '<||>' parens pExpr
+@
+
+Note that '<**' is used to ignore the parse result of the second argument and that '**>' 
+is used to ignore the parse result of the first argument. These combinators
+help us to define the /derived combinator/s /within/ and /parens/.
+
+@
+within :: 'BNF' 'Token' a -> 'BNF' 'Token' b -> 'BNF' 'Token' a -> 'BNF' 'Token' b
+within l p r = 'mkRule' $ l '**>' p '<**' r
+
+parens :: 'BNF' 'Token' a -> 'BNF' 'Token' a
+parens p = within ('keychar' '(') p ('keychar' ')')
+@
+
+All possible evaluations are obtained by invoking the 'parse' function.
+
+@
+run1 = 'parse' pExpr (lexer "1+2*2-5")            -- [0,1,0,-5,-9] 
+run2 = 'parse' pExpr (lexer "((1+(2*2))-3)-5")    -- [-3]
+@
+
+With every introduction of an operator '+', '-', '*' or '/' the number of ambiguities is 
+multiplied. The number of ambiguities behaves like the sequence https://oeis.org/A000108.
+
+=== Simple disambiguation
+
+This library offers simple disambiguation strategies that are applied post-parse 
+(the parser still faces the ambiguity, but the semantic evaluation only yields 
+the results according to the strategy). The disambiguations strategies are still
+in the /experimental/ phase. 
+
+We group the operators according to their priorities and use 
+'<::=' to turn the choice operator '<||>' into a left-biased operator locally
+(use 'leftBiased' for the same effect globally).
+
+@
+pExpr1 :: BNF Token Int
+pExpr1 = \"Expr\" '<::='  (      (-) '<$$>' pExpr1 '<**' 'keychar' \'-\' '<**>' pExpr1
+                        '<||>' (+) '<$$>' pExpr1 '<**' 'keychar' \'+\' '<**>' pExpr1 )
+                 '<||>' (      (*) '<$$>' pExpr1 '<**' 'keychar' \'*\' '<**>' pExpr1
+                        '<||>' div '<$$>' pExpr1 '<**' 'keychar' \'/\' '<**>' pExpr1 )
+                 '<||>' (      'int_lit'
+                        '<||>' 'parens' pExpr1 )
+
+run3 = 'parseWithOptions' ['maximumPivotAtNt'] pExpr1 (lexer "1+2*2-5") -- [0]
+@
+
+The option 'maximumPivotAtNt' enables the 'longest-match' disambiguation strategy 
+and makes the arithmetic operators left-associative.
+
+=== Grammar rewrites
+
+To deal with the particular ambiguities associated with operators we can 
+rewrite the grammar to disambiguate pre-parse.
+
+We define the /chainl/ combinator for parsing chains of left-associative operators.
+
+@
+chainl :: 'BNF' 'Token' a -> 'BNF' 'Token' (a -> a -> a) -> 'BNF' 'Token' a
+chainl p s = 'mkRule' $
+    foldl (flip ($)) '<$$>' p '<**>' many (flip '<$$>' s '<**>' p)
+@
+
+The expression parser is written with chainl as follows:
+
+@
+pExpr2 :: BNF Token Int
+pExpr2 = pE1
+ where  pE1 = chainl pE2 (\"E1\" '<::=>' (+) '<$$' 'keychar' \'+\' '<||>' (-) '<$$' 'keychar' \'-\')
+        pE2 = chainl pE3 (\"E2\" '<::=>' (*) '<$$' 'keychar' \'*\' '<||>' div '<$$' 'keychar' \'/\')
+        pE3 = \"E3\" '<::=>' 'int_lit' '<||>' parens pExpr2
+
+run4 = 'parse' 'pExpr2' (lexer "1+2*2-5")       -- [0]
+@
+
+Pre-parse disambiguation is desirable, as the parsing process could 
+speed up dramatically. In general however, it is not always possible to find 
+the appropriate grammar rewrite and implement it in a high-level combinator such 
+as chainl, /motivating the existence of this library/.
+
+More simple examples can be found in "GLL.Combinators.Test.Interface".
+
+-}
+module GLL.Combinators.Interface (
+    -- * Elementary parsers
+    term_parser, satisfy,
+    -- ** Elementary parsers using the 'Token' datatype 
+    keychar, keyword, int_lit, float_lit, bool_lit, char_lit, string_lit, alt_id_lit, id_lit, token,
+    -- ** Elementary character-level parsers
+    char, 
+    -- * Elementary combinators
+    -- *** Sequencing
+    (<**>),
+    -- *** Choice
+    (<||>),
+    -- *** Semantic actions
+    (<$$>),
+    -- *** Nonterminal introduction
+    (<:=>),(<::=>),chooses,chooses_prec,
+    -- * Types
+    -- ** Grammar (combinator expression) types
+    BNF, SymbExpr, AltExpr, AltExprs,
+    -- ** Parseable token types 
+    Token(..), Parseable(..), SubsumesToken(..), unlexTokens, unlexToken,  
+    -- * Running a parser 
+    parse, printParseData, evaluatorWithParseData,
+    -- **  Running a parser with options
+    parseWithOptions, parseWithParseOptions, evaluatorWithParseDataAndOptions, 
+    printParseDataWithOptions, 
+    --printGrammarData,
+    -- *** Possible options
+    CombinatorOptions, CombinatorOption, 
+             GLL.Combinators.Options.maximumErrors, throwErrors, 
+             maximumPivot, maximumPivotAtNt,leftBiased,
+    -- *** Running a parser with options and explicit failure
+--    parseWithOptionsAndError, parseWithParseOptionsAndError,
+    -- ** Runing a parser to obtain 'ParseResult'.
+--    parseResult, parseResultWithOptions,ParseResult(..),
+    -- ** Builtin lexers.
+    default_lexer, 
+    -- *** Lexer settings
+        lexer, LexerSettings(..), emptyLanguage,
+    -- * Derived combinators
+    mkNt, 
+    -- *** Ignoring semantic results
+    (<$$), (**>), (<**),
+    -- *** EBNF patterns
+    optional, preferably, reluctantly, optionalWithDef,
+    multiple, multiple1, multipleSepBy, multipleSepBy1,
+      multipleSepBy2, within, parens, braces, brackets, angles,
+      foldr_multiple, foldr_multipleSepBy,
+    -- *** Operator expressions
+    fromOpTable, opTableFromList, OpTable, Assoc(..), Fixity(..),
+     -- *** Disambiguation  
+            (<:=), (<::=),(<<<**>), (<**>>>), (<<**>), (<<<**), (**>>>), (<**>>),
+            longest_match,shortest_match,
+            many, many1, some, some1, 
+            manySepBy, manySepBy1, manySepBy2, 
+              someSepBy, someSepBy1,someSepBy2,
+    -- * Lifting
+    HasAlts(..), IsSymbExpr(..), IsAltExpr(..),
+     -- * Memoisation
+    memo, newMemoTable, memClear, MemoTable, MemoRef, useMemoisation,
+    ) where
+
+import GLL.Combinators.Options
+import GLL.Combinators.Visit.FUNGLL
+import GLL.Combinators.Visit.Join
+import GLL.Combinators.Visit.Sem
+import GLL.Combinators.Memoisation
+import GLL.Combinators.Lexer
+import GLL.Types.Grammar
+import GLL.Types.DataSets
+import GLL.Types.BSR
+import GLL.Flags hiding (runOptions)
+import GLL.Parseable.Char
+
+import Control.Monad (when)
+import Control.Compose (OO(..))
+import Control.Arrow
+import qualified Data.Array as A
+import qualified Data.IntMap as IM
+import qualified Data.Map as M
+import qualified Data.Set as S
+import Data.Text (pack)
+import qualified Data.Text
+import Data.IORef 
+import Data.Time.Clock
+import System.IO.Unsafe
+
+parse' :: (Show t, Parseable t, IsSymbExpr s) => ParseOptions -> 
+            PCOptions -> s t a -> [t] -> (ParseResult t, Either String [a])
+parse' popts opts p' input =  
+    let SymbExpr (Nt lower_start, vpa2, vpa3) = 
+          mkRule ("__Augment" <:=> OO [id <$$> p'])
+        start       = pack "__Start"
+        arr         = mkInput input 
+        m           = length input 
+        parse_res   = parser_for start vpa2 arr
+        as          = evaluator_for lower_start vpa3 opts (bsrs_result parse_res) arr
+        res_list    = unsafePerformIO as
+    in (parse_res, if res_success parse_res && not (null res_list)
+                    then Right $ res_list 
+                    else Left (error_message parse_res) )
+-- | Print some information about the parse.
+-- Helpful for debugging.
+printParseData :: (Parseable t, IsSymbExpr s, Show a) => s t a -> [t] -> IO ()
+printParseData = printParseDataWithOptions [] [] 
+
+-- | Variant of 'printParseData' which can be controlled by 'ParseOption's
+printParseDataWithOptions :: (Parseable t, IsSymbExpr s, Show a) => ParseOptions -> CombinatorOptions -> s t a -> [t] -> IO ()
+printParseDataWithOptions popts opts p' input = 
+    let SymbExpr (Nt lower_start,vpa2,vpa3) = toSymb p'
+        start       = pack "__Start"
+        parse_res   = parser_for start vpa2 arr
+        arr         = mkInput input 
+        (_,m)       = A.bounds arr
+    in do startTime <- getCurrentTime
+          putStrLn $ "#tokens:              " ++ (show m)
+          putStrLn $ "#successes:           " ++ (show $ res_successes parse_res)
+          endTime <- getCurrentTime
+          putStrLn $ "recognition time:     " ++ show (diffUTCTime endTime startTime)
+          startTime' <- getCurrentTime
+          putStrLn $ "#descriptors          " ++ (show $ nr_descriptors parse_res)
+          putStrLn $ "#BSRs                 " ++ (show $ nr_bsrs parse_res) 
+          endTime <- getCurrentTime
+          putStrLn $ "parse-data time:      " ++ show (diffUTCTime endTime startTime')
+          putStrLn $ "total time:           " ++ show (diffUTCTime endTime startTime)
+
+-- | Print some information 
+evaluatorWithParseData :: (Parseable t, IsSymbExpr s, Show a) => s t a -> [t] -> [a]
+evaluatorWithParseData = evaluatorWithParseDataAndOptions [] [] 
+
+evaluatorWithParseDataAndOptions :: (Parseable t, IsSymbExpr s, Show a) => ParseOptions -> CombinatorOptions -> s t a -> [t] -> [a]
+evaluatorWithParseDataAndOptions popts opts p' input = 
+    let SymbExpr (Nt lower_start,vpa2,vpa3) = toSymb p'
+        start       = pack "__Start"
+        parse_res   = parser_for start vpa2 arr
+        arr         = mkInput input 
+        (_,m)       = A.bounds arr
+    in unsafePerformIO $ do 
+          startTime <- getCurrentTime
+          putStrLn $ "#tokens:              " ++ (show m)
+          putStrLn $ "#successes:           " ++ (show $ res_successes parse_res)
+          endTime <- getCurrentTime
+          putStrLn $ "recognition time:     " ++ show (diffUTCTime endTime startTime)
+          startTime' <- getCurrentTime
+          putStrLn $ "#descriptors          " ++ (show $ nr_descriptors parse_res)
+          putStrLn $ "#BSRs                 " ++ (show $ nr_bsrs parse_res) 
+          endTime <- getCurrentTime
+          putStrLn $ "parse-data time:      " ++ show (diffUTCTime endTime startTime')
+          startTime' <- getCurrentTime
+          as <- evaluator_for start vpa3 (runOptions opts) (bsrs_result parse_res) arr
+--          putStrLn $ "#derivations:         " ++ show (length as)
+          when (not (null as)) (writeFile "/tmp/derivation" (show (head as)))
+          endTime <- getCurrentTime
+          putStrLn $ "semantic phase:       " ++ show (diffUTCTime endTime startTime')
+          putStrLn $ "total time:           " ++ show (diffUTCTime endTime startTime)
+          return as
+-- | 
+-- Runs a parser given a string of 'Parseable's and returns a list of 
+-- semantic results, corresponding to all finitely many derivations.
+parse :: (Show t, Parseable t, IsSymbExpr s) => s t a -> [t] -> [a]
+parse = parseWithOptions [throwErrors] 
+
+-- | 
+-- Run the parser with some 'CombinatorOptions'.
+parseWithOptions :: (Show t, Parseable t, IsSymbExpr s) => 
+                        CombinatorOptions -> s t a -> [t] -> [a]
+parseWithOptions opts p ts = parseWithParseOptions defaultPOpts opts p ts
+
+-- | 
+-- Run the parser with some 'ParseOptions' and 'CombinatorOptions'.
+parseWithParseOptions :: (Show t, Parseable t, IsSymbExpr s) => 
+                     ParseOptions -> CombinatorOptions -> s t a -> [t] -> [a]
+parseWithParseOptions pcopts opts p ts = 
+    case parseWithParseOptionsAndError pcopts opts p ts of
+        Left str | throw_errors opts'   -> error str
+                 | otherwise            -> []
+        Right as                        -> as
+    where opts' = runOptions opts
+
+-- | 
+-- Run the parser with some 'CombinatorOptions' and return either an error or the results.
+-- Any returned results will be a list of length greater than 0.
+parseWithOptionsAndError :: (Show t, Parseable t, IsSymbExpr s) => 
+                        CombinatorOptions -> s t a -> [t] -> Either String [a]
+parseWithOptionsAndError opts p = parseWithParseOptionsAndError defaultPOpts opts p 
+
+-- | 
+-- Run the parser with some 'ParseOptions' and 'CombinatorOptions'.
+-- Returns either an error or the results.
+-- Any returned results will be a list of length greater than 0.
+parseWithParseOptionsAndError :: (Show t, Parseable t, IsSymbExpr s) => 
+       ParseOptions -> CombinatorOptions -> s t a -> [t] -> Either String [a]
+parseWithParseOptionsAndError popts opts p = (\(_,t) -> t) . parse' defaultPOpts (runOptions opts) p
+
+
+-- | Get the 'ParseResult', containing an 'SPPF', 
+--  produced by parsing the given input with the given parser.
+parseResult :: (Show t, Parseable t, IsSymbExpr s) => s t a -> [t] -> ParseResult t
+parseResult = parseResultWithOptions [] [] 
+
+-- | Get the 'ParseResult' given some 'ParseOptions' and 'CombinatorOptions'. 
+parseResultWithOptions :: (Show t, Parseable t, IsSymbExpr s) => 
+         ParseOptions -> CombinatorOptions -> s t a -> [t] -> ParseResult t
+parseResultWithOptions popts opts p str = 
+    (\(s,_) -> s) $ parse' popts (runOptions opts) p str
+
+defaultPOpts = [strictBinarisation, packedNodesOnly]
+
+infixl 2 <:=>
+-- | 
+-- Form a rule by giving the name of the left-hand side of the new rule.
+-- Use this combinator on recursive non-terminals.
+(<:=>) :: (Show t, Ord t, HasAlts b) => String -> b t a -> SymbExpr t a 
+x <:=> altPs = mkNtRule False False x altPs
+infixl 2 <::=>
+
+-- | 
+--  Variant of '<:=>' for recursive non-terminals that have a potentially infinite
+--  number of derivations for some input string.
+--
+--  A non-terminal yields infinitely many derivations  
+--  if and only if it is left-recursive and would be
+--  left-recursive if all the right-hand sides of the productions of the
+--  grammar are reversed.
+(<::=>) :: (Show t, Ord t, HasAlts b) => String -> b t a -> SymbExpr t a 
+x <::=> altPs = mkNtRule True False x altPs
+
+-- | Variant of '<::=>' that can be supplied with a list of alternates
+chooses :: (Show t, Ord t, IsAltExpr alt) => String -> [alt t a] -> SymbExpr t a
+chooses p alts | null alts = error "chooses cannot be given an empty list of alternatives"
+               | otherwise = (<::=>) p (OO (map toAlt alts))
+
+-- | Variant of '<::=' that can be supplied with a list of alternates
+chooses_prec :: (Show t, Ord t, IsAltExpr alt) => String -> [alt t a] -> SymbExpr t a
+chooses_prec p alts | null alts = error "chooses cannot be given an empty list of alternatives"
+                    | otherwise = (<::=) p (OO (map toAlt alts))
+
+infixl 4 <$$>
+-- |
+-- Form an 'AltExpr' by mapping some semantic action overy the result
+-- of the second argument.
+(<$$>) :: (Show t, Ord t, IsSymbExpr s) => (a -> b) -> s t a -> AltExpr t b
+f <$$> p' = join_apply f p'
+
+infixl 4 <**>,<<<**>,<**>>>
+-- | 
+-- Add a 'SymbExpr' to the right-hand side represented by an 'AltExpr'
+-- creating a new 'AltExpr'. 
+-- The semantic result of the first argument is applied to the second 
+-- as a cross-product. 
+(<**>) :: (Show t, Ord t, IsAltExpr i, IsSymbExpr s) => 
+            i t (a -> b) -> s t a -> AltExpr t b
+pl' <**> pr' = join_seq [] pl' pr'
+
+-- | Variant of '<**>' that applies longest match on the left operand.
+(<**>>>) :: (Show t, Ord t, IsAltExpr i, IsSymbExpr s) => 
+            i t (a -> b) -> s t a -> AltExpr t b
+pl' <**>>> pr' = join_seq [maximumPivot] pl' pr'
+
+-- | Variant of '<**>' that applies shortest match on the left operand.
+(<<<**>) :: (Show t, Ord t, IsAltExpr i, IsSymbExpr s) => 
+            i t (a -> b) -> s t a -> AltExpr t b
+pl' <<<**> pr' = join_seq [minimumPivot] pl' pr'
+
+
+infixr 3 <||>
+-- |
+-- Add an 'AltExpr' to a list of 'AltExpr'
+-- The resuling  '[] :. AltExpr' forms the right-hand side of a rule.
+(<||>) :: (Show t, Ord t, IsAltExpr i, HasAlts b) => i t a -> b t a -> AltExprs t a
+l' <||> r' = let l = toAlt l'
+                 r = altsOf r'
+             in OO (l : r)
+
+-- |
+-- Apply this combinator to an alternative to turn all underlying occurrences
+-- of '<**>' (or variants) apply 'longest match'.
+longest_match :: (Show t, Ord t, IsAltExpr alt) => alt t a -> AltExpr t a
+longest_match isalt = AltExpr (v1,v2,\opts -> v3 (maximumPivot opts))
+  where AltExpr (v1,v2,v3) = toAlt isalt 
+
+-- Apply this combinator to an alternative to turn all underlying occurrences
+-- of '<**>' (or variants) apply 'shortest match'.
+shortest_match :: (Show t, Ord t, IsAltExpr alt) => alt t a -> AltExpr t a
+shortest_match isalt = AltExpr (v1,v2,\opts -> v3 (minimumPivot opts))
+  where AltExpr (v1,v2,v3) = toAlt isalt 
+
+-- | Create a symbol-parse for a terminal given:
+--
+--  * The 'Parseable' token represented by the terminal.
+--  * A function from that 'Parseable' to a semantic result.
+term_parser :: Parseable t => t -> (t -> a) -> SymbExpr t a 
+term_parser t f = SymbExpr (Term t, parse_term t,\_ _ _ arr l _ -> return [f (arr A.! l)])
+
+-- | Parse a single character.
+--
+-- @
+-- char c = term_parser c id
+-- @
+--
+-- Currently, this is the only character-level combinator exported
+-- by this module. Please use token-level combinators for practical parsing.
+-- Might change in the future.
+char :: Char -> SymbExpr Char Char
+char c = term_parser c id
+{-
+-- | Parse a list of characters.
+string :: [Char] -> SymbExpr Char [Char]
+string [] = mkRule $ satisfy []
+string (c:cs) = mkRule $ (:) <$$> char c <**> string cs
+
+-- | 
+-- Apply a parser within two other parsers.
+within :: IsSymbExpr s => BNF Char a -> s Char b -> BNF Char c -> BNF Char b
+within l p r = mkRule $ l *> (toSymb p) <* r
+
+-- | 
+-- Apply a parser within parentheses.
+-- parens p = within (char '(') p (char ')')
+parens :: BNF Char a -> BNF Char a 
+parens p = within (char '(') p (char ')')
+-}
+
+-- | Parse a single character, using a 'SubsumesToken' type.
+keychar :: (Parseable t, SubsumesToken t) => Char -> SymbExpr t Char
+keychar c = term_parser (upcast (Char c)) (const c)        -- helper for Char tokens
+
+-- | Parse a single character, using a 'SubsumesToken' type.
+keyword :: (Parseable t, SubsumesToken t) => String -> SymbExpr t String
+keyword k = term_parser (upcast (Keyword k)) (const k)        -- helper for Char tokens
+
+-- | Parse a single integer, using a 'SubsumesToken' type.
+-- Returns the lexeme interpreted as an 'Int'.
+int_lit :: (Parseable t, SubsumesToken t) => SymbExpr t Int
+int_lit  = term_parser (upcast (IntLit Nothing)) (unwrap . downcast)
+ where  unwrap (Just (IntLit (Just i)))  = i
+        unwrap _ = error "int_lit: downcast, or token without lexeme"
+
+-- | Parse a single floating point literal, using a 'SubsumesToken' type.
+-- Returns the lexeme interpreted as a 'Double'.
+float_lit :: (Parseable t, SubsumesToken t) => SymbExpr t Double
+float_lit  = term_parser (upcast (FloatLit Nothing)) (unwrap . downcast)
+ where  unwrap (Just (FloatLit (Just i)))  = i
+        unwrap _ = error "float_lit: downcast, or token without lexeme"
+
+-- | Parse a single Boolean, using a 'SubsumesToken' type.
+-- Returns the lexeme interpreter as a Boolean.
+bool_lit :: (Parseable t, SubsumesToken t) => SymbExpr t Bool
+bool_lit  = term_parser (upcast (BoolLit Nothing)) (unwrap . downcast)
+ where  unwrap (Just (BoolLit (Just b)))  = b
+        unwrap _ = error "bool_lit: downcast, or token without lexeme"
+
+-- | Parse a single Character literal, using a 'SubsumesToken' type.
+-- Returns the lexeme interpreted as a Character literal.
+char_lit :: (Parseable t, SubsumesToken t) => SymbExpr t Char
+char_lit  = term_parser (upcast (CharLit Nothing)) (unwrap . downcast)
+ where  unwrap (Just (CharLit (Just s))) = s
+        unwrap _ = error "char_lit: downcast, or token without lexeme"
+
+-- | Parse a single String literal, using a 'SubsumesToken' type.
+-- Returns the lexeme interpreted as a String literal.
+string_lit :: (Parseable t, SubsumesToken t) => SymbExpr t String
+string_lit  = term_parser (upcast (StringLit Nothing)) (unwrap . downcast)
+ where  unwrap (Just (StringLit (Just i))) = i
+        unwrap _ = error "string_lit: downcast, or token without lexeme"
+
+-- | Parse a single identifier, using a 'SubsumesToken' type.
+-- Returns the lexeme as a String.
+id_lit :: (Parseable t, SubsumesToken t) => SymbExpr t String
+id_lit = term_parser (upcast (IDLit Nothing)) (unwrap . downcast)
+ where  unwrap (Just (IDLit (Just i))) = i
+        unwrap _ = error "id_lit: downcast, or token without lexeme"
+
+-- | Parse a single alternative identifier, using a 'SubsumesToken' type.
+-- Returns the lexeme as a String.
+alt_id_lit :: (Parseable t, SubsumesToken t) => SymbExpr t String
+alt_id_lit = term_parser (upcast (AltIDLit Nothing)) (unwrap . downcast)
+ where  unwrap (Just (AltIDLit (Just i))) = i
+        unwrap _ = error "alt_id_lit: downcast, or token without lexeme"
+
+
+-- | Parse a single arbitrary token, using a 'SubsumesToken' type.
+-- Returns the lexeme.
+token :: (Parseable t, SubsumesToken t) => String -> SymbExpr t String
+token name = term_parser (upcast (Token name Nothing)) (unwrap . downcast)
+ where  unwrap (Just (Token name' (Just i))) | name == name' = i
+        unwrap _  = error "tokenT: downcast, or token without lexeme"
+
+epsilon :: (Show t, Ord t) => AltExpr t ()
+epsilon = AltExpr ([], seqStart ,\_ _ _ _ _ l r -> 
+                        if l == r then return [(l,())] else return [] )
+    where x = "__eps"
+
+-- | The empty right-hand side that yields its 
+--  first argument as a semantic result.
+satisfy :: (Show t, Ord t ) => a -> AltExpr t a
+satisfy a = a <$$ epsilon
+
+-- | 
+-- This function memoises a parser, given:
+--
+-- * A 'MemoRef' pointing to a fresh 'MemoTable', created using 'newMemoTable'.
+-- * The 'SymbExpr' to memoise.
+--
+-- Use 'memo' on those parsers that are expected to derive the same 
+-- substring multiple times. If the same combinator expression is used
+-- to parse multiple times the 'MemoRef' needs to be cleared using 'memClear'.
+--
+-- 'memo' relies on 'unsafePerformIO' and is therefore potentially unsafe.
+-- The option 'useMemoisation' enables memoisation.
+-- It is off by default, even if 'memo' is used in a combinator expression.
+memo :: (Ord t, Show t, IsSymbExpr s) => MemoRef [a] -> s t a -> SymbExpr t a
+memo ref p' = let   SymbExpr (sym,rules,sem) = toSymb p'
+                    lhs_sem opts ctx sppf arr l r 
+                        | not (do_memo opts) = sem opts ctx sppf arr l r
+                        | otherwise = do
+                            tab <- readIORef ref
+                            case memLookup (l,r) tab of
+                                Just as -> return as
+                                Nothing -> do   as <- sem opts ctx sppf arr l r
+                                                modifyIORef ref (memInsert (l,r) as)
+                                                return as
+               in SymbExpr (sym, rules, lhs_sem)
+
+-- | 
+-- Helper function for defining new combinators.
+-- Use 'mkNt' to form a new unique non-terminal name based on
+-- the symbol of a given 'SymbExpr' and a 'String' that is unique to
+-- the newly defined combinator.
+mkNt :: (Show t, Ord t, IsSymbExpr s) => s t a -> String -> String 
+mkNt p str = let SymbExpr (myx,_,_) = mkRule p
+                in "_(" ++ show myx ++ ")" ++ str
+
+-- | Specialised fmap for altparsers
+(.$.) :: (Show t, Ord t, IsAltExpr i) => (a -> b) -> i t a -> AltExpr t b
+f .$. i = let AltExpr (s,r,sem) = toAlt i
+            in AltExpr (s,r,\opts slot ctx sppf arr l r -> 
+                                do  as <- sem opts slot ctx sppf arr l r
+                                    return $ map (id *** f) as )
+
+-- | 
+-- Variant of '<$$>' that ignores the semantic result of its second argument. 
+(<$$) :: (Show t, Ord t, IsSymbExpr s) => b -> s t a -> AltExpr t b
+f <$$ p = const f <$$> p
+infixl 4 <$$
+
+-- | 
+infixl 4 **>, <<**>, **>>>
+
+-- | 
+-- Variant of '<**>' that ignores the semantic result of the first argument.
+(**>) :: (Show t, Ord t, IsAltExpr i, IsSymbExpr s) => i t a -> s t b -> AltExpr t b
+l **> r = flip const .$. l <**> r
+
+-- Variant of '<**>' that applies longest match on its left operand. 
+(**>>>) :: (Show t, Ord t, IsAltExpr i, IsSymbExpr s) => i t a -> s t b -> AltExpr t b
+l **>>> r = flip const .$. l <**>>> r
+
+-- Variant of '<**>' that ignores shortest match on its left operand.
+(<<**>) :: (Show t, Ord t, IsAltExpr i, IsSymbExpr s) => i t a -> s t b -> AltExpr t b
+l <<**>r = flip const .$. l <<<**> r
+
+
+infixl 4 <**, <<<**, <**>>
+-- | 
+-- Variant of '<**>' that ignores the semantic result of the second argument.
+(<**) :: (Show t, Ord t, IsAltExpr i, IsSymbExpr s) => i t a -> s t b -> AltExpr t a
+l <** r = const .$. l <**> r 
+
+-- | Variant of '<**' that applies longest match on its left operand.
+(<**>>) :: (Show t, Ord t, IsAltExpr i, IsSymbExpr s) => i t a -> s t b -> AltExpr t a
+l <**>> r = const .$. l <**>>> r 
+
+-- | Variant '<**' that applies shortest match on its left operand
+(<<<**) :: (Show t, Ord t, IsAltExpr i, IsSymbExpr s) => i t a -> s t b -> AltExpr t a
+l <<<** r = const .$. l <<<**> r 
+
+-- | 
+-- Variant of '<::=>' that prioritises productions from left-to-right (or top-to-bottom).
+x <::= altPs = mkNtRule True True x altPs 
+infixl 2 <::=
+
+-- | 
+-- Variant of '<:=>' that prioritises productions from left-to-right (or top-to-bottom).
+x <:= altPs = mkNtRule False True x altPs 
+infixl 2 <:=
+
+-- | Try to apply a parser multiple times (0 or more) with shortest match
+-- applied to each occurrence of the parser.
+many :: (Show t, Ord t, IsSymbExpr s) => s t a -> SymbExpr t [a]
+many = multiple_ (<<<**>)
+
+-- | Try to apply a parser multiple times (1 or more) with shortest match
+-- applied to each occurrence of the parser.
+many1 :: (Show t, Ord t, IsSymbExpr s) => s t a -> SymbExpr t [a]
+many1 = multiple1_ (<<<**>) 
+
+-- | Try to apply a parser multiple times (0 or more) with longest match
+-- applied to each occurrence of the parser.
+some :: (Show t, Ord t, IsSymbExpr s) => s t a -> SymbExpr t [a]
+some = multiple_ (<**>>>)
+
+-- | Try to apply a parser multiple times (1 or more) with longest match
+-- applied to each occurrence of the parser.
+some1 :: (Show t, Ord t, IsSymbExpr s) => s t a -> SymbExpr t [a]
+some1 = multiple1_ (<**>>>) 
+
+-- | Try to apply a parser multiple times (0 or more). The results are returned in a list.
+-- In the case of ambiguity the largest list is returned.
+multiple :: (Show t, Ord t, IsSymbExpr s) => s t a -> SymbExpr t [a]
+multiple = multiple_ (<**>)
+
+-- | Try to apply a parser multiple times (1 or more). The results are returned in a list.
+-- In the case of ambiguity the largest list is returned.
+multiple1 :: (Show t, Ord t, IsSymbExpr s) => s t a -> SymbExpr t [a]
+multiple1 = multiple1_ (<**>)
+
+-- | Internal
+multiple_ disa p = let fresh = mkNt p "*" 
+                    in fresh <::=> ((:) <$$> p) `disa` (multiple_ disa p) <||> satisfy []
+
+-- | Internal
+multiple1_ disa p = let fresh = mkNt p "+"
+                     in fresh <::=> ((:) <$$> p) `disa` (multiple_ disa p)
+
+-- | Same as 'many' but with an additional separator.
+manySepBy :: (Show t, Ord t, IsSymbExpr s, IsSymbExpr s2, IsAltExpr s2) => 
+                s t a -> s2 t b -> SymbExpr t [a]
+manySepBy = sepBy many
+-- | Same as 'many1' but with an additional separator.
+manySepBy1 :: (Show t, Ord t, IsSymbExpr s, IsSymbExpr s2, IsAltExpr s2) => 
+                s t a -> s2 t b -> SymbExpr t [a]
+manySepBy1 = sepBy1 many
+-- | Same as 'some1' but with an additional separator.
+someSepBy :: (Show t, Ord t, IsSymbExpr s, IsSymbExpr s2, IsAltExpr s2) => 
+                s t a -> s2 t b -> SymbExpr t [a]
+someSepBy = sepBy some
+-- | Same as 'some1' but with an additional separator.
+someSepBy1 :: (Show t, Ord t, IsSymbExpr s, IsSymbExpr s2, IsAltExpr s2) => 
+                s t a -> s2 t b -> SymbExpr t [a]
+someSepBy1 = sepBy1 some
+-- | Same as 'multiple' but with an additional separator.
+multipleSepBy :: (Show t, Ord t, IsSymbExpr s, IsSymbExpr s2, IsAltExpr s2) => 
+                    s t a -> s2 t b -> SymbExpr t [a]
+multipleSepBy = sepBy multiple 
+-- | Same as 'multiple1' but with an additional separator.
+multipleSepBy1 :: (Show t, Ord t, IsSymbExpr s, IsSymbExpr s2, IsAltExpr s2) => 
+                    s t a -> s2 t b -> SymbExpr t [a]
+multipleSepBy1 = sepBy1 multiple 
+
+sepBy :: (Show t, Ord t, IsSymbExpr s1, IsSymbExpr s2, IsAltExpr s2) => 
+           (AltExpr t a -> SymbExpr t [a]) -> s1 t a -> s2 t b -> SymbExpr t [a]
+sepBy mult p c = mkRule $ satisfy [] <||> (:) <$$> p <**> mult (c **> p)
+
+sepBy1 :: (Show t, Ord t, IsSymbExpr s1, IsSymbExpr s2, IsAltExpr s2) => 
+           (AltExpr t a -> SymbExpr t [a]) -> s1 t a -> s2 t b -> SymbExpr t [a]
+sepBy1 mult p c = mkRule $ (:) <$$> p <**> mult (c **> p)
+
+-- | Like 'multipleSepBy1' but matching at least two occurrences of the 
+-- first argument. The returned list is therefore always of at least
+-- length 2. At least one separator will be consumed.
+multipleSepBy2 p s = mkRule $
+  (:) <$$> p <** s <**> multipleSepBy1 p s
+
+-- | Like 'multipleSepBy2' but matching the minimum number of 
+-- occurrences of the first argument as possible (at least 2).
+someSepBy2 p s = mkRule $
+  (:) <$$> p <** s <**> someSepBy1 p s
+
+-- | Like 'multipleSepBy2' but matching the maximum number of
+-- occurrences of the first argument as possible (at least 2).
+manySepBy2 p s = mkRule $ 
+  (:) <$$> p <** s <**> manySepBy1 p s
+
+-- | Derive either from the given symbol or the empty string.
+optional :: (Show t, Ord t, IsSymbExpr s) => s t a -> SymbExpr t (Maybe a)
+optional p = fresh 
+  <:=>  Just <$$> p 
+  <||>  satisfy Nothing 
+  where fresh = mkNt p "?"
+
+-- | Version of 'optional' that prefers to derive from the given symbol,
+-- affects only nullable nonterminal symbols
+preferably :: (Show t, Ord t, IsSymbExpr s) => s t a -> SymbExpr t (Maybe a)
+preferably p = fresh 
+  <:=   Just <$$> p 
+  <||>  satisfy Nothing 
+  where fresh = mkNt p "?"
+
+-- | Version of 'optional' that prefers to derive the empty string from 
+-- the given symbol, affects only nullable nonterminal symbols
+reluctantly :: (Show t, Ord t, IsSymbExpr s) => s t a -> SymbExpr t (Maybe a)
+reluctantly p = fresh 
+  <:=   satisfy Nothing  
+  <||>  Just <$$> p
+  where fresh = mkNt p "?"
+
+optionalWithDef :: (Show t, Ord t, IsSymbExpr s) => s t a -> a -> SymbExpr t a 
+optionalWithDef p def = mkNt p "?" <:=> id <$$> p <||> satisfy def
+
+-- | Place a piece of BNF /within/ two other BNF fragments, ignoring their semantics.
+within :: (Show t, Ord t, IsSymbExpr s) => BNF t a -> s t b -> BNF t c -> BNF t b
+within l p r = mkRule $ l **> toSymb p <** r
+
+-- | Place a piece of BNF between the characters '(' and ')'.
+parens p = within (keychar '(') p (keychar ')')
+-- | Place a piece of BNF between the characters '{' and '}'.
+braces p = within (keychar '{') p (keychar '}')
+-- | Place a piece of BNF between the characters '[' and ']'.
+brackets p = within (keychar '[') p (keychar ']')
+-- | Place a piece of BNF between the characters '<' and '>'.
+angles p = within (keychar '<') p (keychar '>')
+-- | Place a piece of BNF between two single quotes.
+quotes p = within (keychar '\'') p (keychar '\'')
+-- | Place a piece of BNF between two double quotes.
+dquotes p = within (keychar '"') p (keychar '"')
+
+foldr_multiple :: (IsSymbExpr s, Parseable t) => s t (a -> a) -> a -> BNF t a 
+foldr_multiple comb def = mkNt comb "-foldr" 
+  <::=> satisfy def 
+  <||> ($)      <$$> comb <<<**> foldr_multiple comb def
+
+foldr_multipleSepBy :: (IsSymbExpr s, Parseable t) => s t (a -> a) -> s t b -> a -> BNF t a 
+foldr_multipleSepBy comb sep def = mkNt comb "-foldr" 
+  <::=> satisfy def 
+  <||>  ($ def) <$$> comb
+  <||> ($)      <$$> comb <** sep <<<**> foldr_multipleSepBy comb sep def
+
+-- | A table mapping operator keywords to a 'Fixity' and 'Assoc'
+-- It provides a convenient way to build an expression grammar (see 'fromOpTable'). 
+type OpTable e  = M.Map Double [(String, Fixity e)] 
+data Fixity e   = Prefix (String -> e -> e) | Infix (e -> String -> e -> e) Assoc
+data Assoc      = LAssoc | RAssoc | NA
+
+opTableFromList :: [(Double, [(String, Fixity e)])] -> OpTable e 
+opTableFromList = M.fromList
+
+fromOpTable :: (SubsumesToken t, Parseable t, IsSymbExpr s) => String -> OpTable e -> s t e -> BNF t e 
+fromOpTable nt ops rec = chooses_prec (nt ++ "-infix-prefix-exprs") $
+  [ mkNterm ix row
+  | (ix, row) <- zip [1..] (M.elems ops)
+  ]
+  where mkNterm ix ops = chooses (ntName ix) $ 
+          [ mkAlt op fix | (op, fix) <- ops ]
+          where mkAlt op fix = case fix of
+                  Prefix f -> f <$$> keyword op <**> rec 
+                  Infix f assoc -> case assoc of 
+                    LAssoc -> f <$$> rec <**> keyword op <**>>> rec
+                    RAssoc -> f <$$> rec <**> keyword op <<<**> rec
+                    _      -> f <$$> rec <**> keyword op <**> rec
+                
+        ntName i = show i ++ nt ++ "-op-row"
+
diff --git a/src/GLL/Combinators/Visit/FUNGLL.hs b/src/GLL/Combinators/Visit/FUNGLL.hs
new file mode 100644
--- /dev/null
+++ b/src/GLL/Combinators/Visit/FUNGLL.hs
@@ -0,0 +1,124 @@
+
+module GLL.Combinators.Visit.FUNGLL where
+
+import GLL.Types.Grammar
+import GLL.Types.BSR
+import GLL.Types.DataSets
+
+import qualified Data.IntMap as IM
+import qualified Data.Map as M
+import qualified Data.Set as S
+import qualified Data.IntSet as IS
+import qualified Data.Array as A
+
+type Command t  = State t (ContF t) -> State t (ContF t)
+data ContF t    = ContF (Descr t -> Command t)
+
+type Parse_Symb t   = (Symbol t, Input t -> Slot t -> Int -> Int -> ContF t -> Command t)
+type Parse_Choice t = Input t -> Nt -> Int -> ContF t -> Command t 
+type Parse_Seq t    = Input t -> Nt -> [Symbol t] -> Int -> ContF t -> Command t
+type Parse_Alt t    = Parse_Seq t
+
+parser_for :: (Parseable t) => Nt -> Parse_Symb t -> Input t -> ParseResult t
+parser_for x (Term t,p) inp = error "assert: terminal given to parser_for"
+parser_for x (Nt s,p) inp = resultFromState inp (
+  p inp (Slot x [Nt s] []) 0 0 cont0 emptyState) (s,0,0)
+  where cont0 = ContF cf
+          where cf (_,_,r) s | r == snd (A.bounds inp) = s { successes = successes s + 1 } 
+                             | otherwise = s
+
+parse_nterm :: (Ord t) => Nt -> [Parse_Seq t] -> Parse_Symb t
+parse_nterm n = nterm n . foldl altOp altStart 
+
+parse_term :: Parseable t => t -> Parse_Symb t
+parse_term = term
+
+parse_apply :: Ord t => Parse_Symb t -> Parse_Seq t
+parse_apply = seqOp seqStart 
+
+parse_seq :: Ord t => Parse_Seq t -> Parse_Symb t -> Parse_Seq t
+parse_seq = seqOp
+
+nterm :: (Ord t) => Nt -> Parse_Choice t -> Parse_Symb t
+nterm n p = (Nt n, parser)
+  where parser inp g l k c s 
+          | null rs   = p inp n k cont_for s'
+          | otherwise = compAll [ applyCF c (g,l,r) | r <- rs ] s'
+          where s' = s { grel = addCont (n,k) (g,l,c) (grel s) } 
+                rs = extents (n,k) (prel s) 
+
+        cont_for = ContF cf 
+         where cf (_,k,r) s = 
+                compAll [ applyCF c (g,l',r) | (g,l',c) <- conts (n,k) (grel s) ] s'
+                where s' = s { prel = addExtent (n,k) r (prel s) }
+
+term :: Parseable t => t -> Parse_Symb t
+term t = (Term t, parser)
+  where parser inp g l k c s
+          | lb <= k, k <= ub, matches (inp A.! k) t = applyCF c (g, l, k+1) s
+          | otherwise                               = s
+         where (lb,ub) = A.bounds inp
+
+seqStart :: Ord t => Parse_Seq t
+seqStart inp x beta l c = continue (Slot x [] beta, l, l, l) c
+
+seqOp :: Ord t => Parse_Seq t -> Parse_Symb t -> Parse_Seq t
+seqOp p (s,q) inp x beta l c0 = p inp x (s:beta) l c1
+  where c1 = ContF c1f
+         where c1f ((Slot _ alpha _),l,k) = q inp (Slot x (alpha++[s]) beta) l k c2
+                where c2 = ContF c2f
+                       where c2f (g,l,r) = continue (g,l,k,r) c0
+
+continue :: (Ord t) => BSR t -> ContF t -> Command t
+continue bsr@(g@(Slot x alpha beta),l,k,r) c s 
+  | hasDescr descr (uset s) = s'
+  | otherwise               = applyCF c descr s''
+  where descr = (g,l,r)
+        s'  | not (null alpha) || null beta = s { bsrs = addBSR bsr (bsrs s) }
+            | otherwise                     = s
+        s'' = s'  { uset = addDescr descr (uset s') }
+
+altStart :: Parse_Choice t
+altStart inp n l c s = s
+
+altOp :: Parse_Choice t -> Parse_Seq t -> Parse_Choice t
+altOp p q inp n l c = p inp n l c . q inp n [] l c
+
+compAll :: [Command t] -> Command t
+compAll = foldr (.) id
+
+applyCF (ContF cf) a = cf a
+
+-- | 
+-- The "ParseResult" datatype contains some information about a parse:
+--
+--  * Whether the parse was successful
+--  * The number of descriptors that have been processed
+--  * The number of BSR elements 
+data ParseResult t = ParseResult{ bsrs_result               :: BSRs t
+                                , res_success               :: Bool
+                                , res_successes             :: Int
+                                , nr_descriptors            :: Int
+                                , nr_bsrs                   :: Int
+                                , error_message             :: String
+                                }
+
+resultFromState :: Parseable t => Input t -> State t c -> (Nt, Int, Int) -> ParseResult t
+resultFromState inp (State uset _ _ pMap cs) (s, l, m) =
+    let usize       = sum  [ S.size s   | (l, r2s) <- IM.assocs uset
+                                        , (r,s) <- IM.assocs r2s ]
+        p_nodes     = sum [ IS.size ks  | (l, r2j) <- IM.assocs pMap
+                                        , (r, j2s) <- IM.assocs r2j
+                                        , (j, s2k) <- IM.assocs j2s
+                                        , (s, ks)  <- M.assocs s2k ]
+    in ParseResult pMap (cs > 0) cs usize p_nodes "no errors to report" 
+
+instance Show (ParseResult t) where
+    show res | res_success res = result_string
+             | otherwise       = result_string ++ "\n" ++ error_message res
+     where result_string = unlines $
+                [   "Success             "  ++ show (res_success res)
+                ,   "#Success            "  ++ show (res_successes res)
+                ,   "Descriptors:        "  ++ show (nr_descriptors res)
+                ,   "BSRs:               "  ++ show (nr_bsrs res)
+                ]
diff --git a/src/GLL/Combinators/Visit/Join.hs b/src/GLL/Combinators/Visit/Join.hs
new file mode 100644
--- /dev/null
+++ b/src/GLL/Combinators/Visit/Join.hs
@@ -0,0 +1,102 @@
+{-# LANGUAGE FlexibleInstances #-}
+
+module GLL.Combinators.Visit.Join where
+
+import GLL.Types.BSR
+import GLL.Types.Grammar
+import GLL.Combinators.Visit.Sem
+import GLL.Combinators.Visit.FUNGLL
+import GLL.Combinators.Options
+
+import Control.Compose (OO(..),unOO)
+import Data.List (intercalate)
+import Data.Text (pack)
+
+-- | A combinator expression representing a symbol.
+-- A 'SymbExpr' either represents a terminal or a nonterminal.
+-- In the latter case it is constructed with (a variant of) '<:=>' and 
+-- adds a rule to the grammar of which the represented symbol is the 
+-- left-hand side.
+data SymbExpr t a = SymbExpr (Symbol t, Parse_Symb t, Sem_Symb t a)
+-- | A combinator expression representing a BNF-grammar. The terminals of
+-- the grammar are of type 't'. When used to parse, the expression yields
+-- semantic results of type 'a'. 
+type BNF t a = SymbExpr t a
+-- | 
+-- A combinator expression representing an alternative: 
+-- the right-hand side of a production.
+data AltExpr t a = AltExpr ([Symbol t], Parse_Alt t, Sem_Alt t a)
+
+-- | A list of alternatives represents the right-hand side of a rule.
+type AltExprs = OO [] AltExpr
+
+mkNtRule :: (Show t, Ord t, HasAlts b) => Bool -> Bool -> String -> b t a -> SymbExpr t a
+mkNtRule use_ctx left_biased x' altPs' =
+    let vas1 = map (\(AltExpr (f,_,_)) -> f) altPs 
+        vas2 = map (\(AltExpr (_,s,_)) -> s) altPs
+        vas3 = map (\(AltExpr (_,_,t)) -> t) altPs
+        alts  = map (Prod x) vas1    
+        altPs = altsOf altPs'
+        x     = pack x'
+    in SymbExpr (Nt x, parse_nterm x vas2, sem_nterm use_ctx left_biased x alts vas3)
+
+join_apply :: (Show t, Ord t, IsSymbExpr s) => (a -> b) -> s t a -> AltExpr t b
+join_apply f p' = 
+    let SymbExpr (vpa1,vpa2,vpa3) = mkRule p' in AltExpr
+          ([vpa1],parse_apply vpa2, sem_apply f vpa3)
+
+join_seq :: (Show t, Ord t, IsAltExpr i, IsSymbExpr s) => 
+              CombinatorOptions -> i t (a -> b) -> s t a -> AltExpr t b
+join_seq local_opts pl' pr' = 
+  let AltExpr (vimp1,vimp2,vimp3) = toAlt pl'
+      SymbExpr (vpa1,vpa2,vpa3)  = mkRule pr' in AltExpr
+  (vimp1++[vpa1], parse_seq vimp2 vpa2, sem_seq local_opts vimp3 vpa3)
+
+-- | 
+-- Class for lifting to 'SymbExpr'.
+class IsSymbExpr a where
+    toSymb :: (Show t, Ord t) => a t b -> SymbExpr t b
+    -- | Synonym of 'toSymb' for creating /derived combinators/. 
+    mkRule :: (Show t, Ord t) => a t b -> BNF t b
+    mkRule = toSymb
+
+instance IsSymbExpr AltExpr where
+    toSymb = toSymb . OO . (:[]) 
+
+instance IsSymbExpr SymbExpr where
+    toSymb = id 
+
+instance IsSymbExpr AltExprs where
+    toSymb a = mkNtRule False False mkName a 
+        where mkName = "_" ++ "(" ++ intercalate "|" (map op (unOO a)) ++ ")"
+                where op (AltExpr (rhs,_,_)) = "(" ++ intercalate "*" (map show rhs) ++ ")"
+              
+                
+-- | 
+-- Class for lifting to 'AltExprs'. 
+class HasAlts a where
+    altsOf :: (Show t, Ord t) => a t b -> [AltExpr t b]
+
+instance HasAlts AltExpr where
+    altsOf = (:[])
+
+instance HasAlts SymbExpr where
+    altsOf = altsOf . toAlt
+
+instance HasAlts AltExprs where
+    altsOf = unOO 
+
+-- | 
+-- Class for lifting to 'AltExpr'. 
+class IsAltExpr a where
+    toAlt :: (Show t, Ord t) => a t b -> AltExpr t b
+
+instance IsAltExpr AltExpr where
+    toAlt = id
+
+instance IsAltExpr SymbExpr where
+    toAlt p = join_apply id p
+
+instance IsAltExpr AltExprs where
+    toAlt = toAlt . mkRule
+
diff --git a/src/GLL/Combinators/Visit/Sem.hs b/src/GLL/Combinators/Visit/Sem.hs
new file mode 100644
--- /dev/null
+++ b/src/GLL/Combinators/Visit/Sem.hs
@@ -0,0 +1,77 @@
+
+module GLL.Combinators.Visit.Sem where
+
+import GLL.Combinators.Options
+import GLL.Types.Grammar
+import GLL.Types.BSR
+
+import Control.Monad (forM)
+import qualified Data.Array as A
+import qualified Data.IntMap as IM
+import qualified Data.Set as S
+
+type Sem_Symb t a = PCOptions -> Ancestors t 
+                        -> BSRs t -> Input t -> Int -> Int -> IO [a]
+type Sem_Alt  t a = PCOptions -> (Prod t,Int) -> Ancestors t 
+                        -> BSRs t -> Input t -> Int -> Int -> IO [(Int,a)]
+
+evaluator_for :: (Ord t) => Nt -> Sem_Symb t a -> PCOptions -> BSRs t -> Input t -> IO [a]
+evaluator_for start sem opts bsrs inp = sem opts emptyAncestors bsrs inp 0 (snd (A.bounds inp))
+
+sem_nterm :: Bool -> Bool -> Nt -> [Prod t] -> [Sem_Alt t a] -> Sem_Symb t a
+sem_nterm use_ctx left_biased x alts ps opts ctx sppf arr l r =
+        let ctx' = ctx `toAncestors` (x,l,r)
+            sems = zip alts ps 
+            seq (alt@(Prod _ rhs), va3) = 
+                va3 opts (alt,length rhs) ctx' sppf arr l r 
+        in if use_ctx && ctx `inAncestors` (Nt x, l, r) 
+                then return []
+                else do ass <- forM sems seq
+                        let choices = case (pivot_select_nt opts, pivot_select opts) of
+                                        (True,Just compare) -> maintainWith compare ass
+                                        _                   -> ass
+                        return (concatChoice left_biased opts (map (map snd) choices))
+ where
+    concatChoice :: Bool -> PCOptions -> [[a]] -> [a]
+    concatChoice left_biased opts ress = 
+        if left_biased || left_biased_choice opts
+        then firstRes ress
+        else concat ress
+     where  firstRes []         = []
+            firstRes ([]:ress)  = firstRes ress
+            firstRes (res:_)    = res
+
+sem_apply :: Ord t => (a -> b) -> Sem_Symb t a -> Sem_Alt t b
+sem_apply f p opts (alt,j) ctx sppf arr l r = 
+        let op f a = (r,f a)
+        in do   as <- p opts ctx sppf arr l r
+                return (maybe [] (const (map (op f) as)) $ sppf `pNodeLookup'` ((alt,1),l,r))
+
+sem_seq :: Ord t => CombinatorOptions -> Sem_Alt t (a -> b) -> Sem_Symb t a -> Sem_Alt t b 
+sem_seq local_opts p q opts (alt@(Prod x rhs),j) ctx sppf arr l r = 
+    let ks      = maybe [] id $ sppf `pNodeLookup'` ((alt,j), l, r)
+        choices = case pivot_select (runOptionsOn opts local_opts) of
+                    Nothing      -> ks
+                    Just compare -> maximumsWith compare ks
+        seq k  = do     as      <- q opts ctx' sppf arr k r
+                        a2bs    <- p opts (alt,j-1) ctx'' sppf arr l k
+                        return [ (k,a2b a) | (_,a2b) <- a2bs, a <- as ]
+          where ctx'  | k > l       = emptyAncestors 
+                      | otherwise   = ctx
+                ctx'' | k < r       = emptyAncestors
+                      | otherwise   = ctx
+    in do   ass <- forM choices seq
+            return (concat ass)
+
+--- contexts
+type Ancestors t = S.Set Nt
+
+emptyAncestors :: Ancestors t
+emptyAncestors = S.empty
+
+inAncestors :: Ancestors t -> (Symbol t, Int, Int) -> Bool
+inAncestors ctx (Term _, _, _) = False
+inAncestors ctx (Nt x, l, r) = S.member x ctx 
+
+toAncestors :: Ancestors t -> (Nt, Int, Int) -> Ancestors t
+toAncestors ctx (x, l, r) = S.insert x ctx  
diff --git a/src/GLL/ParserCombinators.hs b/src/GLL/ParserCombinators.hs
new file mode 100644
--- /dev/null
+++ b/src/GLL/ParserCombinators.hs
@@ -0,0 +1,6 @@
+
+module GLL.ParserCombinators (
+    module GLL.Combinators.Interface 
+    ) where
+
+import GLL.Combinators.Interface
diff --git a/src/GLL/Types/BSR.hs b/src/GLL/Types/BSR.hs
new file mode 100644
--- /dev/null
+++ b/src/GLL/Types/BSR.hs
@@ -0,0 +1,67 @@
+{-# LANGUAGE StandaloneDeriving #-}
+
+module GLL.Types.BSR where
+
+import qualified    Data.Array as A
+import qualified    Data.Map as M
+import qualified    Data.IntMap as IM
+import qualified    Data.Set as S 
+import qualified    Data.IntSet as IS 
+import              Data.List (elemIndices, findIndices)
+
+import GLL.Types.Grammar
+
+type Input t    = A.Array Int t
+-- make sure that tokens are equal independent of their character level value
+type SlotL t    = (Slot t, Int)                   -- slot with left extent
+type PrL t      = (Prod t, Int)                     -- Production rule with left extent
+type NtL        = (Nt, Int)                     -- Nonterminal with left extent
+
+-- | 
+-- Stores packed nodes using nested "Data.IntMap"s, nesting is as follows:
+--
+-- * left extent
+-- * right extent
+-- * dot position (from left to right)
+-- * mapping from productions to set of pivots
+type BSRs t  =   IM.IntMap (IM.IntMap (IM.IntMap (M.Map (Prod t) IS.IntSet)))
+type BSR t = (Slot t, Int, Int, Int)
+
+emptyBSRs :: (Ord t) => BSRs t
+emptyBSRs = IM.empty
+
+pNodeLookup :: (Ord t) => BSRs t -> (Slot t, Int, Int) -> Maybe [Int]
+pNodeLookup bsrs (Slot x alpha beta,l,r)= pNodeLookup' bsrs ((Prod x (alpha++beta),length alpha),l,r)
+
+pNodeLookup' :: (Ord t) => BSRs t -> ((Prod t, Int), Int, Int) -> Maybe [Int]
+pNodeLookup' pMap ((alt,j),l,r) = maybe Nothing inner $ IM.lookup l pMap
+    where   inner   = maybe Nothing inner2 . IM.lookup r
+            inner2  = maybe Nothing inner3 . IM.lookup j
+            inner3  = maybe Nothing (Just . IS.toList) . M.lookup alt
+
+addBSR = pMapInsert
+addBSR, pMapInsert :: (Ord t) => BSR t -> BSRs t -> BSRs t
+pMapInsert f@((Slot x alpha beta), l, k, r) pMap = 
+ add (Prod x (alpha++beta)) (length alpha) l r k
+ where add alt j l r k = IM.alter addInnerL l pMap
+        where addInnerL mm = case mm of 
+                             Nothing -> Just singleRJAK
+                             Just m ->  Just $ IM.alter addInnerR r m
+              addInnerR mm = case mm of
+                             Nothing -> Just singleJAK
+                             Just m  -> Just $ IM.alter addInnerJ j m
+              addInnerJ mm = case mm of
+                             Nothing -> Just singleAK
+                             Just m  -> Just $ M.insertWith IS.union alt singleK m
+              singleRJAK= IM.fromList [(r, singleJAK)]
+              singleJAK = IM.fromList [(j, singleAK)]
+              singleAK  = M.fromList [(alt, singleK)]
+              singleK   = IS.singleton k
+
+showBSRs pMap = unlines [ show ((a,j),l,r) ++ " --> " ++ show kset
+                        | (l,r2j) <- IM.assocs pMap, (r,j2a) <- IM.assocs r2j
+                        , (j,a2k) <- IM.assocs j2a, (a,kset) <- M.assocs a2k ]
+
+mkInput :: (Parseable t) => [t] -> Input t
+mkInput input = A.listArray (0,m) (input++[eos])
+  where m = length input
diff --git a/src/GLL/Types/DataSets.hs b/src/GLL/Types/DataSets.hs
new file mode 100644
--- /dev/null
+++ b/src/GLL/Types/DataSets.hs
@@ -0,0 +1,99 @@
+
+module GLL.Types.DataSets where
+
+import GLL.Types.Grammar
+import GLL.Types.BSR
+
+import qualified Data.IntMap as IM
+import qualified Data.Map as M
+import qualified Data.Set as S
+import Data.List (nub)
+
+type Descr t    = (Slot t, Int, Int)
+type Comm t     = (Nt, Int)
+data Cont t c   = Cont (Slot t, Int) c
+data State t c  = State { uset       :: USet t
+                        , grel       :: GRel t c
+                        , prel       :: PRel t
+                        , bsrs       :: BSRs t
+                        , successes  :: Int
+                        }
+
+instance (Ord t) => Ord (Cont t c) where
+  (Cont c _) `compare` (Cont c' _) = c `compare` c'
+
+instance (Eq t) => Eq (Cont t c) where
+  (Cont c _) == (Cont c' _) = c == c'
+
+emptyUSet       :: USet t
+addDescr        :: (Ord t) => Descr t  -> USet t   -> USet t
+hasDescr        :: (Ord t) => Descr t  -> USet t   -> Bool
+
+emptyG         :: GRel t c
+addCont         :: (Ord t) => Comm t -> (Slot t, Int, c) -> GRel t c -> GRel t c
+conts           :: Comm t -> GRel t c -> [(Slot t, Int, c)]
+
+emptyP         :: PRel t
+addExtent       :: Comm t -> Int -> PRel t -> PRel t
+extents         :: Comm t -> PRel t -> [Int]
+
+emptyState :: (Ord t) => State t c
+emptyState = State emptyUSet emptyG emptyP emptyBSRs 0
+
+type RList t    =   [Descr t]
+type USet t     =   IM.IntMap (IM.IntMap (S.Set (Slot t)))
+type GRel t c   =   IM.IntMap (M.Map Nt (S.Set (Cont t c)))
+type PRel t     =   IM.IntMap (M.Map Nt [Int])
+
+descrs2list :: USet t -> [(Slot t, Int, Int)]
+descrs2list uset =  [ (g,l,k)
+                    | (l, k2m)  <- IM.assocs uset
+                    , (k, g2m)  <- IM.assocs k2m
+                    , g         <- S.toList g2m ]
+
+printDescrs :: (Show t) => USet t -> IO ()
+printDescrs = putStr . unlines . map show . descrs2list
+
+emptyRList = []
+popRList (x:xs)  = (x,xs) 
+popRList _       = error "popRList"
+unionRList       = flip (++)
+singletonRList   = (:[])
+fromListRList    :: Ord t => [Descr t]  -> USet t   -> RList t
+fromListRList ds uset = foldr op emptyRList (nub ds)
+  where op d rset   | hasDescr d uset   = rset
+                    | otherwise         = unionRList (singletonRList d) rset
+
+
+emptyUSet = IM.empty
+
+addDescr alt@(slot,i,l) = IM.alter inner i 
+  where inner mm = case mm of 
+                      Nothing -> Just $ IM.singleton l single 
+                      Just m  -> Just $ IM.insertWith (S.union) l single m
+        single = S.singleton slot
+
+hasDescr alt@(slot,i,l) = not . maybe True inner . IM.lookup i
+  where inner m = maybe True (not . (slot `S.member`)) $ IM.lookup l m
+
+emptyG = IM.empty
+singleCG k v = addCont k v emptyG
+addCont (n,i) (gs,l,c) = IM.alter inner i
+ where inner mm = case mm of 
+                    Nothing -> Just $ M.singleton n single 
+                    Just m  -> Just $ M.insertWith S.union n single m
+       single = S.singleton (Cont (gs,l) c)
+conts (n,l) = maybe [] inner . IM.lookup l
+         where inner m = maybe [] (map unCont . S.toList) $ M.lookup n m
+               unCont (Cont (gs,l') cf) = (gs,l',cf)
+
+emptyP = IM.empty
+addExtent (gs,l) i = IM.alter inner l
+ where inner mm = case mm of 
+                    Nothing -> Just $ M.singleton gs [i]
+                    Just m  -> Just $ M.insertWith (++) gs [i] m
+
+extents (gs,l) = maybe [] inner . IM.lookup l 
+         where inner = maybe [] id .  M.lookup gs
+
+
