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