-
Notifications
You must be signed in to change notification settings - Fork 38
Expand file tree
/
Copy pathDFA.js
More file actions
159 lines (149 loc) · 4.71 KB
/
DFA.js
File metadata and controls
159 lines (149 loc) · 4.71 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
/* Copyright (c) 2012-2022 The ANTLR Project. All rights reserved.
* Use of this file is governed by the BSD 3-clause license that
* can be found in the LICENSE.txt file in the project root.
*/
import DFAState from './DFAState.js';
import StarLoopEntryState from '../state/StarLoopEntryState.js';
import ATNConfigSet from './../atn/ATNConfigSet.js';
import DFASerializer from './DFASerializer.js';
import LexerDFASerializer from './LexerDFASerializer.js';
import HashSet from "../misc/HashSet.js";
export default class DFA {
constructor(atnStartState, decision) {
if (decision === undefined) {
decision = 0;
}
/**
* From which ATN state did we create this DFA?
*/
this.atnStartState = atnStartState;
this.decision = decision;
/**
* A set of all DFA states. Use {@link Map} so we can get old state back
* ({@link Set} only allows you to see if it's there).
*/
this._states = new HashSet();
this.s0 = null;
/**
* {@code true} if this DFA is for a precedence decision; otherwise,
* {@code false}. This is the backing field for {@link //isPrecedenceDfa},
* {@link //setPrecedenceDfa}
*/
this.precedenceDfa = false;
if (atnStartState instanceof StarLoopEntryState)
{
if (atnStartState.isPrecedenceDecision) {
this.precedenceDfa = true;
let precedenceState = new DFAState(null, new ATNConfigSet());
precedenceState.edges = [];
precedenceState.isAcceptState = false;
precedenceState.requiresFullContext = false;
this.s0 = precedenceState;
}
}
}
/**
* Get the start state for a specific precedence value.
*
* @param precedence The current precedence.
* @return The start state corresponding to the specified precedence, or
* {@code null} if no start state exists for the specified precedence.
*
* @throws IllegalStateException if this is not a precedence DFA.
* @see //isPrecedenceDfa()
*/
getPrecedenceStartState(precedence) {
if (!(this.precedenceDfa)) {
throw ("Only precedence DFAs may contain a precedence start state.");
}
// s0.edges is never null for a precedence DFA
if (precedence < 0 || precedence >= this.s0.edges.length) {
return null;
}
return this.s0.edges[precedence] || null;
}
/**
* Set the start state for a specific precedence value.
*
* @param precedence The current precedence.
* @param startState The start state corresponding to the specified
* precedence.
*
* @throws IllegalStateException if this is not a precedence DFA.
* @see //isPrecedenceDfa()
*/
setPrecedenceStartState(precedence, startState) {
if (!(this.precedenceDfa)) {
throw ("Only precedence DFAs may contain a precedence start state.");
}
if (precedence < 0) {
return;
}
/**
* synchronization on s0 here is ok. when the DFA is turned into a
* precedence DFA, s0 will be initialized once and not updated again
* s0.edges is never null for a precedence DFA
*/
this.s0.edges[precedence] = startState;
}
/**
* Sets whether this is a precedence DFA. If the specified value differs
* from the current DFA configuration, the following actions are taken;
* otherwise no changes are made to the current DFA.
*
* <ul>
* <li>The {@link //states} map is cleared</li>
* <li>If {@code precedenceDfa} is {@code false}, the initial state
* {@link //s0} is set to {@code null}; otherwise, it is initialized to a new
* {@link DFAState} with an empty outgoing {@link DFAState//edges} array to
* store the start states for individual precedence values.</li>
* <li>The {@link //precedenceDfa} field is updated</li>
* </ul>
*
* @param precedenceDfa {@code true} if this is a precedence DFA; otherwise,
* {@code false}
*/
setPrecedenceDfa(precedenceDfa) {
if (this.precedenceDfa!==precedenceDfa) {
this._states = new HashSet();
if (precedenceDfa) {
let precedenceState = new DFAState(null, new ATNConfigSet());
precedenceState.edges = [];
precedenceState.isAcceptState = false;
precedenceState.requiresFullContext = false;
this.s0 = precedenceState;
} else {
this.s0 = null;
}
this.precedenceDfa = precedenceDfa;
}
}
/**
* Return a list of all states in this DFA, ordered by state number.
*/
sortedStates() {
let list = this._states.values();
return list.sort(function(a, b) {
return a.stateNumber - b.stateNumber;
});
}
toString(literalNames, symbolicNames) {
literalNames = literalNames || null;
symbolicNames = symbolicNames || null;
if (this.s0 === null) {
return "";
}
let serializer = new DFASerializer(this, literalNames, symbolicNames);
return serializer.toString();
}
toLexerString() {
if (this.s0 === null) {
return "";
}
let serializer = new LexerDFASerializer(this);
return serializer.toString();
}
get states(){
return this._states;
}
}