-
-
Notifications
You must be signed in to change notification settings - Fork 108
/
Copy pathparser.js
177 lines (169 loc) · 4.95 KB
/
parser.js
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
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
"use strict";
const { Parser, isRecognitionException } = require("chevrotain");
const { allTokens, tokens: t } = require("./tokens");
const lexicalStructure = require("./productions/lexical-structure");
const typesValuesVariables = require("./productions/types-values-and-variables");
const names = require("./productions/names");
const packagesModules = require("./productions/packages-and-modules");
const classes = require("./productions/classes");
const interfaces = require("./productions/interfaces");
const arrays = require("./productions/arrays");
const blocksStatements = require("./productions/blocks-and-statements");
const expressions = require("./productions/expressions");
/**
* This parser attempts to strongly align with the specs style at:
* - https://docs.oracle.com/javase/specs/jls/se11/html/jls-19.html
*
* Deviations from the spec will be marked.
*
* Note that deviations from the spec do not mean deviations from Java Grammar.
* Rather it means an **equivalent** grammar which was written differently, e.g:
* - LL(k) vs LR(K)
* - Left Recursions vs Repetitions
* - NonTerminals combined together or divided to sub-NonTerminals
* - ...
*
* A special type of spec deviations are the "super grammar" kind.
* This means that the parser has been defined in such a way that it accept a
* **strict superset** of the inputs the official grammar accepts.
*
* This technique is used to simplify the parser when narrowing the set
* of accepted inputs can more easily be done in a post parsing phase.
*
* TODO: document guide lines for using back tracking
*
*/
class JavaParser extends Parser {
constructor() {
super(allTokens, {
// TODO: performance: maxLookahead = 1 may be faster, but could we refactor the grammar to it?
// and more importantly, do we want to?
maxLookahead: 2,
// ambiguities resolved by backtracking
ignoredIssues: {
annotationTypeMemberDeclaration: {
OR: true
},
typeDeclaration: {
OR: true
},
typeArgument: {
OR: true
},
type: {
OR: true
},
referenceType: {
OR: true
},
compilationUnit: {
OR: true
},
classBodyDeclaration: {
OR: true
},
classMemberDeclaration: {
OR: true
},
unannReferenceType: {
OR: true
},
formalParameter: {
OR: true
},
interfaceMemberDeclaration: {
OR: true
},
blockStatement: {
OR: true
},
forStatement: {
OR: true
},
newExpression: {
OR: true
},
arrayCreationExpression: {
OR: true,
OR2: true
},
expression: {
OR: true
},
lambdaParameterList: {
OR: true
},
lambdaParameter: {
OR: true
},
primaryPrefix: {
OR: true
},
castExpression: {
OR: true
},
referenceTypeCastExpression: {
OR: true
},
elementValue: {
OR: true
},
resource: {
OR: true
},
forInit: {
OR: true
},
interfaceDeclaration: {
OR: true
}
}
});
const $ = this;
// ---------------------
// Productions from §3 (Lexical Structure)
// ---------------------
$.RULE("typeIdentifier", () => {
// TODO: implement: Identifier but not var in the lexer
$.CONSUME(t.Identifier);
});
// Include the productions from all "chapters".
lexicalStructure.defineRules.call(this, $, t);
typesValuesVariables.defineRules.call(this, $, t);
names.defineRules.call(this, $, t);
classes.defineRules.call(this, $, t);
packagesModules.defineRules.call(this, $, t);
interfaces.defineRules.call(this, $, t);
arrays.defineRules.call(this, $, t);
blocksStatements.defineRules.call(this, $, t);
expressions.defineRules.call(this, $, t);
this.performSelfAnalysis();
}
// hack to turn off CST building side effects during backtracking
// TODO: should be patched in Chevrotain
cstPostNonTerminal(ruleCstResult, ruleName) {
if (this.isBackTracking() === false) {
super.cstPostNonTerminal(ruleCstResult, ruleName);
}
}
BACKTRACK_LOOKAHEAD(production, errValue = false) {
this.isBackTrackingStack.push(1);
// TODO: "saveRecogState" does not handle the occurrence stack
const orgState = this.saveRecogState();
try {
// hack to enable outputting none CST values from grammar rules.
this.outputCst = false;
return production.call(this);
} catch (e) {
if (isRecognitionException(e)) {
return errValue;
}
throw e;
} finally {
this.outputCst = true;
this.reloadRecogState(orgState);
this.isBackTrackingStack.pop();
}
}
}
module.exports = JavaParser;