23
23
*/
24
24
25
25
package org. opensolaris. opengrok. analysis. sh;
26
- import org . opensolaris . opengrok . analysis . JFlexXref;
26
+
27
27
import java. io. IOException;
28
- import org. opensolaris. opengrok. web. Util;
29
28
import java. util. Stack;
30
-
29
+ import org. opensolaris. opengrok. analysis. JFlexXrefSimple;
30
+ import org. opensolaris. opengrok. web. HtmlConsts;
31
+ import org. opensolaris. opengrok. web. Util;
31
32
% %
32
33
%public
33
34
%class ShXref
34
- %extends JFlexXref
35
+ %extends JFlexXrefSimple
35
36
%unicode
36
37
%int
37
38
%include CommonXref.lexh
38
39
%{
39
- private final Stack<Integer > stateStack = new Stack<Integer > ();
40
40
private final Stack<String > styleStack = new Stack<String > ();
41
41
42
42
// State variables for the HEREDOC state. They tell what the stop word is,
@@ -46,9 +46,8 @@ import java.util.Stack;
46
46
private boolean heredocStripLeadingTabs;
47
47
48
48
@Override
49
- public void reset() {
50
- super . reset();
51
- stateStack. clear();
49
+ protected void clearStack() {
50
+ super . clearStack();
52
51
styleStack. clear();
53
52
}
54
53
@@ -58,32 +57,21 @@ import java.util.Stack;
58
57
@Override
59
58
protected void setLineNumber(int x) { yyline = x; }
60
59
61
- private void pushstate(int state, String style) throws IOException {
62
- if (! styleStack. empty()) {
63
- out. write(" </span>" );
64
- }
65
- if (style == null ) {
66
- out. write(" <span>" );
67
- } else {
68
- out. write(" <span class=\" " + style + " \" >" );
69
- }
70
- stateStack. push(yystate());
71
- styleStack. push(style);
72
- yybegin(state);
60
+ @Override
61
+ public void pushSpan(int newState, String className) throws IOException {
62
+ super . pushSpan(newState, className);
63
+ styleStack. push(className);
73
64
}
74
65
75
- private void popstate() throws IOException {
76
- out. write(" </span>" );
77
- yybegin(stateStack. pop());
78
- styleStack. pop();
79
- if (! styleStack. empty()) {
80
- String style = styleStack. peek();
81
- if (style == null ) {
82
- out. write(" <span>" );
83
- } else {
84
- out. write(" <span class=\" " + style + " \" >" );
66
+ @Override
67
+ public void yypop() throws IOException {
68
+ super . yypop();
69
+ styleStack. pop();
70
+
71
+ if (! styleStack. empty()) {
72
+ String style = styleStack. peek();
73
+ disjointSpan(style);
85
74
}
86
- }
87
75
}
88
76
89
77
/**
@@ -150,7 +138,8 @@ File = {FNameChar}+ "." ([a-zA-Z]+)
150
138
state on the stack to prevent premature exit from the
151
139
STRING state. */
152
140
\$\{ {Identifier} \[\" {
153
- out. write(yytext()); pushstate(STRING , " s" );
141
+ out. write(yytext());
142
+ pushSpan(STRING , HtmlConsts . STRING_CLASS );
154
143
}
155
144
}
156
145
@@ -160,11 +149,25 @@ File = {FNameChar}+ "." ([a-zA-Z]+)
160
149
writeSymbol(id, Consts . shkwd, yyline);
161
150
}
162
151
163
- {Number} { out. write(" <span class=\" n\" >" ); out. write(yytext()); out. write(" </span>" ); }
152
+ {Number} {
153
+ String lastClassName = getDisjointSpanClassName();
154
+ disjointSpan(HtmlConsts . NUMBER_CLASS );
155
+ out. write(yytext());
156
+ disjointSpan(lastClassName);
157
+ }
164
158
165
- \$ ? \" { pushstate(STRING , " s" ); out. write(yytext()); }
166
- \$ ? \' { pushstate(QSTRING , " s" ); out. write(yytext()); }
167
- "#" { pushstate(SCOMMENT , " c" ); out. write(yytext()); }
159
+ \$ ? \" {
160
+ pushSpan(STRING , HtmlConsts . STRING_CLASS );
161
+ out. write(yytext());
162
+ }
163
+ \$ ? \' {
164
+ pushSpan(QSTRING , HtmlConsts . STRING_CLASS );
165
+ out. write(yytext());
166
+ }
167
+ "#" {
168
+ pushSpan(SCOMMENT , HtmlConsts . COMMENT_CLASS );
169
+ out. write(yytext());
170
+ }
168
171
169
172
// Recognize here-documents. At least a subset of them.
170
173
"<<" "-" ? {WhspChar} * {Identifier} {WhspChar} * {
@@ -173,7 +176,7 @@ File = {FNameChar}+ "." ([a-zA-Z]+)
173
176
174
177
heredocStripLeadingTabs = (text. charAt(2 ) == ' -' );
175
178
heredocStopWord = text. substring(heredocStripLeadingTabs ? 3 : 2 ). trim();
176
- pushstate (HEREDOC , " s " );
179
+ pushSpan (HEREDOC , HtmlConsts . STRING_CLASS );
177
180
}
178
181
179
182
// Any sequence of more than two < characters should not start HEREDOC. Use
@@ -186,37 +189,46 @@ File = {FNameChar}+ "." ([a-zA-Z]+)
186
189
187
190
<STRING> {
188
191
\" {WhspChar} * \" { out. write(yytext()); }
189
- \" { out. write(yytext()); popstate (); }
192
+ \" { out. write(yytext()); yypop (); }
190
193
\\\\ | \\\" | \\\$ | \\ ` { out. write(yytext()); }
191
- \$\( { pushstate(SUBSHELL , null ); out. write(yytext()); }
192
- ` { pushstate(BACKQUOTE , null ); out. write(yytext()); }
194
+ \$\( {
195
+ pushSpan(SUBSHELL , null );
196
+ out. write(yytext());
197
+ }
198
+ ` {
199
+ pushSpan(BACKQUOTE , null );
200
+ out. write(yytext());
201
+ }
193
202
194
203
/* Bug #15661: Recognize ksh command substitution within strings. According
195
204
* to ksh man page http://www2.research.att.com/~gsf/man/man1/ksh-man.html#Command%20Substitution
196
205
* the opening brace must be followed by a blank.
197
206
*/
198
207
"${" / {WhspChar} | {EOL} {
199
- pushstate(BRACEGROUP , null ); out. write(yytext());
208
+ pushSpan(BRACEGROUP , null );
209
+ out. write(yytext());
200
210
}
201
211
}
202
212
203
213
<QSTRING> {
204
214
\' {WhspChar} * \' { out. write(yytext()); }
205
215
\\ ' { out. write(" \\ '" ); }
206
- \' { out. write(yytext()); popstate (); }
216
+ \' { out. write(yytext()); yypop (); }
207
217
}
208
218
209
219
<SCOMMENT> {
210
- {EOL} { popstate();
211
- startNewLine();}
220
+ {EOL} {
221
+ yypop();
222
+ startNewLine();
223
+ }
212
224
}
213
225
214
226
<SUBSHELL> {
215
- \) { out. write(yytext()); popstate (); }
227
+ \) { out. write(yytext()); yypop (); }
216
228
}
217
229
218
230
<BACKQUOTE> {
219
- ` { out. write(yytext()); popstate (); }
231
+ ` { out. write(yytext()); yypop (); }
220
232
}
221
233
222
234
<BRACEGROUP> {
@@ -225,15 +237,15 @@ File = {FNameChar}+ "." ([a-zA-Z]+)
225
237
* the closing brace must be on beginning of line, or it must be preceded by
226
238
* a semi-colon and (optionally) whitespace.
227
239
*/
228
- ^ {WhspChar} * \} { out. write(yytext()); popstate (); }
229
- ; {WhspChar} * \} { out. write(yytext()); popstate (); }
240
+ ^ {WhspChar} * \} { out. write(yytext()); yypop (); }
241
+ ; {WhspChar} * \} { out. write(yytext()); yypop (); }
230
242
}
231
243
232
244
<HEREDOC> {
233
245
[^\n] + {
234
246
String line = yytext();
235
247
if (isHeredocStopWord(line)) {
236
- popstate ();
248
+ yypop ();
237
249
}
238
250
out. write(Util . htmlize(line));
239
251
}
@@ -249,8 +261,8 @@ File = {FNameChar}+ "." ([a-zA-Z]+)
249
261
/* $# should not start a comment. */
250
262
"$#" { out. write(yytext()); }
251
263
252
- \$ ? \( { pushstate (SUBSHELL , null ); out. write(yytext()); }
253
- ` { pushstate (BACKQUOTE , null ); out. write(yytext()); }
264
+ \$ ? \( { pushSpan (SUBSHELL , null ); out. write(yytext()); }
265
+ ` { pushSpan (BACKQUOTE , null ); out. write(yytext()); }
254
266
255
267
/* Bug #15661: Recognize ksh command substitution within strings. According
256
268
* to ksh man page http://www2.research.att.com/~gsf/man/man1/ksh-man.html#Command%20Substitution
@@ -259,7 +271,7 @@ File = {FNameChar}+ "." ([a-zA-Z]+)
259
271
* group too early if the ${ cmd; } expression contains nested { cmd; } groups.
260
272
*/
261
273
\$ ? \{ / {WhspChar} | {EOL} {
262
- pushstate (BRACEGROUP , null ); out. write(yytext());
274
+ pushSpan (BRACEGROUP , null ); out. write(yytext());
263
275
}
264
276
}
265
277
@@ -297,12 +309,3 @@ File = {FNameChar}+ "." ([a-zA-Z]+)
297
309
writeEMailAddress(yytext());
298
310
}
299
311
}
300
-
301
- <<EOF>> {
302
- // If we reach EOF while being in a nested state, pop all the way up
303
- // the initial state so that we close open HTML tags.
304
- while (! stateStack. isEmpty()) {
305
- popstate();
306
- }
307
- return YYEOF ;
308
- }
0 commit comments