-
Notifications
You must be signed in to change notification settings - Fork 38
Expand file tree
/
Copy pathATNConfig.js
More file actions
134 lines (124 loc) · 5.11 KB
/
ATNConfig.js
File metadata and controls
134 lines (124 loc) · 5.11 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
/* 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 SemanticContext from './SemanticContext.js';
import HashCode from "../misc/HashCode.js";
function checkParams(params, isCfg) {
if(params===null) {
let result = { state:null, alt:null, context:null, semanticContext:null };
if(isCfg) {
result.reachesIntoOuterContext = 0;
}
return result;
} else {
let props = {};
props.state = params.state || null;
props.alt = (params.alt === undefined) ? null : params.alt;
props.context = params.context || null;
props.semanticContext = params.semanticContext || null;
if(isCfg) {
props.reachesIntoOuterContext = params.reachesIntoOuterContext || 0;
props.precedenceFilterSuppressed = params.precedenceFilterSuppressed || false;
}
return props;
}
}
export default class ATNConfig {
/**
* @param {Object} params A tuple: (ATN state, predicted alt, syntactic, semantic context).
* The syntactic context is a graph-structured stack node whose
* path(s) to the root is the rule invocation(s)
* chain used to arrive at the state. The semantic context is
* the tree of semantic predicates encountered before reaching
* an ATN state
*/
constructor(params, config) {
this.checkContext(params, config);
params = checkParams(params);
config = checkParams(config, true);
// The ATN state associated with this configuration///
this.state = params.state!==null ? params.state : config.state;
// What alt (or lexer rule) is predicted by this configuration///
this.alt = params.alt!==null ? params.alt : config.alt;
/**
* The stack of invoking states leading to the rule/states associated
* with this config. We track only those contexts pushed during
* execution of the ATN simulator
*/
this.context = params.context!==null ? params.context : config.context;
this.semanticContext = params.semanticContext!==null ? params.semanticContext :
(config.semanticContext!==null ? config.semanticContext : SemanticContext.NONE);
// TODO: make it a boolean then
/**
* We cannot execute predicates dependent upon local context unless
* we know for sure we are in the correct context. Because there is
* no way to do this efficiently, we simply cannot evaluate
* dependent predicates unless we are in the rule that initially
* invokes the ATN simulator.
* closure() tracks the depth of how far we dip into the
* outer context: depth > 0. Note that it may not be totally
* accurate depth since I don't ever decrement
*/
this.reachesIntoOuterContext = config.reachesIntoOuterContext;
this.precedenceFilterSuppressed = config.precedenceFilterSuppressed;
}
checkContext(params, config) {
if((params.context===null || params.context===undefined) &&
(config===null || config.context===null || config.context===undefined)) {
this.context = null;
}
}
hashCode() {
let hash = new HashCode();
this.updateHashCode(hash);
return hash.finish();
}
updateHashCode(hash) {
hash.update(this.state.stateNumber, this.alt, this.context, this.semanticContext);
}
/**
* An ATN configuration is equal to another if both have
* the same state, they predict the same alternative, and
* syntactic/semantic contexts are the same
*/
equals(other) {
if (this === other) {
return true;
} else if (! (other instanceof ATNConfig)) {
return false;
} else {
return this.state.stateNumber===other.state.stateNumber &&
this.alt===other.alt &&
(this.context===null ? other.context===null : this.context.equals(other.context)) &&
this.semanticContext.equals(other.semanticContext) &&
this.precedenceFilterSuppressed===other.precedenceFilterSuppressed;
}
}
hashCodeForConfigSet() {
let hash = new HashCode();
hash.update(this.state.stateNumber, this.alt, this.semanticContext);
return hash.finish();
}
equalsForConfigSet(other) {
if (this === other) {
return true;
} else if (! (other instanceof ATNConfig)) {
return false;
} else {
return this.state.stateNumber===other.state.stateNumber &&
this.alt===other.alt &&
this.semanticContext.equals(other.semanticContext);
}
}
toString() {
return "(" + this.state + "," + this.alt +
(this.context!==null ? ",[" + this.context.toString() + "]" : "") +
(this.semanticContext !== SemanticContext.NONE ?
("," + this.semanticContext.toString())
: "") +
(this.reachesIntoOuterContext>0 ?
(",up=" + this.reachesIntoOuterContext)
: "") + ")";
}
}