1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * See LICENSE.txt included in this distribution for the specific 9 * language governing permissions and limitations under the License. 10 * 11 * When distributing Covered Code, include this CDDL HEADER in each 12 * file and include the License file at LICENSE.txt. 13 * If applicable, add the following below this CDDL HEADER, with the 14 * fields enclosed by brackets "[]" replaced with your own identifying 15 * information: Portions Copyright [yyyy] [name of copyright owner] 16 * 17 * CDDL HEADER END 18 */ 19 20 /* 21 * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. 22 * Portions Copyright (c) 2017, Chris Fraire <cfraire@me.com>. 23 */ 24 25 package org.opengrok.indexer.analysis.swift; 26 27 import java.io.IOException; 28 import org.opengrok.indexer.analysis.JFlexSymbolMatcher; 29 import org.opengrok.indexer.analysis.ScopeAction; 30 import org.opengrok.indexer.util.StringUtils; 31 import org.opengrok.indexer.web.HtmlConsts; 32 %% 33 %public 34 %class SwiftXref 35 %extends JFlexSymbolMatcher 36 %unicode 37 %int 38 %char 39 %include ../CommonLexer.lexh 40 %include ../CommonXref.lexh 41 %{ 42 /* Must match {WhiteSpace} regex */ 43 private final static String WHITE_SPACE = "[ \\t\\f]+"; 44 45 private int nestedComment; 46 47 @Override reset()48 public void reset() { 49 super.reset(); 50 nestedComment = 0; 51 } 52 53 @Override yypop()54 public void yypop() throws IOException { 55 onDisjointSpanChanged(null, yychar); 56 super.yypop(); 57 } 58 chkLOC()59 protected void chkLOC() { 60 switch (yystate()) { 61 case COMMENT: 62 case SCOMMENT: 63 case SDOC: 64 break; 65 default: 66 phLOC(); 67 break; 68 } 69 } 70 %} 71 72 File = [a-zA-Z]{FNameChar}* "." ([Jj][Aa][Vv][Aa] | 73 [Pp][Rr][Oo][Pp][Ee][Rr][Tt][Ii][Ee][Ss] | [Pp][Rr][Oo][Pp][Ss] | 74 [Xx][Mm][Ll] | [Cc][Oo][Nn][Ff] | [Tt][Xx][Tt] | [Hh][Tt][Mm][Ll]? | 75 [Ii][Nn][Ii] | [Jj][Nn][Ll][Pp] | [Jj][Aa][Dd] | [Dd][Ii][Ff][Ff] | 76 [Pp][Aa][Tt][Cc][Hh]) 77 78 /* TODO support markdown in comments 79 SdocWithClassArg = "@throws" | "@exception" 80 SdocWithParamNameArg = "@param" 81 82 ClassName = "class"{WhiteSpace}({Identifier} ".")* {Identifier} 83 ParamName = {Identifier} | "<" {Identifier} ">" 84 */ 85 86 %state STRING COMMENT SCOMMENT SDOC TSTRING 87 88 %include ../Common.lexh 89 %include ../CommonURI.lexh 90 %include ../CommonPath.lexh 91 %include Swift.lexh 92 %% 93 <YYINITIAL>{ 94 \{ { chkLOC(); onScopeChanged(ScopeAction.INC, yytext(), yychar); } 95 \} { chkLOC(); onScopeChanged(ScopeAction.DEC, yytext(), yychar); } 96 \; { chkLOC(); onScopeChanged(ScopeAction.END, yytext(), yychar); } 97 98 {Identifier} { 99 chkLOC(); 100 String id = yytext(); 101 onFilteredSymbolMatched(id, yychar, Consts.kwd); 102 } 103 104 [`] {Identifier} [`] { 105 chkLOC(); 106 String capture = yytext(); 107 String id = capture.substring(1, capture.length() - 1); 108 onNonSymbolMatched("`", yychar); 109 onFilteredSymbolMatched(id, yychar, null); 110 onNonSymbolMatched("`", yychar); 111 } 112 113 {ImplicitIdentifier} { 114 chkLOC(); 115 onKeywordMatched(yytext(), yychar); 116 } 117 118 "<" ({File}|{FPath}) ">" { 119 chkLOC(); 120 onNonSymbolMatched("<", yychar); 121 String path = yytext(); 122 path = path.substring(1, path.length() - 1); 123 onFilelikeMatched(path, yychar + 1); 124 onNonSymbolMatched(">", yychar + 1 + path.length()); 125 } 126 127 /*{Hier} 128 { onPathlikeMatched(yytext(), '.', false, yychar); } 129 */ 130 {Number} { 131 chkLOC(); 132 onDisjointSpanChanged(HtmlConsts.NUMBER_CLASS, yychar); 133 onNonSymbolMatched(yytext(), yychar); 134 onDisjointSpanChanged(null, yychar); 135 } 136 137 \" { 138 chkLOC(); 139 yypush(STRING); 140 onDisjointSpanChanged(HtmlConsts.STRING_CLASS, yychar); 141 onNonSymbolMatched(yytext(), yychar); 142 } 143 \"\"\" { 144 chkLOC(); 145 yypush(TSTRING); 146 onDisjointSpanChanged(HtmlConsts.STRING_CLASS, yychar); 147 onNonSymbolMatched(yytext(), yychar); 148 } 149 "/**" / [^/] { 150 if (nestedComment++ == 0) { 151 yypush(SDOC); 152 onDisjointSpanChanged(HtmlConsts.COMMENT_CLASS, yychar); 153 } 154 onNonSymbolMatched(yytext(), yychar); 155 } 156 "//" { 157 yypush(SCOMMENT); 158 onDisjointSpanChanged(HtmlConsts.COMMENT_CLASS, yychar); 159 onNonSymbolMatched(yytext(), yychar); 160 } 161 } 162 163 <STRING> { 164 \\[\"\\] { chkLOC(); onNonSymbolMatched(yytext(), yychar); } 165 \" { 166 chkLOC(); 167 onNonSymbolMatched(yytext(), yychar); 168 yypop(); 169 } 170 } 171 172 <TSTRING> { 173 \"\"\" { 174 chkLOC(); 175 onNonSymbolMatched(yytext(), yychar); 176 yypop(); 177 } 178 } 179 180 <STRING, TSTRING> { 181 {WhspChar}*{EOL} { 182 onDisjointSpanChanged(null, yychar); 183 onEndOfLineMatched(yytext(), yychar); 184 onDisjointSpanChanged(HtmlConsts.STRING_CLASS, yychar); 185 } 186 } 187 188 <YYINITIAL, COMMENT, SDOC> { 189 "/*" { 190 if (nestedComment++ == 0) { 191 yypush(COMMENT); 192 onDisjointSpanChanged(HtmlConsts.COMMENT_CLASS, yychar); 193 } 194 onNonSymbolMatched(yytext(), yychar); 195 } 196 } 197 198 <COMMENT, SDOC> { 199 "*/" { 200 onNonSymbolMatched(yytext(), yychar); 201 if (--nestedComment == 0) { 202 yypop(); 203 } 204 } 205 {WhspChar}*{EOL} { 206 onDisjointSpanChanged(null, yychar); 207 onEndOfLineMatched(yytext(), yychar); 208 onDisjointSpanChanged(HtmlConsts.COMMENT_CLASS, yychar); 209 } 210 } 211 212 /* TODO: support markdown in comments 213 <SDOC> { 214 {SdocWithParamNameArg} {WhiteSpace} {ParamName} | 215 {SdocWithClassArg} {WhiteSpace} {ClassName} { 216 String text = yytext(); 217 String[] tokens = text.split(WHITE_SPACE, 2); 218 onNonSymbolMatched(tokens[0], EmphasisHint.STRONG, yychar); 219 onNonSymbolMatched(text.substring(tokens[0].length(), text.length() - 220 tokens[1].length()), yychar); 221 onNonSymbolMatched(tokens[1], EmphasisHint.EM, yychar); 222 } 223 "@" {Identifier} { 224 onNonSymbolMatched(yytext(), EmphasisHint.STRONG, yychar); 225 } 226 } 227 */ 228 229 <SCOMMENT> { 230 {WhspChar}*{EOL} { 231 yypop(); 232 onEndOfLineMatched(yytext(), yychar); 233 } 234 } 235 236 <YYINITIAL, STRING, COMMENT, SCOMMENT, SDOC, TSTRING> { 237 {WhspChar}*{EOL} { onEndOfLineMatched(yytext(), yychar); } 238 [[\s]--[\n]] { onNonSymbolMatched(yytext(), yychar); } 239 [^\n] { chkLOC(); onNonSymbolMatched(yytext(), yychar); } 240 } 241 242 <STRING, COMMENT, SCOMMENT, SDOC, TSTRING> { 243 {FPath} { 244 chkLOC(); 245 onPathlikeMatched(yytext(), '/', false, yychar); 246 } 247 248 {File} 249 { 250 chkLOC(); 251 String path = yytext(); 252 onFilelikeMatched(path, yychar); 253 } 254 255 {FNameChar}+ "@" {FNameChar}+ "." {FNameChar}+ 256 { 257 chkLOC(); 258 onEmailAddressMatched(yytext(), yychar); 259 } 260 } 261 262 <STRING, SCOMMENT, TSTRING> { 263 {BrowseableURI} { 264 chkLOC(); 265 onUriMatched(yytext(), yychar); 266 } 267 } 268 269 <COMMENT, SDOC> { 270 {BrowseableURI} { 271 onUriMatched(yytext(), yychar, StringUtils.END_C_COMMENT); 272 } 273 } 274