1 module gamma.parsgen.lalr1.SimpleLR1ConflictResolver;
2 
3 import gamma.grammar.Alternative;
4 import gamma.grammar.Grammar;
5 import gamma.grammar.Nonterminal;
6 import gamma.grammar.Terminal;
7 import gamma.parsgen.lalr1.LR1ConflictResolver;
8 
9 /**
10  * A standard LR(1) conflict resolver.
11  *
12  * @author SöKa
13  */
14 public class SimpleLR1ConflictResolver : LR1ConflictResolver
15 {
16     int srConflicts = 0;
17 
18     int rrConflicts = 0;
19 
20     int haltConflicts = 0;
21 
22     private Grammar grammar;
23 
24     this(Grammar grammar)
25     {
26         this.grammar = grammar;
27     }
28 
29     public Object resolveShiftReduceConflict(Terminal terminal, Alternative alternative, size_t state)
30     {
31         import std.format : format;
32 
33         ++srConflicts;
34         alternative.position
35             .markError(format!"shift/reduce conflict at state %s for look-ahead %s"(state, terminal));
36         return terminal;
37     }
38 
39     public Object resolveReduceReduceConflict(Alternative alternative1, Alternative alternative2,
40         Terminal terminal, size_t state)
41     {
42         import std.format : format;
43 
44         ++rrConflicts;
45         alternative1.position
46             .markError(format!"reduce/reduce conflict with '%s' for look-ahead %s"(alternative2,
47                 (terminal !is null) ? terminal.toString : "(null)"));
48 
49         const n1 = (cast(Nonterminal) alternative1.lhs.symbol).index;
50         const n2 = (cast(Nonterminal) alternative2.lhs.symbol).index;
51 
52         if (n1 < n2)
53             return alternative1;
54         else if (n1 > n2)
55             return alternative2;
56         else
57             foreach (alternative; this.grammar.ruleOf(this.grammar.nonterminal(n1)).alternatives)
58             {
59                 if (alternative == alternative1)
60                     return alternative1;
61                 else if (alternative == alternative2)
62                     return alternative2;
63             }
64         return null;
65     }
66 
67     public void noteHaltConflictOn(Alternative alternative, size_t state)
68     {
69         ++haltConflicts;
70         alternative.position
71             .markError("reduce/halt conflict");
72     }
73 
74 
75     public int getHaltConflicts() const
76     {
77         return this.haltConflicts;
78     }
79 
80 
81     public int getRrConflicts() const
82     {
83         return this.rrConflicts;
84     }
85 
86 
87     public int getSrConflicts() const
88     {
89         return this.srConflicts;
90     }
91 }