xref: /OpenGrok/opengrok-indexer/src/main/jflex/analysis/php/PhpXref.lex (revision d219b4cea555a12b602d2d5518daa22134ad4879)
1*d219b4ceSAdam Hornacek /*
2*d219b4ceSAdam Hornacek  * CDDL HEADER START
3*d219b4ceSAdam Hornacek  *
4*d219b4ceSAdam Hornacek  * The contents of this file are subject to the terms of the
5*d219b4ceSAdam Hornacek  * Common Development and Distribution License (the "License").
6*d219b4ceSAdam Hornacek  * You may not use this file except in compliance with the License.
7*d219b4ceSAdam Hornacek  *
8*d219b4ceSAdam Hornacek  * See LICENSE.txt included in this distribution for the specific
9*d219b4ceSAdam Hornacek  * language governing permissions and limitations under the License.
10*d219b4ceSAdam Hornacek  *
11*d219b4ceSAdam Hornacek  * When distributing Covered Code, include this CDDL HEADER in each
12*d219b4ceSAdam Hornacek  * file and include the License file at LICENSE.txt.
13*d219b4ceSAdam Hornacek  * If applicable, add the following below this CDDL HEADER, with the
14*d219b4ceSAdam Hornacek  * fields enclosed by brackets "[]" replaced with your own identifying
15*d219b4ceSAdam Hornacek  * information: Portions Copyright [yyyy] [name of copyright owner]
16*d219b4ceSAdam Hornacek  *
17*d219b4ceSAdam Hornacek  * CDDL HEADER END
18*d219b4ceSAdam Hornacek  */
19*d219b4ceSAdam Hornacek 
20*d219b4ceSAdam Hornacek /*
21*d219b4ceSAdam Hornacek  * Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved.
22*d219b4ceSAdam Hornacek  * Portions Copyright (c) 2017, Chris Fraire <cfraire@me.com>.
23*d219b4ceSAdam Hornacek  */
24*d219b4ceSAdam Hornacek 
25*d219b4ceSAdam Hornacek /*
26*d219b4ceSAdam Hornacek  * Cross reference a PHP file
27*d219b4ceSAdam Hornacek  */
28*d219b4ceSAdam Hornacek 
29*d219b4ceSAdam Hornacek package org.opengrok.indexer.analysis.php;
30*d219b4ceSAdam Hornacek 
31*d219b4ceSAdam Hornacek import java.io.IOException;
32*d219b4ceSAdam Hornacek import java.util.Arrays;
33*d219b4ceSAdam Hornacek import java.util.HashSet;
34*d219b4ceSAdam Hornacek import java.util.Set;
35*d219b4ceSAdam Hornacek import java.util.Stack;
36*d219b4ceSAdam Hornacek import org.opengrok.indexer.analysis.JFlexSymbolMatcher;
37*d219b4ceSAdam Hornacek import org.opengrok.indexer.analysis.EmphasisHint;
38*d219b4ceSAdam Hornacek import org.opengrok.indexer.web.HtmlConsts;
39*d219b4ceSAdam Hornacek %%
40*d219b4ceSAdam Hornacek %public
41*d219b4ceSAdam Hornacek %class PhpXref
42*d219b4ceSAdam Hornacek %extends JFlexSymbolMatcher
43*d219b4ceSAdam Hornacek %unicode
44*d219b4ceSAdam Hornacek %ignorecase
45*d219b4ceSAdam Hornacek %int
46*d219b4ceSAdam Hornacek %char
47*d219b4ceSAdam Hornacek %include ../CommonLexer.lexh
48*d219b4ceSAdam Hornacek %include ../CommonXref.lexh
49*d219b4ceSAdam Hornacek %{
50*d219b4ceSAdam Hornacek   private final static Set<String> PSEUDO_TYPES;
51*d219b4ceSAdam Hornacek   private final Stack<String> popStrings = new Stack<>();
52*d219b4ceSAdam Hornacek   private final Stack<String> docLabels = new Stack<String>();
53*d219b4ceSAdam Hornacek 
54*d219b4ceSAdam Hornacek   static {
55*d219b4ceSAdam Hornacek     PSEUDO_TYPES = new HashSet<String>(Arrays.asList(
56*d219b4ceSAdam Hornacek         new String[] {
57*d219b4ceSAdam Hornacek             "string", "integer", "int", "boolean", "bool", "float", "double",
58*d219b4ceSAdam Hornacek             "object", "mixed", "array", "resource", "void", "null", "callback",
59*d219b4ceSAdam Hornacek             "false", "true", "self", "callable"
60*d219b4ceSAdam Hornacek         }
61*d219b4ceSAdam Hornacek     ));
62*d219b4ceSAdam Hornacek   }
63*d219b4ceSAdam Hornacek 
64*d219b4ceSAdam Hornacek   @Override
clearStack()65*d219b4ceSAdam Hornacek   protected void clearStack() {
66*d219b4ceSAdam Hornacek       super.clearStack();
67*d219b4ceSAdam Hornacek       popStrings.clear();
68*d219b4ceSAdam Hornacek       docLabels.clear();
69*d219b4ceSAdam Hornacek   }
70*d219b4ceSAdam Hornacek 
71*d219b4ceSAdam Hornacek   /**
72*d219b4ceSAdam Hornacek    * save current yy state to stack
73*d219b4ceSAdam Hornacek    * @param newState state id
74*d219b4ceSAdam Hornacek    * @param popString string for the state
75*d219b4ceSAdam Hornacek    */
yypush(int newState,String popString)76*d219b4ceSAdam Hornacek   public void yypush(int newState, String popString) {
77*d219b4ceSAdam Hornacek       super.yypush(newState);
78*d219b4ceSAdam Hornacek       popStrings.push(popString);
79*d219b4ceSAdam Hornacek   }
80*d219b4ceSAdam Hornacek 
81*d219b4ceSAdam Hornacek   /**
82*d219b4ceSAdam Hornacek    * save current yy state to stack
83*d219b4ceSAdam Hornacek    * @param newState state id
84*d219b4ceSAdam Hornacek    */
85*d219b4ceSAdam Hornacek   @Override
yypush(int newState)86*d219b4ceSAdam Hornacek   public void yypush(int newState) {
87*d219b4ceSAdam Hornacek       yypush(newState, null);
88*d219b4ceSAdam Hornacek   }
89*d219b4ceSAdam Hornacek 
90*d219b4ceSAdam Hornacek   /**
91*d219b4ceSAdam Hornacek    * pop last state from stack
92*d219b4ceSAdam Hornacek    * @throws IOException in case of any I/O problem
93*d219b4ceSAdam Hornacek    */
94*d219b4ceSAdam Hornacek   @Override
yypop()95*d219b4ceSAdam Hornacek   public void yypop() throws IOException {
96*d219b4ceSAdam Hornacek       String popString = popStrings.pop();
97*d219b4ceSAdam Hornacek       if (popString != null) {
98*d219b4ceSAdam Hornacek           onDisjointSpanChanged(popString, yychar);
99*d219b4ceSAdam Hornacek       }
100*d219b4ceSAdam Hornacek       super.yypop();
101*d219b4ceSAdam Hornacek   }
102*d219b4ceSAdam Hornacek 
writeDocTag()103*d219b4ceSAdam Hornacek   private void writeDocTag() throws IOException {
104*d219b4ceSAdam Hornacek     String capture = yytext();
105*d219b4ceSAdam Hornacek     String sigil = capture.substring(0, 1);
106*d219b4ceSAdam Hornacek     String tag = capture.substring(1);
107*d219b4ceSAdam Hornacek     onNonSymbolMatched(sigil, yychar);
108*d219b4ceSAdam Hornacek     onNonSymbolMatched(tag, EmphasisHint.STRONG, yychar);
109*d219b4ceSAdam Hornacek   }
110*d219b4ceSAdam Hornacek 
isTabOrSpace(int i)111*d219b4ceSAdam Hornacek   private boolean isTabOrSpace(int i) {
112*d219b4ceSAdam Hornacek     return yycharat(i) == '\t' || yycharat(i) == ' ';
113*d219b4ceSAdam Hornacek   }
114*d219b4ceSAdam Hornacek 
isHtmlState(int state)115*d219b4ceSAdam Hornacek   private static boolean isHtmlState(int state) {
116*d219b4ceSAdam Hornacek     return state == TAG_NAME            || state == AFTER_TAG_NAME
117*d219b4ceSAdam Hornacek         || state == ATTRIBUTE_NOQUOTE   || state == ATTRIBUTE_SINGLE
118*d219b4ceSAdam Hornacek         || state == ATTRIBUTE_DOUBLE    || state == HTMLCOMMENT
119*d219b4ceSAdam Hornacek         || state == YYINITIAL;
120*d219b4ceSAdam Hornacek   }
121*d219b4ceSAdam Hornacek 
chkLOC()122*d219b4ceSAdam Hornacek   protected void chkLOC() {
123*d219b4ceSAdam Hornacek       switch (yystate()) {
124*d219b4ceSAdam Hornacek           case HTMLCOMMENT:
125*d219b4ceSAdam Hornacek           case SCOMMENT:
126*d219b4ceSAdam Hornacek           case COMMENT:
127*d219b4ceSAdam Hornacek           case DOCCOMMENT:
128*d219b4ceSAdam Hornacek           case DOCCOM_TYPE_THEN_NAME:
129*d219b4ceSAdam Hornacek           case DOCCOM_NAME:
130*d219b4ceSAdam Hornacek           case DOCCOM_TYPE:
131*d219b4ceSAdam Hornacek               break;
132*d219b4ceSAdam Hornacek           default:
133*d219b4ceSAdam Hornacek               phLOC();
134*d219b4ceSAdam Hornacek               break;
135*d219b4ceSAdam Hornacek       }
136*d219b4ceSAdam Hornacek   }
137*d219b4ceSAdam Hornacek %}
138*d219b4ceSAdam Hornacek 
139*d219b4ceSAdam Hornacek Identifier = [a-zA-Z_\u007F-\u10FFFF] [a-zA-Z0-9_\u007F-\u10FFFF]*
140*d219b4ceSAdam Hornacek 
141*d219b4ceSAdam Hornacek File = [a-zA-Z]{FNameChar}* "." ("php"|"php3"|"php4"|"phps"|"phtml"|"inc"|"diff"|"patch")
142*d219b4ceSAdam Hornacek 
143*d219b4ceSAdam Hornacek BinaryNumber = 0[b|B][01]+
144*d219b4ceSAdam Hornacek OctalNumber = 0[0-7]+
145*d219b4ceSAdam Hornacek DecimalNumber = [1-9][0-9]+
146*d219b4ceSAdam Hornacek HexadecimalNumber = 0[xX][0-9a-fA-F]+
147*d219b4ceSAdam Hornacek FloatNumber = (([0-9]* "." [0-9]+) | ([0-9]+ "." [0-9]*) | [0-9]+)([eE][+-]?[0-9]+)?
148*d219b4ceSAdam Hornacek Number = [+-]?({BinaryNumber}|{OctalNumber}|{DecimalNumber}|{HexadecimalNumber}|{FloatNumber})
149*d219b4ceSAdam Hornacek 
150*d219b4ceSAdam Hornacek //do not support <script language="php"> and </script> opening/closing tags
151*d219b4ceSAdam Hornacek OpeningTag = ("<?" "php"?) | "<?="
152*d219b4ceSAdam Hornacek ClosingTag = "?>"
153*d219b4ceSAdam Hornacek 
154*d219b4ceSAdam Hornacek CastTypes = "int"|"integer"|"real"|"double"|"float"|"string"|"binary"|"array"
155*d219b4ceSAdam Hornacek             |"object"|"bool"|"boolean"|"unset"
156*d219b4ceSAdam Hornacek 
157*d219b4ceSAdam Hornacek DoubleQuoteEscapeSequences = \\ (([nrtfve\\$]) | ([xX] [0-9a-fA-F]{1,2}) |  ([0-7]{1,3}))
158*d219b4ceSAdam Hornacek SingleQuoteEscapeSequences = \\ [\\\']
159*d219b4ceSAdam Hornacek 
160*d219b4ceSAdam Hornacek DocPreviousChar = "*" | {WhspChar}+
161*d219b4ceSAdam Hornacek 
162*d219b4ceSAdam Hornacek //does not supported nested type expressions like ((array|integer)[]|boolean)[]
163*d219b4ceSAdam Hornacek //that would require additional states
164*d219b4ceSAdam Hornacek DocType = {IndividualDocType} (\| {IndividualDocType})*
165*d219b4ceSAdam Hornacek IndividualDocType = ({SimpleDocType} "[]"? | ( \( {SimpleDocType} "[]"? ( \| {SimpleDocType} "[]"? )* \)\[\] ))
166*d219b4ceSAdam Hornacek SimpleDocType = {Identifier}
167*d219b4ceSAdam Hornacek 
168*d219b4ceSAdam Hornacek DocParamWithType = "return" | "throws" | "throw" | "var" | "see"  //"see" can take a URL
169*d219b4ceSAdam Hornacek DocParamWithTypeAndName = "param" | "global" | "property" | "property-read"
170*d219b4ceSAdam Hornacek                           | "property-write"
171*d219b4ceSAdam Hornacek DocParamWithName = "uses"
172*d219b4ceSAdam Hornacek DocInlineTags = "internal" | "inheritDoc" | "link" | "example"
173*d219b4ceSAdam Hornacek //method needs special treatment
174*d219b4ceSAdam Hornacek 
175*d219b4ceSAdam Hornacek HtmlNameStart = [a-zA-Z_\u00C0-\u10FFFFFF]
176*d219b4ceSAdam Hornacek HtmlName      = {HtmlNameStart} ({HtmlNameStart} | [\-.0-9\u00B7])*
177*d219b4ceSAdam Hornacek 
178*d219b4ceSAdam Hornacek %state TAG_NAME AFTER_TAG_NAME ATTRIBUTE_NOQUOTE ATTRIBUTE_SINGLE ATTRIBUTE_DOUBLE HTMLCOMMENT
179*d219b4ceSAdam Hornacek %state IN_SCRIPT STRING SCOMMENT HEREDOC NOWDOC COMMENT QSTRING BACKQUOTE STRINGEXPR STRINGVAR
180*d219b4ceSAdam Hornacek %state DOCCOMMENT DOCCOM_TYPE_THEN_NAME DOCCOM_NAME DOCCOM_TYPE
181*d219b4ceSAdam Hornacek 
182*d219b4ceSAdam Hornacek %include ../Common.lexh
183*d219b4ceSAdam Hornacek %include ../CommonURI.lexh
184*d219b4ceSAdam Hornacek %include ../CommonPath.lexh
185*d219b4ceSAdam Hornacek %%
186*d219b4ceSAdam Hornacek <YYINITIAL> { //HTML
187*d219b4ceSAdam Hornacek     "<" | "</"      {
188*d219b4ceSAdam Hornacek         chkLOC();
189*d219b4ceSAdam Hornacek         onNonSymbolMatched(yytext(), yychar);
190*d219b4ceSAdam Hornacek         yypush(TAG_NAME);
191*d219b4ceSAdam Hornacek     }
192*d219b4ceSAdam Hornacek 
193*d219b4ceSAdam Hornacek     "<!--" {
194*d219b4ceSAdam Hornacek         onDisjointSpanChanged(HtmlConsts.COMMENT_CLASS, yychar);
195*d219b4ceSAdam Hornacek         onNonSymbolMatched(yytext(), yychar);
196*d219b4ceSAdam Hornacek         yybegin(HTMLCOMMENT);
197*d219b4ceSAdam Hornacek     }
198*d219b4ceSAdam Hornacek }
199*d219b4ceSAdam Hornacek 
200*d219b4ceSAdam Hornacek <TAG_NAME> {
201*d219b4ceSAdam Hornacek     {HtmlName} {
202*d219b4ceSAdam Hornacek         chkLOC();
203*d219b4ceSAdam Hornacek         String lastClassName = getDisjointSpanClassName();
204*d219b4ceSAdam Hornacek         onDisjointSpanChanged(HtmlConsts.NUMBER_CLASS, yychar);
205*d219b4ceSAdam Hornacek         onNonSymbolMatched(yytext(), yychar);
206*d219b4ceSAdam Hornacek         onDisjointSpanChanged(lastClassName, yychar);
207*d219b4ceSAdam Hornacek         yybegin(AFTER_TAG_NAME);
208*d219b4ceSAdam Hornacek     }
209*d219b4ceSAdam Hornacek 
210*d219b4ceSAdam Hornacek     {HtmlName}:{HtmlName} {
211*d219b4ceSAdam Hornacek         chkLOC();
212*d219b4ceSAdam Hornacek         String lastClassName = getDisjointSpanClassName();
213*d219b4ceSAdam Hornacek         onDisjointSpanChanged(HtmlConsts.NUMBER_CLASS, yychar);
214*d219b4ceSAdam Hornacek         int i = 0;
215*d219b4ceSAdam Hornacek         while (yycharat(i) != ':') i++;
216*d219b4ceSAdam Hornacek         onNonSymbolMatched(yytext().substring(0,i), yychar);
217*d219b4ceSAdam Hornacek         onDisjointSpanChanged(null, yychar);
218*d219b4ceSAdam Hornacek         onNonSymbolMatched(":", yychar);
219*d219b4ceSAdam Hornacek         onDisjointSpanChanged(HtmlConsts.NUMBER_CLASS, yychar);
220*d219b4ceSAdam Hornacek         onNonSymbolMatched(yytext().substring(i + 1), yychar);
221*d219b4ceSAdam Hornacek         onDisjointSpanChanged(lastClassName, yychar);
222*d219b4ceSAdam Hornacek         yybegin(AFTER_TAG_NAME);
223*d219b4ceSAdam Hornacek     }
224*d219b4ceSAdam Hornacek }
225*d219b4ceSAdam Hornacek 
226*d219b4ceSAdam Hornacek <AFTER_TAG_NAME> {
227*d219b4ceSAdam Hornacek     {HtmlName} {
228*d219b4ceSAdam Hornacek         chkLOC();
229*d219b4ceSAdam Hornacek         //attribute
230*d219b4ceSAdam Hornacek         onNonSymbolMatched(yytext(), EmphasisHint.STRONG, yychar);
231*d219b4ceSAdam Hornacek     }
232*d219b4ceSAdam Hornacek 
233*d219b4ceSAdam Hornacek     "=" {WhspChar}* (\" | \')? {
234*d219b4ceSAdam Hornacek         chkLOC();
235*d219b4ceSAdam Hornacek         char attributeDelim = yycharat(yylength()-1);
236*d219b4ceSAdam Hornacek         onNonSymbolMatched("=", yychar);
237*d219b4ceSAdam Hornacek         onDisjointSpanChanged(HtmlConsts.STRING_CLASS, yychar);
238*d219b4ceSAdam Hornacek         onNonSymbolMatched(yytext().substring(1), yychar);
239*d219b4ceSAdam Hornacek         if (attributeDelim == '\'') {
240*d219b4ceSAdam Hornacek             yypush(ATTRIBUTE_SINGLE);
241*d219b4ceSAdam Hornacek         } else if (attributeDelim == '"') {
242*d219b4ceSAdam Hornacek             yypush(ATTRIBUTE_DOUBLE);
243*d219b4ceSAdam Hornacek         } else {
244*d219b4ceSAdam Hornacek             yypush(ATTRIBUTE_NOQUOTE);
245*d219b4ceSAdam Hornacek         }
246*d219b4ceSAdam Hornacek     }
247*d219b4ceSAdam Hornacek }
248*d219b4ceSAdam Hornacek 
249*d219b4ceSAdam Hornacek <TAG_NAME, AFTER_TAG_NAME> {
250*d219b4ceSAdam Hornacek     ">"     {
251*d219b4ceSAdam Hornacek         chkLOC();
252*d219b4ceSAdam Hornacek         onNonSymbolMatched(yytext(), yychar);
253*d219b4ceSAdam Hornacek         yypop(); //to YYINITIAL
254*d219b4ceSAdam Hornacek     }
255*d219b4ceSAdam Hornacek }
256*d219b4ceSAdam Hornacek 
257*d219b4ceSAdam Hornacek <YYINITIAL, TAG_NAME, AFTER_TAG_NAME> {
258*d219b4ceSAdam Hornacek     {OpeningTag}    {
259*d219b4ceSAdam Hornacek         chkLOC();
260*d219b4ceSAdam Hornacek         onNonSymbolMatched(yytext(), EmphasisHint.STRONG, yychar);
261*d219b4ceSAdam Hornacek         yypush(IN_SCRIPT); }
262*d219b4ceSAdam Hornacek }
263*d219b4ceSAdam Hornacek 
264*d219b4ceSAdam Hornacek <ATTRIBUTE_NOQUOTE> {
265*d219b4ceSAdam Hornacek     {WhspChar}* {EOL} {
266*d219b4ceSAdam Hornacek         onDisjointSpanChanged(null, yychar);
267*d219b4ceSAdam Hornacek         onEndOfLineMatched(yytext(), yychar);
268*d219b4ceSAdam Hornacek         yypop();
269*d219b4ceSAdam Hornacek     }
270*d219b4ceSAdam Hornacek     {WhspChar}+   {
271*d219b4ceSAdam Hornacek         onNonSymbolMatched(yytext(), yychar);
272*d219b4ceSAdam Hornacek         onDisjointSpanChanged(null, yychar);
273*d219b4ceSAdam Hornacek         yypop();
274*d219b4ceSAdam Hornacek     }
275*d219b4ceSAdam Hornacek     ">"     {
276*d219b4ceSAdam Hornacek         chkLOC();
277*d219b4ceSAdam Hornacek         onNonSymbolMatched(yytext(), yychar);
278*d219b4ceSAdam Hornacek         onDisjointSpanChanged(null, yychar);
279*d219b4ceSAdam Hornacek         //pop twice
280*d219b4ceSAdam Hornacek         yypop();
281*d219b4ceSAdam Hornacek         yypop();
282*d219b4ceSAdam Hornacek     }
283*d219b4ceSAdam Hornacek }
284*d219b4ceSAdam Hornacek 
285*d219b4ceSAdam Hornacek <ATTRIBUTE_DOUBLE>\" {
286*d219b4ceSAdam Hornacek     chkLOC();
287*d219b4ceSAdam Hornacek     onNonSymbolMatched(yytext(), yychar);
288*d219b4ceSAdam Hornacek     onDisjointSpanChanged(null, yychar); yypop();
289*d219b4ceSAdam Hornacek }
290*d219b4ceSAdam Hornacek <ATTRIBUTE_SINGLE>\' {
291*d219b4ceSAdam Hornacek     chkLOC();
292*d219b4ceSAdam Hornacek     onNonSymbolMatched(yytext(), yychar);
293*d219b4ceSAdam Hornacek     onDisjointSpanChanged(null, yychar); yypop();
294*d219b4ceSAdam Hornacek }
295*d219b4ceSAdam Hornacek 
296*d219b4ceSAdam Hornacek <ATTRIBUTE_DOUBLE, ATTRIBUTE_SINGLE> {
297*d219b4ceSAdam Hornacek     {WhspChar}* {EOL} {
298*d219b4ceSAdam Hornacek         onDisjointSpanChanged(null, yychar);
299*d219b4ceSAdam Hornacek         onEndOfLineMatched(yytext(), yychar);
300*d219b4ceSAdam Hornacek         onDisjointSpanChanged(HtmlConsts.STRING_CLASS, yychar);
301*d219b4ceSAdam Hornacek     }
302*d219b4ceSAdam Hornacek }
303*d219b4ceSAdam Hornacek 
304*d219b4ceSAdam Hornacek <ATTRIBUTE_NOQUOTE, ATTRIBUTE_DOUBLE, ATTRIBUTE_SINGLE> {
305*d219b4ceSAdam Hornacek     {OpeningTag} {
306*d219b4ceSAdam Hornacek         chkLOC();
307*d219b4ceSAdam Hornacek         onDisjointSpanChanged(null, yychar);
308*d219b4ceSAdam Hornacek         onNonSymbolMatched(yytext(), EmphasisHint.STRONG, yychar);
309*d219b4ceSAdam Hornacek         yypush(IN_SCRIPT, HtmlConsts.STRING_CLASS);
310*d219b4ceSAdam Hornacek     }
311*d219b4ceSAdam Hornacek }
312*d219b4ceSAdam Hornacek 
313*d219b4ceSAdam Hornacek <HTMLCOMMENT> {
314*d219b4ceSAdam Hornacek     "-->" {
315*d219b4ceSAdam Hornacek         onNonSymbolMatched(yytext(), yychar);
316*d219b4ceSAdam Hornacek         onDisjointSpanChanged(null, yychar);
317*d219b4ceSAdam Hornacek         yybegin(YYINITIAL);
318*d219b4ceSAdam Hornacek     }
319*d219b4ceSAdam Hornacek 
320*d219b4ceSAdam Hornacek     {WhspChar}* {EOL} {
321*d219b4ceSAdam Hornacek         onDisjointSpanChanged(null, yychar);
322*d219b4ceSAdam Hornacek         onEndOfLineMatched(yytext(), yychar);
323*d219b4ceSAdam Hornacek         onDisjointSpanChanged(HtmlConsts.COMMENT_CLASS, yychar);
324*d219b4ceSAdam Hornacek     }
325*d219b4ceSAdam Hornacek 
326*d219b4ceSAdam Hornacek     {OpeningTag} {
327*d219b4ceSAdam Hornacek         onDisjointSpanChanged(null, yychar);
328*d219b4ceSAdam Hornacek         onNonSymbolMatched(yytext(), EmphasisHint.STRONG, yychar);
329*d219b4ceSAdam Hornacek         yypush(IN_SCRIPT, HtmlConsts.COMMENT_CLASS);
330*d219b4ceSAdam Hornacek     }
331*d219b4ceSAdam Hornacek }
332*d219b4ceSAdam Hornacek 
333*d219b4ceSAdam Hornacek <IN_SCRIPT> {
334*d219b4ceSAdam Hornacek     "$" {Identifier} {
335*d219b4ceSAdam Hornacek         chkLOC();
336*d219b4ceSAdam Hornacek         //we ignore keywords if the identifier starts with one of variable chars
337*d219b4ceSAdam Hornacek         String id = yytext().substring(1);
338*d219b4ceSAdam Hornacek         onNonSymbolMatched("$", yychar);
339*d219b4ceSAdam Hornacek         onFilteredSymbolMatched(id, yychar, null);
340*d219b4ceSAdam Hornacek     }
341*d219b4ceSAdam Hornacek 
342*d219b4ceSAdam Hornacek     {Identifier} {
343*d219b4ceSAdam Hornacek         chkLOC();
344*d219b4ceSAdam Hornacek         onFilteredSymbolMatched(yytext(), yychar, Consts.kwd);
345*d219b4ceSAdam Hornacek     }
346*d219b4ceSAdam Hornacek 
347*d219b4ceSAdam Hornacek     \( {WhspChar}* {CastTypes} {WhspChar}* \) {
348*d219b4ceSAdam Hornacek         chkLOC();
349*d219b4ceSAdam Hornacek         onNonSymbolMatched("(", yychar);
350*d219b4ceSAdam Hornacek         int i = 1, j;
351*d219b4ceSAdam Hornacek         while (isTabOrSpace(i)) { onNonSymbolMatched(yycharat(i++), yychar); }
352*d219b4ceSAdam Hornacek 
353*d219b4ceSAdam Hornacek         j = i + 1;
354*d219b4ceSAdam Hornacek         while (!isTabOrSpace(j) && yycharat(j) != ')') { j++; }
355*d219b4ceSAdam Hornacek         onNonSymbolMatched(yytext().substring(i, j), EmphasisHint.EM, yychar);
356*d219b4ceSAdam Hornacek 
357*d219b4ceSAdam Hornacek         onNonSymbolMatched(yytext().substring(j, yylength()), yychar);
358*d219b4ceSAdam Hornacek     }
359*d219b4ceSAdam Hornacek 
360*d219b4ceSAdam Hornacek     b? \" {
361*d219b4ceSAdam Hornacek         chkLOC();
362*d219b4ceSAdam Hornacek         yypush(STRING);
363*d219b4ceSAdam Hornacek         if (yycharat(0) == 'b') { onNonSymbolMatched('b', yychar); }
364*d219b4ceSAdam Hornacek         onDisjointSpanChanged(HtmlConsts.STRING_CLASS, yychar);
365*d219b4ceSAdam Hornacek         onNonSymbolMatched("\"", yychar);
366*d219b4ceSAdam Hornacek     }
367*d219b4ceSAdam Hornacek 
368*d219b4ceSAdam Hornacek     b? \' {
369*d219b4ceSAdam Hornacek         chkLOC();
370*d219b4ceSAdam Hornacek         yypush(QSTRING);
371*d219b4ceSAdam Hornacek         if (yycharat(0) == 'b') { onNonSymbolMatched('b', yychar); }
372*d219b4ceSAdam Hornacek         onDisjointSpanChanged(HtmlConsts.STRING_CLASS, yychar);
373*d219b4ceSAdam Hornacek         onNonSymbolMatched("\'", yychar);
374*d219b4ceSAdam Hornacek     }
375*d219b4ceSAdam Hornacek 
376*d219b4ceSAdam Hornacek     [`]    {
377*d219b4ceSAdam Hornacek         chkLOC();
378*d219b4ceSAdam Hornacek         yypush(BACKQUOTE);
379*d219b4ceSAdam Hornacek         onDisjointSpanChanged(HtmlConsts.STRING_CLASS, yychar);
380*d219b4ceSAdam Hornacek         onNonSymbolMatched(yytext(), yychar);
381*d219b4ceSAdam Hornacek     }
382*d219b4ceSAdam Hornacek 
383*d219b4ceSAdam Hornacek     b? "<<<" {WhspChar}* ({Identifier} | (\'{Identifier}\') | (\"{Identifier}\")){EOL} {
384*d219b4ceSAdam Hornacek         chkLOC();
385*d219b4ceSAdam Hornacek         if (yycharat(0) == 'b') { onNonSymbolMatched('b', yychar); }
386*d219b4ceSAdam Hornacek         onNonSymbolMatched("<<<", yychar);
387*d219b4ceSAdam Hornacek         int i = yycharat(0) == 'b' ? 4 : 3, j = yylength()-1;
388*d219b4ceSAdam Hornacek         while (isTabOrSpace(i)) {
389*d219b4ceSAdam Hornacek             onNonSymbolMatched(yycharat(i++), yychar);
390*d219b4ceSAdam Hornacek         }
391*d219b4ceSAdam Hornacek         while (yycharat(j) == '\n' || yycharat(j) == '\r') { j--; }
392*d219b4ceSAdam Hornacek 
393*d219b4ceSAdam Hornacek         if (yycharat(i) == '\'' || yycharat(i) == '"') {
394*d219b4ceSAdam Hornacek             yypush(NOWDOC);
395*d219b4ceSAdam Hornacek             String text = yytext().substring(i+1, j);
396*d219b4ceSAdam Hornacek             this.docLabels.push(text);
397*d219b4ceSAdam Hornacek             onNonSymbolMatched(String.valueOf(yycharat(i)), yychar);
398*d219b4ceSAdam Hornacek             onDisjointSpanChanged(HtmlConsts.BOLD_CLASS, yychar);
399*d219b4ceSAdam Hornacek             onNonSymbolMatched(text, yychar);
400*d219b4ceSAdam Hornacek             onDisjointSpanChanged(null, yychar);
401*d219b4ceSAdam Hornacek             onNonSymbolMatched(String.valueOf(yycharat(i)), yychar);
402*d219b4ceSAdam Hornacek         } else {
403*d219b4ceSAdam Hornacek             yypush(HEREDOC);
404*d219b4ceSAdam Hornacek             String text = yytext().substring(i, j+1);
405*d219b4ceSAdam Hornacek             this.docLabels.push(text);
406*d219b4ceSAdam Hornacek             onDisjointSpanChanged(HtmlConsts.BOLD_CLASS, yychar);
407*d219b4ceSAdam Hornacek             onNonSymbolMatched(text, yychar);
408*d219b4ceSAdam Hornacek             onDisjointSpanChanged(null, yychar);
409*d219b4ceSAdam Hornacek         }
410*d219b4ceSAdam Hornacek         onEndOfLineMatched(yytext(), yychar);
411*d219b4ceSAdam Hornacek         onDisjointSpanChanged(HtmlConsts.STRING_CLASS, yychar);
412*d219b4ceSAdam Hornacek     }
413*d219b4ceSAdam Hornacek 
414*d219b4ceSAdam Hornacek     {Number}   {
415*d219b4ceSAdam Hornacek         chkLOC();
416*d219b4ceSAdam Hornacek         String lastClassName = getDisjointSpanClassName();
417*d219b4ceSAdam Hornacek         onDisjointSpanChanged(HtmlConsts.NUMBER_CLASS, yychar);
418*d219b4ceSAdam Hornacek         onNonSymbolMatched(yytext(), yychar);
419*d219b4ceSAdam Hornacek         onDisjointSpanChanged(lastClassName, yychar);
420*d219b4ceSAdam Hornacek     }
421*d219b4ceSAdam Hornacek 
422*d219b4ceSAdam Hornacek     "#"|"//"   {
423*d219b4ceSAdam Hornacek         yypush(SCOMMENT);
424*d219b4ceSAdam Hornacek         onDisjointSpanChanged(HtmlConsts.COMMENT_CLASS, yychar);
425*d219b4ceSAdam Hornacek         onNonSymbolMatched(yytext(), yychar);
426*d219b4ceSAdam Hornacek     }
427*d219b4ceSAdam Hornacek     "/**"      {
428*d219b4ceSAdam Hornacek         yypush(DOCCOMMENT);
429*d219b4ceSAdam Hornacek         onDisjointSpanChanged(HtmlConsts.COMMENT_CLASS, yychar);
430*d219b4ceSAdam Hornacek         onNonSymbolMatched("/*", yychar);
431*d219b4ceSAdam Hornacek         yypushback(1);
432*d219b4ceSAdam Hornacek     }
433*d219b4ceSAdam Hornacek     "/*"       {
434*d219b4ceSAdam Hornacek         yypush(COMMENT);
435*d219b4ceSAdam Hornacek         onDisjointSpanChanged(HtmlConsts.COMMENT_CLASS, yychar);
436*d219b4ceSAdam Hornacek         onNonSymbolMatched(yytext(), yychar);
437*d219b4ceSAdam Hornacek     }
438*d219b4ceSAdam Hornacek 
439*d219b4ceSAdam Hornacek     \{         {
440*d219b4ceSAdam Hornacek         chkLOC();
441*d219b4ceSAdam Hornacek         onNonSymbolMatched(yytext(), yychar);
442*d219b4ceSAdam Hornacek         yypush(IN_SCRIPT);
443*d219b4ceSAdam Hornacek     }
444*d219b4ceSAdam Hornacek     \}         {
445*d219b4ceSAdam Hornacek         chkLOC();
446*d219b4ceSAdam Hornacek         onNonSymbolMatched(yytext(), yychar);
447*d219b4ceSAdam Hornacek         if (!this.stack.empty() && !isHtmlState(this.stack.peek()))
448*d219b4ceSAdam Hornacek             yypop(); //may pop STRINGEXPR/HEREDOC/BACKQUOTE
449*d219b4ceSAdam Hornacek         /* we don't pop unconditionally because we can exit a ?php block with
450*d219b4ceSAdam Hornacek          * with open braces and we discard the information about the number of
451*d219b4ceSAdam Hornacek          * open braces when exiting the block (see the action for {ClosingTag}
452*d219b4ceSAdam Hornacek          * below. An alternative would be keeping two stacks -- one for HTML
453*d219b4ceSAdam Hornacek          * and another for PHP. The PHP scanner only needs one stack because
454*d219b4ceSAdam Hornacek          * it doesn't need to keep state about the HTML */
455*d219b4ceSAdam Hornacek     }
456*d219b4ceSAdam Hornacek 
457*d219b4ceSAdam Hornacek     {ClosingTag} {
458*d219b4ceSAdam Hornacek         chkLOC();
459*d219b4ceSAdam Hornacek         onNonSymbolMatched(yytext(), EmphasisHint.STRONG, yychar);
460*d219b4ceSAdam Hornacek         while (!isHtmlState(yystate()))
461*d219b4ceSAdam Hornacek             yypop();
462*d219b4ceSAdam Hornacek     }
463*d219b4ceSAdam Hornacek } //end of IN_SCRIPT
464*d219b4ceSAdam Hornacek 
465*d219b4ceSAdam Hornacek <STRING> {
466*d219b4ceSAdam Hornacek     \\\"    {
467*d219b4ceSAdam Hornacek         chkLOC();
468*d219b4ceSAdam Hornacek         onNonSymbolMatched(yytext(), EmphasisHint.STRONG, yychar);
469*d219b4ceSAdam Hornacek     }
470*d219b4ceSAdam Hornacek     \"    {
471*d219b4ceSAdam Hornacek         chkLOC();
472*d219b4ceSAdam Hornacek         onNonSymbolMatched(yytext(), yychar);
473*d219b4ceSAdam Hornacek         onDisjointSpanChanged(null, yychar); yypop();
474*d219b4ceSAdam Hornacek     }
475*d219b4ceSAdam Hornacek }
476*d219b4ceSAdam Hornacek 
477*d219b4ceSAdam Hornacek <BACKQUOTE> {
478*d219b4ceSAdam Hornacek     "\\`"    {
479*d219b4ceSAdam Hornacek         chkLOC();
480*d219b4ceSAdam Hornacek         onNonSymbolMatched(yytext(), EmphasisHint.STRONG, yychar);
481*d219b4ceSAdam Hornacek     }
482*d219b4ceSAdam Hornacek     "`"    {
483*d219b4ceSAdam Hornacek         chkLOC();
484*d219b4ceSAdam Hornacek         onNonSymbolMatched("`", yychar);
485*d219b4ceSAdam Hornacek         onDisjointSpanChanged(null, yychar); yypop();
486*d219b4ceSAdam Hornacek     }
487*d219b4ceSAdam Hornacek }
488*d219b4ceSAdam Hornacek 
489*d219b4ceSAdam Hornacek <STRING, BACKQUOTE, HEREDOC> {
490*d219b4ceSAdam Hornacek     "\\{" {
491*d219b4ceSAdam Hornacek         chkLOC();
492*d219b4ceSAdam Hornacek         onNonSymbolMatched(yytext(), yychar);
493*d219b4ceSAdam Hornacek     }
494*d219b4ceSAdam Hornacek 
495*d219b4ceSAdam Hornacek     {DoubleQuoteEscapeSequences} {
496*d219b4ceSAdam Hornacek         chkLOC();
497*d219b4ceSAdam Hornacek         onNonSymbolMatched(yytext(), EmphasisHint.STRONG, yychar);
498*d219b4ceSAdam Hornacek     }
499*d219b4ceSAdam Hornacek 
500*d219b4ceSAdam Hornacek     "$"     {
501*d219b4ceSAdam Hornacek         chkLOC();
502*d219b4ceSAdam Hornacek         onDisjointSpanChanged(null, yychar);
503*d219b4ceSAdam Hornacek         onNonSymbolMatched("$", yychar);
504*d219b4ceSAdam Hornacek         yypush(STRINGVAR, HtmlConsts.STRING_CLASS);
505*d219b4ceSAdam Hornacek     }
506*d219b4ceSAdam Hornacek 
507*d219b4ceSAdam Hornacek     "${" {
508*d219b4ceSAdam Hornacek         chkLOC();
509*d219b4ceSAdam Hornacek         onDisjointSpanChanged(null, yychar);
510*d219b4ceSAdam Hornacek         onNonSymbolMatched(yytext(), yychar);
511*d219b4ceSAdam Hornacek         yypush(STRINGEXPR, HtmlConsts.STRING_CLASS);
512*d219b4ceSAdam Hornacek     }
513*d219b4ceSAdam Hornacek 
514*d219b4ceSAdam Hornacek     /* ${ is different from {$ -- for instance {$foo->bar[1]} is valid
515*d219b4ceSAdam Hornacek      * but ${foo->bar[1]} is not. ${ only enters the full blown scripting state
516*d219b4ceSAdam Hornacek      * when {Identifer}[ is found (see the PHP scanner). Tthe parser seems to
517*d219b4ceSAdam Hornacek      * put more restrictions on the {$ scripting mode than on the
518*d219b4ceSAdam Hornacek      * "${" {Identifer} "[" scripting mode, but that's not relevant here */
519*d219b4ceSAdam Hornacek     "{$" {
520*d219b4ceSAdam Hornacek         chkLOC();
521*d219b4ceSAdam Hornacek         onDisjointSpanChanged(null, yychar);
522*d219b4ceSAdam Hornacek         onNonSymbolMatched("{", yychar);
523*d219b4ceSAdam Hornacek         yypushback(1);
524*d219b4ceSAdam Hornacek         yypush(IN_SCRIPT, HtmlConsts.STRING_CLASS);
525*d219b4ceSAdam Hornacek     }
526*d219b4ceSAdam Hornacek }
527*d219b4ceSAdam Hornacek 
528*d219b4ceSAdam Hornacek <QSTRING> {
529*d219b4ceSAdam Hornacek     {SingleQuoteEscapeSequences} {
530*d219b4ceSAdam Hornacek         chkLOC();
531*d219b4ceSAdam Hornacek         onNonSymbolMatched(yytext(), EmphasisHint.STRONG, yychar);
532*d219b4ceSAdam Hornacek     }
533*d219b4ceSAdam Hornacek 
534*d219b4ceSAdam Hornacek     \'      {
535*d219b4ceSAdam Hornacek         chkLOC();
536*d219b4ceSAdam Hornacek         onNonSymbolMatched("'", yychar);
537*d219b4ceSAdam Hornacek         onDisjointSpanChanged(null, yychar); yypop();
538*d219b4ceSAdam Hornacek     }
539*d219b4ceSAdam Hornacek }
540*d219b4ceSAdam Hornacek 
541*d219b4ceSAdam Hornacek <HEREDOC, NOWDOC>^{Identifier} ";"? {EOL}  {
542*d219b4ceSAdam Hornacek     chkLOC();
543*d219b4ceSAdam Hornacek     int i = yylength() - 1;
544*d219b4ceSAdam Hornacek     boolean hasSemi = false;
545*d219b4ceSAdam Hornacek     while (yycharat(i) == '\n' || yycharat(i) == '\r') { i--; }
546*d219b4ceSAdam Hornacek     if (yycharat(i) == ';') { hasSemi = true; i--; }
547*d219b4ceSAdam Hornacek     if (yytext().substring(0, i+1).equals(this.docLabels.peek())) {
548*d219b4ceSAdam Hornacek         String text = this.docLabels.pop();
549*d219b4ceSAdam Hornacek         yypop();
550*d219b4ceSAdam Hornacek         onDisjointSpanChanged(HtmlConsts.BOLD_CLASS, yychar);
551*d219b4ceSAdam Hornacek         onNonSymbolMatched(text, yychar);
552*d219b4ceSAdam Hornacek         onDisjointSpanChanged(null, yychar);
553*d219b4ceSAdam Hornacek         if (hasSemi) onNonSymbolMatched(";", yychar);
554*d219b4ceSAdam Hornacek         onEndOfLineMatched(yytext(), yychar);
555*d219b4ceSAdam Hornacek     } else {
556*d219b4ceSAdam Hornacek         onNonSymbolMatched(yytext().substring(0,i+1), yychar);
557*d219b4ceSAdam Hornacek         if (hasSemi) onNonSymbolMatched(";", yychar);
558*d219b4ceSAdam Hornacek         onEndOfLineMatched(yytext(), yychar);
559*d219b4ceSAdam Hornacek     }
560*d219b4ceSAdam Hornacek }
561*d219b4ceSAdam Hornacek 
562*d219b4ceSAdam Hornacek <STRING, QSTRING, BACKQUOTE, HEREDOC, NOWDOC>{WhspChar}* {EOL} {
563*d219b4ceSAdam Hornacek     onDisjointSpanChanged(null, yychar);
564*d219b4ceSAdam Hornacek     onEndOfLineMatched(yytext(), yychar);
565*d219b4ceSAdam Hornacek     onDisjointSpanChanged(HtmlConsts.STRING_CLASS, yychar);
566*d219b4ceSAdam Hornacek }
567*d219b4ceSAdam Hornacek 
568*d219b4ceSAdam Hornacek <STRINGVAR> {
569*d219b4ceSAdam Hornacek     {Identifier}    {
570*d219b4ceSAdam Hornacek         chkLOC();
571*d219b4ceSAdam Hornacek         onFilteredSymbolMatched(yytext(), yychar, null);
572*d219b4ceSAdam Hornacek     }
573*d219b4ceSAdam Hornacek 
574*d219b4ceSAdam Hornacek     \[ {Number} \] {
575*d219b4ceSAdam Hornacek         chkLOC();
576*d219b4ceSAdam Hornacek         onNonSymbolMatched("[", yychar);
577*d219b4ceSAdam Hornacek         String lastClassName = getDisjointSpanClassName();
578*d219b4ceSAdam Hornacek         onDisjointSpanChanged(HtmlConsts.NUMBER_CLASS, yychar);
579*d219b4ceSAdam Hornacek         onNonSymbolMatched(yytext().substring(1, yylength()-1), yychar);
580*d219b4ceSAdam Hornacek         onDisjointSpanChanged(lastClassName, yychar);
581*d219b4ceSAdam Hornacek         onNonSymbolMatched("]", yychar);
582*d219b4ceSAdam Hornacek         yypop(); //because "$arr[0][1]" is the same as $arr[0] . "[1]"
583*d219b4ceSAdam Hornacek     }
584*d219b4ceSAdam Hornacek 
585*d219b4ceSAdam Hornacek     \[ {Identifier} \] {
586*d219b4ceSAdam Hornacek         chkLOC();
587*d219b4ceSAdam Hornacek         //then the identifier is actually a string!
588*d219b4ceSAdam Hornacek         onNonSymbolMatched("[", yychar);
589*d219b4ceSAdam Hornacek         String lastClassName = getDisjointSpanClassName();
590*d219b4ceSAdam Hornacek         onDisjointSpanChanged(HtmlConsts.STRING_CLASS, yychar);
591*d219b4ceSAdam Hornacek         onNonSymbolMatched(yytext().substring(1, yylength()-1), yychar);
592*d219b4ceSAdam Hornacek         onDisjointSpanChanged(lastClassName, yychar);
593*d219b4ceSAdam Hornacek         onNonSymbolMatched("]", yychar);
594*d219b4ceSAdam Hornacek         yypop();
595*d219b4ceSAdam Hornacek     }
596*d219b4ceSAdam Hornacek 
597*d219b4ceSAdam Hornacek     \[ "$" {Identifier} \] {
598*d219b4ceSAdam Hornacek         chkLOC();
599*d219b4ceSAdam Hornacek         onNonSymbolMatched("[$", yychar);
600*d219b4ceSAdam Hornacek         onFilteredSymbolMatched(yytext().substring(2, yylength()-1), yychar, null);
601*d219b4ceSAdam Hornacek         onNonSymbolMatched("]", yychar);
602*d219b4ceSAdam Hornacek         yypop();
603*d219b4ceSAdam Hornacek     }
604*d219b4ceSAdam Hornacek 
605*d219b4ceSAdam Hornacek     "->" {Identifier} {
606*d219b4ceSAdam Hornacek         chkLOC();
607*d219b4ceSAdam Hornacek         onNonSymbolMatched(yytext().substring(0, 2), yychar);
608*d219b4ceSAdam Hornacek         onFilteredSymbolMatched(yytext().substring(2), yychar, null);
609*d219b4ceSAdam Hornacek         yypop(); //because "$arr->a[0]" is the same as $arr->a . "[0]"
610*d219b4ceSAdam Hornacek     }
611*d219b4ceSAdam Hornacek 
612*d219b4ceSAdam Hornacek     [^]          { yypushback(1); yypop(); }
613*d219b4ceSAdam Hornacek }
614*d219b4ceSAdam Hornacek 
615*d219b4ceSAdam Hornacek <STRINGEXPR> {
616*d219b4ceSAdam Hornacek     {Identifier} {
617*d219b4ceSAdam Hornacek         chkLOC();
618*d219b4ceSAdam Hornacek         onFilteredSymbolMatched(yytext(), yychar, null);
619*d219b4ceSAdam Hornacek     }
620*d219b4ceSAdam Hornacek     \}  { chkLOC(); onNonSymbolMatched('}', yychar); yypop(); }
621*d219b4ceSAdam Hornacek     \[  { chkLOC(); onNonSymbolMatched('[', yychar); yybegin(IN_SCRIPT); } /* don't push. when we find '}'
622*d219b4ceSAdam Hornacek                                                  * and we pop we want to go to
623*d219b4ceSAdam Hornacek                                                  * STRING/HEREDOC, not back to
624*d219b4ceSAdam Hornacek                                                  * STRINGEXPR */
625*d219b4ceSAdam Hornacek }
626*d219b4ceSAdam Hornacek 
627*d219b4ceSAdam Hornacek <SCOMMENT> {
628*d219b4ceSAdam Hornacek     {ClosingTag}    {
629*d219b4ceSAdam Hornacek         onDisjointSpanChanged(null, yychar);
630*d219b4ceSAdam Hornacek         onNonSymbolMatched(yytext(), EmphasisHint.STRONG, yychar);
631*d219b4ceSAdam Hornacek         while (!isHtmlState(yystate()))
632*d219b4ceSAdam Hornacek             yypop();
633*d219b4ceSAdam Hornacek     }
634*d219b4ceSAdam Hornacek     {WhspChar}* {EOL} {
635*d219b4ceSAdam Hornacek         onDisjointSpanChanged(null, yychar);
636*d219b4ceSAdam Hornacek         onEndOfLineMatched(yytext(), yychar);
637*d219b4ceSAdam Hornacek         yypop();
638*d219b4ceSAdam Hornacek     }
639*d219b4ceSAdam Hornacek }
640*d219b4ceSAdam Hornacek 
641*d219b4ceSAdam Hornacek <DOCCOMMENT> {
642*d219b4ceSAdam Hornacek     {DocPreviousChar} "@" {DocParamWithType} {
643*d219b4ceSAdam Hornacek         writeDocTag(); yybegin(DOCCOM_TYPE);
644*d219b4ceSAdam Hornacek     }
645*d219b4ceSAdam Hornacek 
646*d219b4ceSAdam Hornacek     {DocPreviousChar} "@" {DocParamWithTypeAndName} {
647*d219b4ceSAdam Hornacek         writeDocTag(); yybegin(DOCCOM_TYPE_THEN_NAME);
648*d219b4ceSAdam Hornacek     }
649*d219b4ceSAdam Hornacek 
650*d219b4ceSAdam Hornacek     {DocPreviousChar} "@" {DocParamWithName} {
651*d219b4ceSAdam Hornacek         writeDocTag(); yybegin(DOCCOM_NAME);
652*d219b4ceSAdam Hornacek     }
653*d219b4ceSAdam Hornacek 
654*d219b4ceSAdam Hornacek     ("{@" {DocInlineTags}) | {DocPreviousChar} "@" {Identifier} {
655*d219b4ceSAdam Hornacek         writeDocTag();
656*d219b4ceSAdam Hornacek     }
657*d219b4ceSAdam Hornacek }
658*d219b4ceSAdam Hornacek 
659*d219b4ceSAdam Hornacek <DOCCOM_TYPE_THEN_NAME, DOCCOM_TYPE> {
660*d219b4ceSAdam Hornacek     {WhspChar}+ {DocType} {
661*d219b4ceSAdam Hornacek         int i = 0;
662*d219b4ceSAdam Hornacek         do { onNonSymbolMatched(yycharat(i++), yychar); } while (isTabOrSpace(i));
663*d219b4ceSAdam Hornacek         int j = i;
664*d219b4ceSAdam Hornacek         while (i < yylength()) {
665*d219b4ceSAdam Hornacek             //skip over [], |, ( and )
666*d219b4ceSAdam Hornacek             char c;
667*d219b4ceSAdam Hornacek             while (i < yylength() && ((c = yycharat(i)) == '[' || c == ']'
668*d219b4ceSAdam Hornacek                     || c == '|' || c == '(' || c == ')')) {
669*d219b4ceSAdam Hornacek                 onNonSymbolMatched(c, yychar);
670*d219b4ceSAdam Hornacek                 i++;
671*d219b4ceSAdam Hornacek             }
672*d219b4ceSAdam Hornacek             j = i;
673*d219b4ceSAdam Hornacek             while (j < yylength() && (c = yycharat(j)) != ')' && c != '|'
674*d219b4ceSAdam Hornacek             && c != '[') { j++; }
675*d219b4ceSAdam Hornacek             onFilteredSymbolMatched(yytext().substring(i, j), yychar,
676*d219b4ceSAdam Hornacek                     PSEUDO_TYPES, false);
677*d219b4ceSAdam Hornacek             i = j;
678*d219b4ceSAdam Hornacek         }
679*d219b4ceSAdam Hornacek         yybegin(yystate() == DOCCOM_TYPE_THEN_NAME ? DOCCOM_NAME : DOCCOMMENT);
680*d219b4ceSAdam Hornacek     }
681*d219b4ceSAdam Hornacek 
682*d219b4ceSAdam Hornacek     [^] { yybegin(DOCCOMMENT); yypushback(1); }
683*d219b4ceSAdam Hornacek }
684*d219b4ceSAdam Hornacek 
685*d219b4ceSAdam Hornacek <DOCCOM_NAME> {
686*d219b4ceSAdam Hornacek     {WhspChar}+ "$" {Identifier} {
687*d219b4ceSAdam Hornacek         int i = 0;
688*d219b4ceSAdam Hornacek         do { onNonSymbolMatched(yycharat(i++), yychar); } while (isTabOrSpace(i));
689*d219b4ceSAdam Hornacek 
690*d219b4ceSAdam Hornacek         onNonSymbolMatched("$", yychar);
691*d219b4ceSAdam Hornacek         onFilteredSymbolMatched(yytext().substring(i + 1), yychar, null);
692*d219b4ceSAdam Hornacek         yybegin(DOCCOMMENT);
693*d219b4ceSAdam Hornacek     }
694*d219b4ceSAdam Hornacek 
695*d219b4ceSAdam Hornacek     [^] { yybegin(DOCCOMMENT); yypushback(1); }
696*d219b4ceSAdam Hornacek }
697*d219b4ceSAdam Hornacek 
698*d219b4ceSAdam Hornacek <COMMENT, DOCCOMMENT> {
699*d219b4ceSAdam Hornacek     {WhspChar}* {EOL} {
700*d219b4ceSAdam Hornacek         onDisjointSpanChanged(null, yychar);
701*d219b4ceSAdam Hornacek         onEndOfLineMatched(yytext(), yychar);
702*d219b4ceSAdam Hornacek         onDisjointSpanChanged(HtmlConsts.COMMENT_CLASS, yychar);
703*d219b4ceSAdam Hornacek     }
704*d219b4ceSAdam Hornacek     "*/"    {
705*d219b4ceSAdam Hornacek         onNonSymbolMatched(yytext(), yychar);
706*d219b4ceSAdam Hornacek         onDisjointSpanChanged(null, yychar);
707*d219b4ceSAdam Hornacek         yypop();
708*d219b4ceSAdam Hornacek     }
709*d219b4ceSAdam Hornacek }
710*d219b4ceSAdam Hornacek 
711*d219b4ceSAdam Hornacek <YYINITIAL, TAG_NAME, AFTER_TAG_NAME, ATTRIBUTE_NOQUOTE, ATTRIBUTE_DOUBLE,
712*d219b4ceSAdam Hornacek     ATTRIBUTE_SINGLE, HTMLCOMMENT, IN_SCRIPT, STRING, QSTRING, BACKQUOTE,
713*d219b4ceSAdam Hornacek     HEREDOC, NOWDOC, SCOMMENT, COMMENT, DOCCOMMENT, STRINGEXPR, STRINGVAR> {
714*d219b4ceSAdam Hornacek 
715*d219b4ceSAdam Hornacek     {WhspChar}* {EOL} {
716*d219b4ceSAdam Hornacek         onEndOfLineMatched(yytext(), yychar);
717*d219b4ceSAdam Hornacek     }
718*d219b4ceSAdam Hornacek     [[\s]--[\n]]    { onNonSymbolMatched(yytext(), yychar); }
719*d219b4ceSAdam Hornacek     [^\n]    { chkLOC(); onNonSymbolMatched(yytext(), yychar); }
720*d219b4ceSAdam Hornacek }
721*d219b4ceSAdam Hornacek 
722*d219b4ceSAdam Hornacek <YYINITIAL, HTMLCOMMENT, SCOMMENT, COMMENT, DOCCOMMENT, STRING, QSTRING, BACKQUOTE, HEREDOC, NOWDOC> {
723*d219b4ceSAdam Hornacek     {FPath}
724*d219b4ceSAdam Hornacek             { chkLOC(); onPathlikeMatched(yytext(), '/', false, yychar); }
725*d219b4ceSAdam Hornacek 
726*d219b4ceSAdam Hornacek     {File}
727*d219b4ceSAdam Hornacek             {
728*d219b4ceSAdam Hornacek             chkLOC();
729*d219b4ceSAdam Hornacek             String path = yytext();
730*d219b4ceSAdam Hornacek             onFilelikeMatched(path, yychar);
731*d219b4ceSAdam Hornacek     }
732*d219b4ceSAdam Hornacek 
733*d219b4ceSAdam Hornacek     {BrowseableURI}    {
734*d219b4ceSAdam Hornacek               chkLOC();
735*d219b4ceSAdam Hornacek               onUriMatched(yytext(), yychar);
736*d219b4ceSAdam Hornacek             }
737*d219b4ceSAdam Hornacek 
738*d219b4ceSAdam Hornacek     {FNameChar}+ "@" {FNameChar}+ "." {FNameChar}+
739*d219b4ceSAdam Hornacek             {
740*d219b4ceSAdam Hornacek             chkLOC();
741*d219b4ceSAdam Hornacek             onEmailAddressMatched(yytext(), yychar);
742*d219b4ceSAdam Hornacek             }
743*d219b4ceSAdam Hornacek }
744