Skip to content

Commit b11cb4a

Browse files
committed
Create the 'Tables' data type
This data type encapsulates the result of processing the Grammar. In addition to ActionTable and GotoTable, it also includes intermediate results such as Lr0Items, which are needed for debug printing and info table generation. The 'find_redundancies' function has been moved from Main.lhs to Tabular.lhs almost verbatim (use git show --color-moved=blocks to confirm).
1 parent 08c416e commit b11cb4a

File tree

4 files changed

+95
-63
lines changed

4 files changed

+95
-63
lines changed

happy.cabal

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ executable happy
164164
-- mtl-2.2.1 added Control.Monad.Except
165165

166166
default-language: Haskell98
167-
default-extensions: CPP, MagicHash, FlexibleContexts
167+
default-extensions: CPP, MagicHash, FlexibleContexts, NamedFieldPuns
168168
ghc-options: -Wall
169169
other-modules:
170170
Paths_happy
@@ -181,6 +181,7 @@ executable happy
181181
ProduceCode
182182
ProduceGLRCode
183183
NameSet
184+
Tabular
184185
Target
185186
AttrGrammar
186187
ParamRules

src/LALR.lhs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ Generation of LALR parsing tables.
88
> module LALR
99
> (genActionTable, genGotoTable, genLR0items, precalcClosure0,
1010
> propLookaheads, calcLookaheads, mergeLookaheadInfo, countConflicts,
11-
> Lr0Item(..), Lr1Item)
11+
> Lr0Item(..), Lr1Item, ItemSetWithGotos)
1212
> where
1313

1414
> import GenUtils

src/Main.lhs

Lines changed: 11 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,7 @@ Path settings auto-generated by Cabal:
1717
> import PrettyGrammar
1818
> import Parser
1919

20-
> import First
21-
> import LALR
20+
> import Tabular
2221
> import ProduceCode (produceParser)
2322
> import ProduceGLRCode
2423
> import Info (genInfoFile)
@@ -29,8 +28,7 @@ Path settings auto-generated by Cabal:
2928
> import System.Exit (exitWith, ExitCode(..))
3029
> import Data.Char
3130
> import System.IO
32-
> import Data.Array( assocs, elems, (!) )
33-
> import Data.List( nub, isSuffixOf )
31+
> import Data.List( isSuffixOf )
3432
> import Data.Version ( showVersion )
3533

3634
> main :: IO ()
@@ -84,30 +82,25 @@ Mangle the syntax into something useful.
8482

8583
> optPrint cli DumpMangle $ putStr $ show g
8684

87-
> let first = {-# SCC "First" #-} (mkFirst g)
88-
> closures = {-# SCC "Closures" #-} (precalcClosure0 g)
89-
> sets = {-# SCC "LR0_Sets" #-} (genLR0items g closures)
90-
> _lainfo@(spont,prop) = {-# SCC "Prop" #-} (propLookaheads g sets first)
91-
> la = {-# SCC "Calc" #-} (calcLookaheads (length sets) spont prop)
92-
> items2 = {-# SCC "Merge" #-} (mergeLookaheadInfo la sets)
93-
> goto = {-# SCC "Goto" #-} (genGotoTable g sets)
94-
> action = {-# SCC "Action" #-} (genActionTable g first items2)
95-
> (conflictArray,(sr,rr)) = {-# SCC "Conflict" #-} (countConflicts action)
85+
> let tables = genTables (OptGLR `elem` cli) g
86+
> sets = lr0items tables
87+
> lainfo = (la_prop tables, la_spont tables)
88+
> la = lookaheads tables
89+
> goto = gotoTable tables
90+
> action = actionTable tables
91+
> (conflictArray,(sr,rr)) = conflicts tables
9692

9793
Debug output
9894

9995
> optPrint cli DumpLR0 $ putStr $ show sets
10096
> optPrint cli DumpAction $ putStr $ show action
10197
> optPrint cli DumpGoto $ putStr $ show goto
102-
> optPrint cli DumpLA $ putStr $ show _lainfo
98+
> optPrint cli DumpLA $ putStr $ show lainfo
10399
> optPrint cli DumpLA $ putStr $ show la
104100

105101
Report any unused rules and terminals
106102

107-
> let reduction_filter | OptGLR `elem` cli = any_reduction
108-
> | otherwise = first_reduction
109-
> (unused_rules, unused_terminals)
110-
> = find_redundancies reduction_filter g action
103+
> let (unused_rules, unused_terminals) = redundancies tables
111104
> when (not (null unused_rules))
112105
> (hPutStrLn stderr ("unused rules: " ++ show (length unused_rules)))
113106
> when (not (null unused_terminals))
@@ -298,49 +291,6 @@ Successfully Finished.
298291
> constArgs :: [String]
299292
> constArgs = []
300293

301-
-----------------------------------------------------------------------------
302-
Find unused rules and tokens
303-
304-
> find_redundancies
305-
> :: (LRAction -> [Int]) -> Grammar -> ActionTable -> ([Int], [String])
306-
> find_redundancies extract_reductions g action_table =
307-
> (unused_rules, map (env !) unused_terminals)
308-
> where
309-
> Grammar { terminals = terms,
310-
> token_names = env,
311-
> eof_term = eof,
312-
> starts = starts',
313-
> productions = productions'
314-
> } = g
315-
316-
> actions = concat (map assocs (elems action_table))
317-
> start_rules = [ 0 .. (length starts' - 1) ]
318-
> used_rules = start_rules ++
319-
> nub [ r | (_,a) <- actions, r <- extract_reductions a ]
320-
> used_tokens = errorTok : eof :
321-
> nub [ t | (t,a) <- actions, is_shift a ]
322-
> n_prods = length productions'
323-
> unused_terminals = filter (`notElem` used_tokens) terms
324-
> unused_rules = filter (`notElem` used_rules ) [0..n_prods-1]
325-
326-
> is_shift :: LRAction -> Bool
327-
> is_shift (LR'Shift _ _) = True
328-
> is_shift (LR'Multiple _ LR'Shift{}) = True
329-
> is_shift _ = False
330-
331-
---
332-
selects what counts as a reduction when calculating used/unused
333-
334-
> any_reduction :: LRAction -> [Int]
335-
> any_reduction (LR'Reduce r _) = [r]
336-
> any_reduction (LR'Multiple as a) = concatMap any_reduction (a : as)
337-
> any_reduction _ = []
338-
339-
> first_reduction :: LRAction -> [Int]
340-
> first_reduction (LR'Reduce r _) = [r]
341-
> first_reduction (LR'Multiple _ a) = first_reduction a -- eg R/R conflict
342-
> first_reduction _ = []
343-
344294
------------------------------------------------------------------------------
345295

346296
> possDelit :: String -> String -> IO (String,String)

src/Tabular.lhs

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
> module Tabular ( Tables(..), genTables ) where
2+
3+
> import NameSet (NameSet)
4+
> import First
5+
> import Grammar
6+
> import LALR
7+
8+
> import Data.Array( Array, assocs, elems, (!) )
9+
> import Data.List ( nub )
10+
11+
> data Tables =
12+
> Tables {
13+
> lr0items :: [ItemSetWithGotos],
14+
> la_spont :: [(Int, Lr0Item, NameSet)],
15+
> la_prop :: Array Int [(Lr0Item, Int, Lr0Item)],
16+
> lookaheads :: Array Int [(Lr0Item, NameSet)],
17+
> lr1items :: [ ([Lr1Item], [(Name,Int)]) ],
18+
> gotoTable :: GotoTable,
19+
> actionTable :: ActionTable,
20+
> conflicts :: (Array Int (Int,Int), (Int,Int)),
21+
> redundancies :: ([Int], [String])
22+
> }
23+
24+
> genTables :: Bool -> Grammar -> Tables
25+
> genTables glr g =
26+
> let first = {-# SCC "First" #-} (mkFirst g)
27+
> closures = {-# SCC "Closures" #-} (precalcClosure0 g)
28+
> lr0items = {-# SCC "LR0_Sets" #-} (genLR0items g closures)
29+
> (la_spont, la_prop)
30+
> = {-# SCC "Prop" #-} (propLookaheads g lr0items first)
31+
> lookaheads = {-# SCC "Calc" #-} (calcLookaheads (length lr0items) la_spont la_prop)
32+
> lr1items = {-# SCC "Merge" #-} (mergeLookaheadInfo lookaheads lr0items)
33+
> gotoTable = {-# SCC "Goto" #-} (genGotoTable g lr0items)
34+
> actionTable = {-# SCC "Action" #-} (genActionTable g first lr1items)
35+
> conflicts = {-# SCC "Conflict" #-} (countConflicts actionTable)
36+
> redundancies = find_redundancies glr g actionTable
37+
> in Tables { lr0items, la_spont, la_prop, lookaheads, lr1items,
38+
> gotoTable, actionTable, conflicts, redundancies }
39+
40+
-----------------------------------------------------------------------------
41+
Find unused rules and tokens
42+
43+
> find_redundancies
44+
> :: Bool -> Grammar -> ActionTable -> ([Int], [String])
45+
> find_redundancies glr g action_table =
46+
> (unused_rules, map (env !) unused_terminals)
47+
> where
48+
> Grammar { terminals = terms,
49+
> token_names = env,
50+
> eof_term = eof,
51+
> starts = starts',
52+
> productions = productions'
53+
> } = g
54+
> actions = concat (map assocs (elems action_table))
55+
> start_rules = [ 0 .. (length starts' - 1) ]
56+
> used_rules = start_rules ++
57+
> nub [ r | (_,a) <- actions, r <- extract_reductions a ]
58+
> used_tokens = errorTok : eof :
59+
> nub [ t | (t,a) <- actions, is_shift a ]
60+
> n_prods = length productions'
61+
> unused_terminals = filter (`notElem` used_tokens) terms
62+
> unused_rules = filter (`notElem` used_rules ) [0..n_prods-1]
63+
> extract_reductions = if glr then any_reduction else first_reduction
64+
65+
> is_shift :: LRAction -> Bool
66+
> is_shift (LR'Shift _ _) = True
67+
> is_shift (LR'Multiple _ LR'Shift{}) = True
68+
> is_shift _ = False
69+
70+
---
71+
selects what counts as a reduction when calculating used/unused
72+
73+
> any_reduction :: LRAction -> [Int]
74+
> any_reduction (LR'Reduce r _) = [r]
75+
> any_reduction (LR'Multiple as a) = concatMap any_reduction (a : as)
76+
> any_reduction _ = []
77+
78+
> first_reduction :: LRAction -> [Int]
79+
> first_reduction (LR'Reduce r _) = [r]
80+
> first_reduction (LR'Multiple _ a) = first_reduction a -- eg R/R conflict
81+
> first_reduction _ = []

0 commit comments

Comments
 (0)