Martin Vejnár avatar Martin Vejnár committed fadb8ba

On table conflict, a counterexample is now printed.

Comments (0)

Files changed (3)

     def __repr__(self):
         return 'LexLiteral(%r)' % self.literal
 
+    def __str__(self):
+        return repr(self.literal)
+
 class _LimeLexerClassify:
     def __init__(self):
         self.quote = None
         from lime_grammar import parse_lime_grammar, make_lime_parser
         g = parse_lime_grammar(input)
 
-        from lrparser import InvalidGrammarError
+        from lrparser import InvalidGrammarError, ActionConflictError
         p = make_lime_parser(g, keep_states=options.print_states)
 
         if options.print_states:
 
         from lime_cpp import lime_cpp
         open(options.output, 'w').write(lime_cpp(p))
+    except ActionConflictError, e:
+        print e
+        print 'Counter-example:', ', '.join((str(sym) for sym in e.counterexample()))
+        return 1
     except Exception, e:
         _error(e)
         import traceback
 
 class ActionConflictError(InvalidGrammarError):
     """Raised during a construction of a parser, if the grammar is not LR(k)."""
-    def __init__(self, message, relevant_state, states):
+    def __init__(self, message, relevant_state, states, g):
         InvalidGrammarError.__init__(self, message)
         self.states = states
         self.relevant_state = relevant_state
+        self.g = g
     
     def pretty_states(self):
         """Returns a string with pretty-printed itemsets."""
         
         return '\n'.join(res)
 
+    def counterexample(self):
+        trace = []
+        st = self.relevant_state
+        while st.parent_id:
+            trace.append(st.parent_symbol)
+            st = self.states[st.parent_id]
+        return reversed([self.g.token_comments.get(sym, sym) for sym in trace])
+
 class ParsingError(Exception):
     """Raised by a parser if the input word is not a sentence of the grammar."""
     def __init__(self, message, position):
                     state.goto[symbol] = len(states)
                     state_map[newstate] = len(states)
                     newstate.parent_id = i
+                    newstate.parent_symbol = symbol
                     states.append(newstate)
             
             i += 1
         def add_action(state, lookahead, action, item):
             if lookahead in state.action and state.action[lookahead] != action:
                 raise ActionConflictError('LR(%d) table conflict: actions %s, %s trying to add %s'
-                    % (k, state.action[lookahead], action, item), state, states)
+                    % (k, state.action[lookahead], action, item), state, states, grammar)
             state.action[lookahead] = action
         
         for state_id, state in enumerate(states):
     def __init__(self, itemlist, grammar, first):
         self._close(itemlist, grammar, first)
         self.parent_id = None
+        self.parent_symbol = None
 
         self.goto = {}
         self.action = {}
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.