omlish 0.0.0.dev56__py3-none-any.whl → 0.0.0.dev58__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- omlish/__about__.py +2 -2
- omlish/antlr/__init__.py +0 -0
- omlish/antlr/_runtime/BufferedTokenStream.py +305 -0
- omlish/antlr/_runtime/CommonTokenFactory.py +64 -0
- omlish/antlr/_runtime/CommonTokenStream.py +90 -0
- omlish/antlr/_runtime/FileStream.py +30 -0
- omlish/antlr/_runtime/InputStream.py +90 -0
- omlish/antlr/_runtime/IntervalSet.py +183 -0
- omlish/antlr/_runtime/LL1Analyzer.py +176 -0
- omlish/antlr/_runtime/Lexer.py +332 -0
- omlish/antlr/_runtime/ListTokenSource.py +147 -0
- omlish/antlr/_runtime/Parser.py +583 -0
- omlish/antlr/_runtime/ParserInterpreter.py +173 -0
- omlish/antlr/_runtime/ParserRuleContext.py +189 -0
- omlish/antlr/_runtime/PredictionContext.py +632 -0
- omlish/antlr/_runtime/Recognizer.py +150 -0
- omlish/antlr/_runtime/RuleContext.py +230 -0
- omlish/antlr/_runtime/StdinStream.py +14 -0
- omlish/antlr/_runtime/Token.py +158 -0
- omlish/antlr/_runtime/TokenStreamRewriter.py +258 -0
- omlish/antlr/_runtime/Utils.py +36 -0
- omlish/antlr/_runtime/__init__.py +24 -0
- omlish/antlr/_runtime/_pygrun.py +174 -0
- omlish/antlr/_runtime/atn/ATN.py +135 -0
- omlish/antlr/_runtime/atn/ATNConfig.py +162 -0
- omlish/antlr/_runtime/atn/ATNConfigSet.py +215 -0
- omlish/antlr/_runtime/atn/ATNDeserializationOptions.py +27 -0
- omlish/antlr/_runtime/atn/ATNDeserializer.py +449 -0
- omlish/antlr/_runtime/atn/ATNSimulator.py +50 -0
- omlish/antlr/_runtime/atn/ATNState.py +267 -0
- omlish/antlr/_runtime/atn/ATNType.py +20 -0
- omlish/antlr/_runtime/atn/LexerATNSimulator.py +573 -0
- omlish/antlr/_runtime/atn/LexerAction.py +301 -0
- omlish/antlr/_runtime/atn/LexerActionExecutor.py +146 -0
- omlish/antlr/_runtime/atn/ParserATNSimulator.py +1664 -0
- omlish/antlr/_runtime/atn/PredictionMode.py +502 -0
- omlish/antlr/_runtime/atn/SemanticContext.py +333 -0
- omlish/antlr/_runtime/atn/Transition.py +271 -0
- omlish/antlr/_runtime/atn/__init__.py +4 -0
- omlish/antlr/_runtime/dfa/DFA.py +136 -0
- omlish/antlr/_runtime/dfa/DFASerializer.py +76 -0
- omlish/antlr/_runtime/dfa/DFAState.py +129 -0
- omlish/antlr/_runtime/dfa/__init__.py +4 -0
- omlish/antlr/_runtime/error/DiagnosticErrorListener.py +110 -0
- omlish/antlr/_runtime/error/ErrorListener.py +75 -0
- omlish/antlr/_runtime/error/ErrorStrategy.py +712 -0
- omlish/antlr/_runtime/error/Errors.py +176 -0
- omlish/antlr/_runtime/error/__init__.py +4 -0
- omlish/antlr/_runtime/tree/Chunk.py +33 -0
- omlish/antlr/_runtime/tree/ParseTreeMatch.py +121 -0
- omlish/antlr/_runtime/tree/ParseTreePattern.py +75 -0
- omlish/antlr/_runtime/tree/ParseTreePatternMatcher.py +377 -0
- omlish/antlr/_runtime/tree/RuleTagToken.py +53 -0
- omlish/antlr/_runtime/tree/TokenTagToken.py +50 -0
- omlish/antlr/_runtime/tree/Tree.py +194 -0
- omlish/antlr/_runtime/tree/Trees.py +114 -0
- omlish/antlr/_runtime/tree/__init__.py +2 -0
- omlish/antlr/_runtime/xpath/XPath.py +272 -0
- omlish/antlr/_runtime/xpath/XPathLexer.py +98 -0
- omlish/antlr/_runtime/xpath/__init__.py +4 -0
- omlish/formats/json/cli.py +76 -7
- omlish/formats/props.py +6 -2
- {omlish-0.0.0.dev56.dist-info → omlish-0.0.0.dev58.dist-info}/METADATA +1 -1
- {omlish-0.0.0.dev56.dist-info → omlish-0.0.0.dev58.dist-info}/RECORD +68 -9
- {omlish-0.0.0.dev56.dist-info → omlish-0.0.0.dev58.dist-info}/LICENSE +0 -0
- {omlish-0.0.0.dev56.dist-info → omlish-0.0.0.dev58.dist-info}/WHEEL +0 -0
- {omlish-0.0.0.dev56.dist-info → omlish-0.0.0.dev58.dist-info}/entry_points.txt +0 -0
- {omlish-0.0.0.dev56.dist-info → omlish-0.0.0.dev58.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,136 @@
|
|
1
|
+
# type: ignore
|
2
|
+
# ruff: noqa
|
3
|
+
# flake8: noqa
|
4
|
+
#
|
5
|
+
# Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
|
6
|
+
# Use of this file is governed by the BSD 3-clause license that
|
7
|
+
# can be found in the LICENSE.txt file in the project root.
|
8
|
+
from ..atn.ATNState import StarLoopEntryState
|
9
|
+
|
10
|
+
from ..atn.ATNConfigSet import ATNConfigSet
|
11
|
+
from ..atn.ATNState import DecisionState
|
12
|
+
from .DFAState import DFAState
|
13
|
+
from ..error.Errors import IllegalStateException
|
14
|
+
|
15
|
+
|
16
|
+
class DFA(object):
|
17
|
+
__slots__ = ('atnStartState', 'decision', '_states', 's0', 'precedenceDfa')
|
18
|
+
|
19
|
+
def __init__(self, atnStartState:DecisionState, decision:int=0):
|
20
|
+
# From which ATN state did we create this DFA?
|
21
|
+
self.atnStartState = atnStartState
|
22
|
+
self.decision = decision
|
23
|
+
# A set of all DFA states. Use {@link Map} so we can get old state back
|
24
|
+
# ({@link Set} only allows you to see if it's there).
|
25
|
+
self._states = dict()
|
26
|
+
self.s0 = None
|
27
|
+
# {@code true} if this DFA is for a precedence decision; otherwise,
|
28
|
+
# {@code false}. This is the backing field for {@link #isPrecedenceDfa},
|
29
|
+
# {@link #setPrecedenceDfa}.
|
30
|
+
self.precedenceDfa = False
|
31
|
+
|
32
|
+
if isinstance(atnStartState, StarLoopEntryState):
|
33
|
+
if atnStartState.isPrecedenceDecision:
|
34
|
+
self.precedenceDfa = True
|
35
|
+
precedenceState = DFAState(configs=ATNConfigSet())
|
36
|
+
precedenceState.edges = []
|
37
|
+
precedenceState.isAcceptState = False
|
38
|
+
precedenceState.requiresFullContext = False
|
39
|
+
self.s0 = precedenceState
|
40
|
+
|
41
|
+
|
42
|
+
# Get the start state for a specific precedence value.
|
43
|
+
#
|
44
|
+
# @param precedence The current precedence.
|
45
|
+
# @return The start state corresponding to the specified precedence, or
|
46
|
+
# {@code null} if no start state exists for the specified precedence.
|
47
|
+
#
|
48
|
+
# @throws IllegalStateException if this is not a precedence DFA.
|
49
|
+
# @see #isPrecedenceDfa()
|
50
|
+
|
51
|
+
def getPrecedenceStartState(self, precedence:int):
|
52
|
+
if not self.precedenceDfa:
|
53
|
+
raise IllegalStateException("Only precedence DFAs may contain a precedence start state.")
|
54
|
+
|
55
|
+
# s0.edges is never null for a precedence DFA
|
56
|
+
if precedence < 0 or precedence >= len(self.s0.edges):
|
57
|
+
return None
|
58
|
+
return self.s0.edges[precedence]
|
59
|
+
|
60
|
+
# Set the start state for a specific precedence value.
|
61
|
+
#
|
62
|
+
# @param precedence The current precedence.
|
63
|
+
# @param startState The start state corresponding to the specified
|
64
|
+
# precedence.
|
65
|
+
#
|
66
|
+
# @throws IllegalStateException if this is not a precedence DFA.
|
67
|
+
# @see #isPrecedenceDfa()
|
68
|
+
#
|
69
|
+
def setPrecedenceStartState(self, precedence:int, startState:DFAState):
|
70
|
+
if not self.precedenceDfa:
|
71
|
+
raise IllegalStateException("Only precedence DFAs may contain a precedence start state.")
|
72
|
+
|
73
|
+
if precedence < 0:
|
74
|
+
return
|
75
|
+
|
76
|
+
# synchronization on s0 here is ok. when the DFA is turned into a
|
77
|
+
# precedence DFA, s0 will be initialized once and not updated again
|
78
|
+
# s0.edges is never null for a precedence DFA
|
79
|
+
if precedence >= len(self.s0.edges):
|
80
|
+
ext = [None] * (precedence + 1 - len(self.s0.edges))
|
81
|
+
self.s0.edges.extend(ext)
|
82
|
+
self.s0.edges[precedence] = startState
|
83
|
+
#
|
84
|
+
# Sets whether this is a precedence DFA. If the specified value differs
|
85
|
+
# from the current DFA configuration, the following actions are taken;
|
86
|
+
# otherwise no changes are made to the current DFA.
|
87
|
+
#
|
88
|
+
# <ul>
|
89
|
+
# <li>The {@link #states} map is cleared</li>
|
90
|
+
# <li>If {@code precedenceDfa} is {@code false}, the initial state
|
91
|
+
# {@link #s0} is set to {@code null}; otherwise, it is initialized to a new
|
92
|
+
# {@link DFAState} with an empty outgoing {@link DFAState#edges} array to
|
93
|
+
# store the start states for individual precedence values.</li>
|
94
|
+
# <li>The {@link #precedenceDfa} field is updated</li>
|
95
|
+
# </ul>
|
96
|
+
#
|
97
|
+
# @param precedenceDfa {@code true} if this is a precedence DFA; otherwise,
|
98
|
+
# {@code false}
|
99
|
+
|
100
|
+
def setPrecedenceDfa(self, precedenceDfa:bool):
|
101
|
+
if self.precedenceDfa != precedenceDfa:
|
102
|
+
self._states = dict()
|
103
|
+
if precedenceDfa:
|
104
|
+
precedenceState = DFAState(configs=ATNConfigSet())
|
105
|
+
precedenceState.edges = []
|
106
|
+
precedenceState.isAcceptState = False
|
107
|
+
precedenceState.requiresFullContext = False
|
108
|
+
self.s0 = precedenceState
|
109
|
+
else:
|
110
|
+
self.s0 = None
|
111
|
+
self.precedenceDfa = precedenceDfa
|
112
|
+
|
113
|
+
@property
|
114
|
+
def states(self):
|
115
|
+
return self._states
|
116
|
+
|
117
|
+
# Return a list of all states in this DFA, ordered by state number.
|
118
|
+
def sortedStates(self):
|
119
|
+
return sorted(self._states.keys(), key=lambda state: state.stateNumber)
|
120
|
+
|
121
|
+
def __str__(self):
|
122
|
+
return self.toString(None)
|
123
|
+
|
124
|
+
def toString(self, literalNames:list=None, symbolicNames:list=None):
|
125
|
+
if self.s0 is None:
|
126
|
+
return ""
|
127
|
+
from .DFASerializer import DFASerializer
|
128
|
+
serializer = DFASerializer(self,literalNames,symbolicNames)
|
129
|
+
return str(serializer)
|
130
|
+
|
131
|
+
def toLexerString(self):
|
132
|
+
if self.s0 is None:
|
133
|
+
return ""
|
134
|
+
from .DFASerializer import LexerDFASerializer
|
135
|
+
serializer = LexerDFASerializer(self)
|
136
|
+
return str(serializer)
|
@@ -0,0 +1,76 @@
|
|
1
|
+
# type: ignore
|
2
|
+
# ruff: noqa
|
3
|
+
# flake8: noqa
|
4
|
+
#
|
5
|
+
# Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
|
6
|
+
# Use of this file is governed by the BSD 3-clause license that
|
7
|
+
# can be found in the LICENSE.txt file in the project root.
|
8
|
+
#/
|
9
|
+
|
10
|
+
# A DFA walker that knows how to dump them to serialized strings.#/
|
11
|
+
from io import StringIO
|
12
|
+
from .. import DFA
|
13
|
+
from ..Utils import str_list
|
14
|
+
from .DFAState import DFAState
|
15
|
+
|
16
|
+
|
17
|
+
class DFASerializer(object):
|
18
|
+
__slots__ = ('dfa', 'literalNames', 'symbolicNames')
|
19
|
+
|
20
|
+
def __init__(self, dfa:DFA, literalNames:list=None, symbolicNames:list=None):
|
21
|
+
self.dfa = dfa
|
22
|
+
self.literalNames = literalNames
|
23
|
+
self.symbolicNames = symbolicNames
|
24
|
+
|
25
|
+
def __str__(self):
|
26
|
+
if self.dfa.s0 is None:
|
27
|
+
return None
|
28
|
+
with StringIO() as buf:
|
29
|
+
for s in self.dfa.sortedStates():
|
30
|
+
n = 0
|
31
|
+
if s.edges is not None:
|
32
|
+
n = len(s.edges)
|
33
|
+
for i in range(0, n):
|
34
|
+
t = s.edges[i]
|
35
|
+
if t is not None and t.stateNumber != 0x7FFFFFFF:
|
36
|
+
buf.write(self.getStateString(s))
|
37
|
+
label = self.getEdgeLabel(i)
|
38
|
+
buf.write("-")
|
39
|
+
buf.write(label)
|
40
|
+
buf.write("->")
|
41
|
+
buf.write(self.getStateString(t))
|
42
|
+
buf.write('\n')
|
43
|
+
output = buf.getvalue()
|
44
|
+
if len(output)==0:
|
45
|
+
return None
|
46
|
+
else:
|
47
|
+
return output
|
48
|
+
|
49
|
+
def getEdgeLabel(self, i:int):
|
50
|
+
if i==0:
|
51
|
+
return "EOF"
|
52
|
+
if self.literalNames is not None and i<=len(self.literalNames):
|
53
|
+
return self.literalNames[i-1]
|
54
|
+
elif self.symbolicNames is not None and i<=len(self.symbolicNames):
|
55
|
+
return self.symbolicNames[i-1]
|
56
|
+
else:
|
57
|
+
return str(i-1)
|
58
|
+
|
59
|
+
def getStateString(self, s:DFAState):
|
60
|
+
n = s.stateNumber
|
61
|
+
baseStateStr = ( ":" if s.isAcceptState else "") + "s" + str(n) + ( "^" if s.requiresFullContext else "")
|
62
|
+
if s.isAcceptState:
|
63
|
+
if s.predicates is not None:
|
64
|
+
return baseStateStr + "=>" + str_list(s.predicates)
|
65
|
+
else:
|
66
|
+
return baseStateStr + "=>" + str(s.prediction)
|
67
|
+
else:
|
68
|
+
return baseStateStr
|
69
|
+
|
70
|
+
class LexerDFASerializer(DFASerializer):
|
71
|
+
|
72
|
+
def __init__(self, dfa:DFA):
|
73
|
+
super().__init__(dfa, None)
|
74
|
+
|
75
|
+
def getEdgeLabel(self, i:int):
|
76
|
+
return "'" + chr(i) + "'"
|
@@ -0,0 +1,129 @@
|
|
1
|
+
# type: ignore
|
2
|
+
# ruff: noqa
|
3
|
+
# flake8: noqa
|
4
|
+
#
|
5
|
+
# Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
|
6
|
+
# Use of this file is governed by the BSD 3-clause license that
|
7
|
+
# can be found in the LICENSE.txt file in the project root.
|
8
|
+
#/
|
9
|
+
|
10
|
+
# Map a predicate to a predicted alternative.#/
|
11
|
+
from io import StringIO
|
12
|
+
from ..atn.ATNConfigSet import ATNConfigSet
|
13
|
+
from ..atn.SemanticContext import SemanticContext
|
14
|
+
|
15
|
+
|
16
|
+
class PredPrediction(object):
|
17
|
+
__slots__ = ('alt', 'pred')
|
18
|
+
|
19
|
+
def __init__(self, pred:SemanticContext, alt:int):
|
20
|
+
self.alt = alt
|
21
|
+
self.pred = pred
|
22
|
+
|
23
|
+
def __str__(self):
|
24
|
+
return "(" + str(self.pred) + ", " + str(self.alt) + ")"
|
25
|
+
|
26
|
+
# A DFA state represents a set of possible ATN configurations.
|
27
|
+
# As Aho, Sethi, Ullman p. 117 says "The DFA uses its state
|
28
|
+
# to keep track of all possible states the ATN can be in after
|
29
|
+
# reading each input symbol. That is to say, after reading
|
30
|
+
# input a1a2..an, the DFA is in a state that represents the
|
31
|
+
# subset T of the states of the ATN that are reachable from the
|
32
|
+
# ATN's start state along some path labeled a1a2..an."
|
33
|
+
# In conventional NFA→DFA conversion, therefore, the subset T
|
34
|
+
# would be a bitset representing the set of states the
|
35
|
+
# ATN could be in. We need to track the alt predicted by each
|
36
|
+
# state as well, however. More importantly, we need to maintain
|
37
|
+
# a stack of states, tracking the closure operations as they
|
38
|
+
# jump from rule to rule, emulating rule invocations (method calls).
|
39
|
+
# I have to add a stack to simulate the proper lookahead sequences for
|
40
|
+
# the underlying LL grammar from which the ATN was derived.
|
41
|
+
#
|
42
|
+
# <p>I use a set of ATNConfig objects not simple states. An ATNConfig
|
43
|
+
# is both a state (ala normal conversion) and a RuleContext describing
|
44
|
+
# the chain of rules (if any) followed to arrive at that state.</p>
|
45
|
+
#
|
46
|
+
# <p>A DFA state may have multiple references to a particular state,
|
47
|
+
# but with different ATN contexts (with same or different alts)
|
48
|
+
# meaning that state was reached via a different set of rule invocations.</p>
|
49
|
+
#/
|
50
|
+
class DFAState(object):
|
51
|
+
__slots__ = (
|
52
|
+
'stateNumber', 'configs', 'edges', 'isAcceptState', 'prediction',
|
53
|
+
'lexerActionExecutor', 'requiresFullContext', 'predicates'
|
54
|
+
)
|
55
|
+
|
56
|
+
def __init__(self, stateNumber:int=-1, configs:ATNConfigSet=ATNConfigSet()):
|
57
|
+
self.stateNumber = stateNumber
|
58
|
+
self.configs = configs
|
59
|
+
# {@code edges[symbol]} points to target of symbol. Shift up by 1 so (-1)
|
60
|
+
# {@link Token#EOF} maps to {@code edges[0]}.
|
61
|
+
self.edges = None
|
62
|
+
self.isAcceptState = False
|
63
|
+
# if accept state, what ttype do we match or alt do we predict?
|
64
|
+
# This is set to {@link ATN#INVALID_ALT_NUMBER} when {@link #predicates}{@code !=null} or
|
65
|
+
# {@link #requiresFullContext}.
|
66
|
+
self.prediction = 0
|
67
|
+
self.lexerActionExecutor = None
|
68
|
+
# Indicates that this state was created during SLL prediction that
|
69
|
+
# discovered a conflict between the configurations in the state. Future
|
70
|
+
# {@link ParserATNSimulator#execATN} invocations immediately jumped doing
|
71
|
+
# full context prediction if this field is true.
|
72
|
+
self.requiresFullContext = False
|
73
|
+
# During SLL parsing, this is a list of predicates associated with the
|
74
|
+
# ATN configurations of the DFA state. When we have predicates,
|
75
|
+
# {@link #requiresFullContext} is {@code false} since full context prediction evaluates predicates
|
76
|
+
# on-the-fly. If this is not null, then {@link #prediction} is
|
77
|
+
# {@link ATN#INVALID_ALT_NUMBER}.
|
78
|
+
#
|
79
|
+
# <p>We only use these for non-{@link #requiresFullContext} but conflicting states. That
|
80
|
+
# means we know from the context (it's $ or we don't dip into outer
|
81
|
+
# context) that it's an ambiguity not a conflict.</p>
|
82
|
+
#
|
83
|
+
# <p>This list is computed by {@link ParserATNSimulator#predicateDFAState}.</p>
|
84
|
+
self.predicates = None
|
85
|
+
|
86
|
+
|
87
|
+
|
88
|
+
# Get the set of all alts mentioned by all ATN configurations in this
|
89
|
+
# DFA state.
|
90
|
+
def getAltSet(self):
|
91
|
+
if self.configs is not None:
|
92
|
+
return set(cfg.alt for cfg in self.configs) or None
|
93
|
+
return None
|
94
|
+
|
95
|
+
def __hash__(self):
|
96
|
+
return hash(self.configs)
|
97
|
+
|
98
|
+
# Two {@link DFAState} instances are equal if their ATN configuration sets
|
99
|
+
# are the same. This method is used to see if a state already exists.
|
100
|
+
#
|
101
|
+
# <p>Because the number of alternatives and number of ATN configurations are
|
102
|
+
# finite, there is a finite number of DFA states that can be processed.
|
103
|
+
# This is necessary to show that the algorithm terminates.</p>
|
104
|
+
#
|
105
|
+
# <p>Cannot test the DFA state numbers here because in
|
106
|
+
# {@link ParserATNSimulator#addDFAState} we need to know if any other state
|
107
|
+
# exists that has this exact set of ATN configurations. The
|
108
|
+
# {@link #stateNumber} is irrelevant.</p>
|
109
|
+
def __eq__(self, other):
|
110
|
+
# compare set of ATN configurations in this set with other
|
111
|
+
if self is other:
|
112
|
+
return True
|
113
|
+
elif not isinstance(other, DFAState):
|
114
|
+
return False
|
115
|
+
else:
|
116
|
+
return self.configs==other.configs
|
117
|
+
|
118
|
+
def __str__(self):
|
119
|
+
with StringIO() as buf:
|
120
|
+
buf.write(str(self.stateNumber))
|
121
|
+
buf.write(":")
|
122
|
+
buf.write(str(self.configs))
|
123
|
+
if self.isAcceptState:
|
124
|
+
buf.write("=>")
|
125
|
+
if self.predicates is not None:
|
126
|
+
buf.write(str(self.predicates))
|
127
|
+
else:
|
128
|
+
buf.write(str(self.prediction))
|
129
|
+
return buf.getvalue()
|
@@ -0,0 +1,110 @@
|
|
1
|
+
# type: ignore
|
2
|
+
# ruff: noqa
|
3
|
+
# flake8: noqa
|
4
|
+
#
|
5
|
+
# Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
|
6
|
+
# Use of this file is governed by the BSD 3-clause license that
|
7
|
+
# can be found in the LICENSE.txt file in the project root.
|
8
|
+
#
|
9
|
+
|
10
|
+
|
11
|
+
#
|
12
|
+
# This implementation of {@link ANTLRErrorListener} can be used to identify
|
13
|
+
# certain potential correctness and performance problems in grammars. "Reports"
|
14
|
+
# are made by calling {@link Parser#notifyErrorListeners} with the appropriate
|
15
|
+
# message.
|
16
|
+
#
|
17
|
+
# <ul>
|
18
|
+
# <li><b>Ambiguities</b>: These are cases where more than one path through the
|
19
|
+
# grammar can match the input.</li>
|
20
|
+
# <li><b>Weak context sensitivity</b>: These are cases where full-context
|
21
|
+
# prediction resolved an SLL conflict to a unique alternative which equaled the
|
22
|
+
# minimum alternative of the SLL conflict.</li>
|
23
|
+
# <li><b>Strong (forced) context sensitivity</b>: These are cases where the
|
24
|
+
# full-context prediction resolved an SLL conflict to a unique alternative,
|
25
|
+
# <em>and</em> the minimum alternative of the SLL conflict was found to not be
|
26
|
+
# a truly viable alternative. Two-stage parsing cannot be used for inputs where
|
27
|
+
# this situation occurs.</li>
|
28
|
+
# </ul>
|
29
|
+
|
30
|
+
from io import StringIO
|
31
|
+
from .. import Parser, DFA
|
32
|
+
from ..atn.ATNConfigSet import ATNConfigSet
|
33
|
+
from .ErrorListener import ErrorListener
|
34
|
+
|
35
|
+
class DiagnosticErrorListener(ErrorListener):
|
36
|
+
|
37
|
+
def __init__(self, exactOnly:bool=True):
|
38
|
+
# whether all ambiguities or only exact ambiguities are reported.
|
39
|
+
self.exactOnly = exactOnly
|
40
|
+
|
41
|
+
def reportAmbiguity(self, recognizer:Parser, dfa:DFA, startIndex:int,
|
42
|
+
stopIndex:int, exact:bool, ambigAlts:set, configs:ATNConfigSet):
|
43
|
+
if self.exactOnly and not exact:
|
44
|
+
return
|
45
|
+
|
46
|
+
with StringIO() as buf:
|
47
|
+
buf.write("reportAmbiguity d=")
|
48
|
+
buf.write(self.getDecisionDescription(recognizer, dfa))
|
49
|
+
buf.write(": ambigAlts=")
|
50
|
+
buf.write(str(self.getConflictingAlts(ambigAlts, configs)))
|
51
|
+
buf.write(", input='")
|
52
|
+
buf.write(recognizer.getTokenStream().getText(startIndex, stopIndex))
|
53
|
+
buf.write("'")
|
54
|
+
recognizer.notifyErrorListeners(buf.getvalue())
|
55
|
+
|
56
|
+
|
57
|
+
def reportAttemptingFullContext(self, recognizer:Parser, dfa:DFA, startIndex:int,
|
58
|
+
stopIndex:int, conflictingAlts:set, configs:ATNConfigSet):
|
59
|
+
with StringIO() as buf:
|
60
|
+
buf.write("reportAttemptingFullContext d=")
|
61
|
+
buf.write(self.getDecisionDescription(recognizer, dfa))
|
62
|
+
buf.write(", input='")
|
63
|
+
buf.write(recognizer.getTokenStream().getText(startIndex, stopIndex))
|
64
|
+
buf.write("'")
|
65
|
+
recognizer.notifyErrorListeners(buf.getvalue())
|
66
|
+
|
67
|
+
def reportContextSensitivity(self, recognizer:Parser, dfa:DFA, startIndex:int,
|
68
|
+
stopIndex:int, prediction:int, configs:ATNConfigSet):
|
69
|
+
with StringIO() as buf:
|
70
|
+
buf.write("reportContextSensitivity d=")
|
71
|
+
buf.write(self.getDecisionDescription(recognizer, dfa))
|
72
|
+
buf.write(", input='")
|
73
|
+
buf.write(recognizer.getTokenStream().getText(startIndex, stopIndex))
|
74
|
+
buf.write("'")
|
75
|
+
recognizer.notifyErrorListeners(buf.getvalue())
|
76
|
+
|
77
|
+
def getDecisionDescription(self, recognizer:Parser, dfa:DFA):
|
78
|
+
decision = dfa.decision
|
79
|
+
ruleIndex = dfa.atnStartState.ruleIndex
|
80
|
+
|
81
|
+
ruleNames = recognizer.ruleNames
|
82
|
+
if ruleIndex < 0 or ruleIndex >= len(ruleNames):
|
83
|
+
return str(decision)
|
84
|
+
|
85
|
+
ruleName = ruleNames[ruleIndex]
|
86
|
+
if ruleName is None or len(ruleName)==0:
|
87
|
+
return str(decision)
|
88
|
+
|
89
|
+
return str(decision) + " (" + ruleName + ")"
|
90
|
+
|
91
|
+
#
|
92
|
+
# Computes the set of conflicting or ambiguous alternatives from a
|
93
|
+
# configuration set, if that information was not already provided by the
|
94
|
+
# parser.
|
95
|
+
#
|
96
|
+
# @param reportedAlts The set of conflicting or ambiguous alternatives, as
|
97
|
+
# reported by the parser.
|
98
|
+
# @param configs The conflicting or ambiguous configuration set.
|
99
|
+
# @return Returns {@code reportedAlts} if it is not {@code null}, otherwise
|
100
|
+
# returns the set of alternatives represented in {@code configs}.
|
101
|
+
#
|
102
|
+
def getConflictingAlts(self, reportedAlts:set, configs:ATNConfigSet):
|
103
|
+
if reportedAlts is not None:
|
104
|
+
return reportedAlts
|
105
|
+
|
106
|
+
result = set()
|
107
|
+
for config in configs:
|
108
|
+
result.add(config.alt)
|
109
|
+
|
110
|
+
return result
|
@@ -0,0 +1,75 @@
|
|
1
|
+
# type: ignore
|
2
|
+
# ruff: noqa
|
3
|
+
# flake8: noqa
|
4
|
+
#
|
5
|
+
# Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
|
6
|
+
# Use of this file is governed by the BSD 3-clause license that
|
7
|
+
# can be found in the LICENSE.txt file in the project root.
|
8
|
+
|
9
|
+
# Provides an empty default implementation of {@link ANTLRErrorListener}. The
|
10
|
+
# default implementation of each method does nothing, but can be overridden as
|
11
|
+
# necessary.
|
12
|
+
|
13
|
+
|
14
|
+
import sys
|
15
|
+
|
16
|
+
class ErrorListener(object):
|
17
|
+
|
18
|
+
def syntaxError(self, recognizer, offendingSymbol, line, column, msg, e):
|
19
|
+
pass
|
20
|
+
|
21
|
+
def reportAmbiguity(self, recognizer, dfa, startIndex, stopIndex, exact, ambigAlts, configs):
|
22
|
+
pass
|
23
|
+
|
24
|
+
def reportAttemptingFullContext(self, recognizer, dfa, startIndex, stopIndex, conflictingAlts, configs):
|
25
|
+
pass
|
26
|
+
|
27
|
+
def reportContextSensitivity(self, recognizer, dfa, startIndex, stopIndex, prediction, configs):
|
28
|
+
pass
|
29
|
+
|
30
|
+
class ConsoleErrorListener(ErrorListener):
|
31
|
+
#
|
32
|
+
# Provides a default instance of {@link ConsoleErrorListener}.
|
33
|
+
#
|
34
|
+
INSTANCE = None
|
35
|
+
|
36
|
+
#
|
37
|
+
# {@inheritDoc}
|
38
|
+
#
|
39
|
+
# <p>
|
40
|
+
# This implementation prints messages to {@link System#err} containing the
|
41
|
+
# values of {@code line}, {@code charPositionInLine}, and {@code msg} using
|
42
|
+
# the following format.</p>
|
43
|
+
#
|
44
|
+
# <pre>
|
45
|
+
# line <em>line</em>:<em>charPositionInLine</em> <em>msg</em>
|
46
|
+
# </pre>
|
47
|
+
#
|
48
|
+
def syntaxError(self, recognizer, offendingSymbol, line, column, msg, e):
|
49
|
+
print("line " + str(line) + ":" + str(column) + " " + msg, file=sys.stderr)
|
50
|
+
|
51
|
+
ConsoleErrorListener.INSTANCE = ConsoleErrorListener()
|
52
|
+
|
53
|
+
class ProxyErrorListener(ErrorListener):
|
54
|
+
|
55
|
+
def __init__(self, delegates):
|
56
|
+
super().__init__()
|
57
|
+
if delegates is None:
|
58
|
+
raise ReferenceError("delegates")
|
59
|
+
self.delegates = delegates
|
60
|
+
|
61
|
+
def syntaxError(self, recognizer, offendingSymbol, line, column, msg, e):
|
62
|
+
for delegate in self.delegates:
|
63
|
+
delegate.syntaxError(recognizer, offendingSymbol, line, column, msg, e)
|
64
|
+
|
65
|
+
def reportAmbiguity(self, recognizer, dfa, startIndex, stopIndex, exact, ambigAlts, configs):
|
66
|
+
for delegate in self.delegates:
|
67
|
+
delegate.reportAmbiguity(recognizer, dfa, startIndex, stopIndex, exact, ambigAlts, configs)
|
68
|
+
|
69
|
+
def reportAttemptingFullContext(self, recognizer, dfa, startIndex, stopIndex, conflictingAlts, configs):
|
70
|
+
for delegate in self.delegates:
|
71
|
+
delegate.reportAttemptingFullContext(recognizer, dfa, startIndex, stopIndex, conflictingAlts, configs)
|
72
|
+
|
73
|
+
def reportContextSensitivity(self, recognizer, dfa, startIndex, stopIndex, prediction, configs):
|
74
|
+
for delegate in self.delegates:
|
75
|
+
delegate.reportContextSensitivity(recognizer, dfa, startIndex, stopIndex, prediction, configs)
|