I convert context-free grammar to normal Greibach form (GNF). The main transformation (from Hopcroft and Ullman) is a sequence of iterations over indexed grammar variables. This is essentially "stateless." I implemented it as a sequence of folds over the corresponding indices (the implementation is pretty simple):
gnf :: Ord a => Set (Rule a) -> Set (Rule a) gnf rl = foldl step1 rl [1..maxIndex rl] where step1 rl' k = foldl step2 rl' [1..k - 1] where step2 rl'' j = noLR k (subst rl'' kj)
maxIndex rl returns the maximum index of the variable in the rule set; subst rl kj performs substitution on k-indexed rules with rules whose right-hand side begins with the variable j-index. After gnf runs, I need to complete the final grammar pass in reverse order.
The noLR problem that converts a grammar with left recursive k-indexed rules. This is a "stateful" function because a unique variable must be generated for each rule (or k-indexed rule) to which noLR applies. So I wrote a stateful function
noLR :: Ord a => Int -> Set (Rule a) -> State [Sym a] (Set (Rule a)) noLR rl = do (n:ns) <- get; put ns; let rl' = ... remove left recursion rl n ... in return rl'
I can combine noLR sequentially to update n, which noLR takes as a parameter. However, I'm not sure how to perform noLR inside step2 in the above function. I can't seem to use let ... in the schema, because stateful computation is built into several recursive functions.
What I want to do is n be some global variable, similar to explicit streaming n, which I can call and update inside step2, so I originally wrote the function as a fold with eta extension (for n). Does anyone know how I can structure gnf within a state monad to achieve this effect? Except for the last calculation in the summary, nothing else is “in terms of state”, and it’s more convenient for me to use the state monad with “trivial” examples. I am lost.
haskell monads state context-free-grammar
danportin
source share