1
- module Happy.Tabular (
2
- mkFirst , genLR0Items , genLookaheads , genLR1States , genActionTable , genGotoTable , countConflicts ,
3
- Lr0Item (.. ), Lr1Item (.. ), Lr0State , Lr1State , LookaheadInfo ,
4
- TabularArgs (.. ), TabularResult , runTabular
5
- ) where
1
+ module Happy.Tabular (TabularArgs (.. ), Lr1State , TabularResult , runTabular ) where
6
2
7
3
import Happy.Grammar.Grammar
8
- import Happy.Tabular.NameSet (NameSet )
9
4
import Happy.Tabular.Tables
10
5
import Happy.Tabular.First
11
- import qualified Happy.Tabular.LALR as LALR
12
- import Happy.Tabular.LALR (Lr0Item , Lr1Item , precalcClosure0 , propLookaheads , calcLookaheads , mergeLookaheadInfo )
6
+ import Happy.Tabular.LALR
13
7
import Happy.Tabular.FindRedundancies
14
8
import Happy.Tabular.Info
15
9
import Data.Set (Set )
16
10
import Data.Array (Array )
17
11
import System.IO
18
- import System.Exit
12
+ import System.Exit hiding ( die )
19
13
import Control.Monad
20
14
21
- -------- Pure tabular functions, may be called without creating TabularArgs --------
22
-
23
- type Lr0State = (Set Lr0Item , [(Name , Int )])
24
- type Lr1State = ([Lr1Item ], [(Name , Int )])
25
- type LookaheadInfo = Array Int [(Lr0Item , NameSet )]
26
-
27
- genLR0Items :: Grammar -> [Lr0State ]
28
- genLR0Items g = LALR. genLR0items g (precalcClosure0 g)
29
-
30
- genLookaheads :: Grammar -> [Lr0State ] -> ([Name ] -> NameSet ) -> LookaheadInfo
31
- genLookaheads g sets first =
32
- let (spont, prop) = propLookaheads g sets first in
33
- calcLookaheads (length sets) spont prop
34
-
35
- genLR1States :: LookaheadInfo -> [Lr0State ] -> [Lr1State ]
36
- genLR1States = mergeLookaheadInfo
37
-
38
- genActionTable :: Grammar -> ([Name ] -> NameSet ) -> [Lr1State ] -> ActionTable
39
- genActionTable = LALR. genActionTable
40
-
41
- genGotoTable :: Grammar -> [Lr0State ] -> GotoTable
42
- genGotoTable = LALR. genGotoTable
43
-
44
- countConflicts :: ActionTable -> (Array Int (Int , Int ), (Int , Int ))
45
- countConflicts = LALR. countConflicts
46
-
47
15
-------- Main entry point (runTabular) --------
48
16
49
17
data TabularArgs = TabularArgs {
50
18
inFile :: String , -- printed to the info file, not used otherwise
51
- infoFile :: Maybe String ,
19
+ infoFile :: Maybe String
20
+
21
+ # ifdef DEBUG
52
22
23
+ ,
53
24
dumpLR0 :: Bool ,
54
25
dumpLA :: Bool ,
55
26
dumpAction :: Bool ,
56
27
dumpGoto :: Bool
28
+
29
+ # endif
30
+
57
31
}
58
32
33
+ type Lr1State = ([Lr1Item ], [(Name , Int )])
59
34
type TabularResult = (ActionTable , GotoTable , [Lr1State ], [Int ])
60
35
61
- runTabular :: TabularArgs -> Grammar -> IO TabularResult
62
- runTabular args g =
63
- let first = mkFirst g
64
- sets = genLR0Items g
65
- la = genLookaheads g sets first
66
- items2 = genLR1States la sets
67
- goto = genGotoTable g sets
68
- action = genActionTable g first items2
69
- (conflictArray, (sr,rr)) = (countConflicts action)
36
+ runTabular :: TabularArgs -> Bool -> Grammar -> IO TabularResult
37
+ runTabular args glr g =
38
+ let first = {-# SCC "First" #-} (mkFirst g)
39
+ closures = {-# SCC "Closures" #-} (precalcClosure0 g)
40
+ sets = {-# SCC "LR0_Sets" #-} (genLR0items g closures)
41
+ _lainfo@ (spont,prop) = {-# SCC "Prop" #-} (propLookaheads g sets first)
42
+ la = {-# SCC "Calc" #-} (calcLookaheads (length sets) spont prop)
43
+ items2 = {-# SCC "Merge" #-} (mergeLookaheadInfo la sets)
44
+ goto = {-# SCC "Goto" #-} (genGotoTable g sets)
45
+ action = {-# SCC "Action" #-} (genActionTable g first items2)
46
+ (conflictArray,(sr,rr)) = {-# SCC "Conflict" #-} (countConflicts action)
70
47
in do
48
+
49
+ #ifdef DEBUG
50
+
71
51
optPrint (dumpLR0 args) (print sets)
72
52
optPrint (dumpLA args) (print la)
73
53
optPrint (dumpAction args) (print action)
74
54
optPrint (dumpGoto args) (print goto)
75
- (unused_rules, unused_terminals) <- reportUnusedRules g action
55
+
56
+ #endif
57
+
58
+ (unused_rules, unused_terminals) <- reportUnusedRules glr g action
76
59
writeInfoFile sets g action goto conflictArray (inFile args) (infoFile args) unused_rules unused_terminals
77
60
reportConflicts g sr rr
78
61
return (action, goto, items2, unused_rules)
62
+
63
+ #ifdef DEBUG
64
+
79
65
where
80
66
optPrint b io = when b (putStr " \n ---------------------\n " >> io)
81
67
68
+ #endif
69
+
82
70
83
71
-------- Helpers --------
84
72
85
- reportUnusedRules :: Grammar -> ActionTable -> IO ([Int ], [String ])
86
- reportUnusedRules g action =
87
- let result@ (unused_rules, unused_terminals) = find_redundancies first_reduction g action in do
88
- when (not (null unused_rules)) $ hPutStrLn stderr (" unused rules: " ++ show (length unused_rules))
89
- when (not (null unused_terminals)) $ hPutStrLn stderr (" unused terminals: " ++ show (length unused_terminals))
90
- return result
73
+ reportUnusedRules :: Bool -> Grammar -> ActionTable -> IO ([Int ], [String ])
74
+ reportUnusedRules glr g action =
75
+ let reduction_filter = if glr then any_reduction else first_reduction
76
+ (unused_rules, unused_terminals) = find_redundancies reduction_filter g action in do
77
+ when (not (null unused_rules))
78
+ (hPutStrLn stderr (" unused rules: " ++ show (length unused_rules)))
79
+ when (not (null unused_terminals))
80
+ (hPutStrLn stderr (" unused terminals: " ++ show (length unused_terminals)))
81
+ return (unused_rules, unused_terminals)
91
82
92
83
reportConflicts :: Grammar -> Int -> Int -> IO ()
93
84
reportConflicts g sr rr = case expect g of
@@ -106,14 +97,27 @@ reportConflicts g sr rr = case expect g of
106
97
if rr /= 0
107
98
then hPutStrLn stderr (" reduce/reduce conflicts: " ++ show rr)
108
99
else return ()
109
- #if !MIN_VERSION_base(4,8,0)
110
- where die s = hPutStr stderr s >> exitWith ( ExitFailure 1 )
111
- #endif
100
+
101
+ die :: String -> IO a
102
+ die s = hPutStr stderr s >> exitWith ( ExitFailure 1 )
112
103
113
104
type ItemSetWithGotos = (Set Lr0Item , [(Name ,Int )])
114
105
writeInfoFile :: [ItemSetWithGotos ] -> Grammar -> ActionTable -> GotoTable -> Array Int (Int ,Int ) -> String -> Maybe String -> [Int ] -> [String ] -> IO ()
115
106
writeInfoFile sets g action goto conflictArray file info_file unused_rules unused_terminals =
116
107
let info = genInfoFile (map fst sets) g action goto (token_specs g) conflictArray file unused_rules unused_terminals in
117
108
case info_file of
118
109
Just s -> writeFile s info >> hPutStrLn stderr (" Grammar info written to: " ++ s)
119
- Nothing -> return ()
110
+ Nothing -> return ()
111
+
112
+ ---
113
+ --- selects what counts as a reduction when calculating used/unused
114
+
115
+ any_reduction :: LRAction -> [Int ]
116
+ any_reduction (LR'Reduce r _) = [r]
117
+ any_reduction (LR'Multiple as a) = concatMap any_reduction (a : as)
118
+ any_reduction _ = []
119
+
120
+ first_reduction :: LRAction -> [Int ]
121
+ first_reduction (LR'Reduce r _) = [r]
122
+ first_reduction (LR'Multiple _ a) = first_reduction a -- eg R/R conflict
123
+ first_reduction _ = []
0 commit comments