Skip to content

Commit cfa99bd

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 cfa99bd

File tree

4 files changed

+110
-63
lines changed

4 files changed

+110
-63
lines changed

happy.cabal

+2-1
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

+1-1
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

+14-61
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,28 @@ 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 select_reductions | OptGLR `elem` cli = select_all_reductions
86+
> | otherwise = select_first_reduction
87+
88+
> let tables = genTables select_reductions g
89+
> sets = lr0items tables
90+
> lainfo = (la_prop tables, la_spont tables)
91+
> la = lookaheads tables
92+
> goto = gotoTable tables
93+
> action = actionTable tables
94+
> (conflictArray,(sr,rr)) = conflicts tables
9695

9796
Debug output
9897

9998
> optPrint cli DumpLR0 $ putStr $ show sets
10099
> optPrint cli DumpAction $ putStr $ show action
101100
> optPrint cli DumpGoto $ putStr $ show goto
102-
> optPrint cli DumpLA $ putStr $ show _lainfo
101+
> optPrint cli DumpLA $ putStr $ show lainfo
103102
> optPrint cli DumpLA $ putStr $ show la
104103

105104
Report any unused rules and terminals
106105

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
106+
> let (unused_rules, unused_terminals) = redundancies tables
111107
> when (not (null unused_rules))
112108
> (hPutStrLn stderr ("unused rules: " ++ show (length unused_rules)))
113109
> when (not (null unused_terminals))
@@ -298,49 +294,6 @@ Successfully Finished.
298294
> constArgs :: [String]
299295
> constArgs = []
300296

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-
344297
------------------------------------------------------------------------------
345298

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

src/Tabular.lhs

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

0 commit comments

Comments
 (0)