xref: /OpenGrok/opengrok-indexer/src/main/jflex/analysis/kotlin/KotlinXref.lex (revision d219b4cea555a12b602d2d5518daa22134ad4879)
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.kotlin;
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.analysis.EmphasisHint;
31 import org.opengrok.indexer.util.StringUtils;
32 import org.opengrok.indexer.web.HtmlConsts;
33 %%
34 %public
35 %class KotlinXref
36 %extends JFlexSymbolMatcher
37 %unicode
38 %ignorecase
39 %int
40 %char
41 %include ../CommonLexer.lexh
42 %include ../CommonXref.lexh
43 %{
44   /* Must match {WhspChar}+ regex */
45   private final static String WHITE_SPACE = "[ \\t\\f]+";
46 
47   private int nestedComment;
48 
49   @Override
reset()50   public void reset() {
51       super.reset();
52       nestedComment = 0;
53   }
54 
55   @Override
yypop()56   public void yypop() throws IOException {
57       onDisjointSpanChanged(null, yychar);
58       super.yypop();
59   }
60 
chkLOC()61   protected void chkLOC() {
62       switch (yystate()) {
63           case COMMENT:
64           case SCOMMENT:
65           case KDOC:
66               break;
67           default:
68               phLOC();
69               break;
70       }
71   }
72 %}
73 
74 File = [a-zA-Z]{FNameChar}* "." ([Jj][Aa][Vv][Aa] |
75     [Pp][Rr][Oo][Pp][Ee][Rr][Tt][Ii][Ee][Ss] | [Pp][Rr][Oo][Pp][Ss] |
76     [Xx][Mm][Ll] | [Cc][Oo][Nn][Ff] | [Tt][Xx][Tt] | [Hh][Tt][Mm][Ll]? |
77     [Ii][Nn][Ii] | [Jj][Nn][Ll][Pp] | [Jj][Aa][Dd] | [Dd][Ii][Ff][Ff] |
78     [Pp][Aa][Tt][Cc][Hh])
79 
80 KdocWithClassArg = "@throws" | "@exception"
81 KdocWithParamNameArg = "@param"
82 
83 ClassName = ({Identifier} ".")* {Identifier}
84 ParamName = {Identifier} | "<" {Identifier} ">"
85 
86 %state  STRING COMMENT SCOMMENT QSTRING KDOC TSTRING
87 
88 %include ../Common.lexh
89 %include ../CommonURI.lexh
90 %include ../CommonPath.lexh
91 %include Kotlin.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 "<" ({File}|{FPath}) ">" {
105         chkLOC();
106         onNonSymbolMatched("<", yychar);
107         String path = yytext();
108         path = path.substring(1, path.length() - 1);
109         onFilelikeMatched(path, yychar + 1);
110         onNonSymbolMatched(">", yychar + 1 + path.length());
111 }
112 
113  {Number}        {
114     chkLOC();
115     onDisjointSpanChanged(HtmlConsts.NUMBER_CLASS, yychar);
116     onNonSymbolMatched(yytext(), yychar);
117     onDisjointSpanChanged(null, yychar);
118  }
119 
120  \"     {
121     chkLOC();
122     yypush(STRING);
123     onDisjointSpanChanged(HtmlConsts.STRING_CLASS, yychar);
124     onNonSymbolMatched(yytext(), yychar);
125  }
126  \'     {
127     chkLOC();
128     yypush(QSTRING);
129     onDisjointSpanChanged(HtmlConsts.STRING_CLASS, yychar);
130     onNonSymbolMatched(yytext(), yychar);
131  }
132  \"\"\"    {
133     chkLOC();
134     yypush(TSTRING);
135     onDisjointSpanChanged(HtmlConsts.STRING_CLASS, yychar);
136     onNonSymbolMatched(yytext(), yychar);
137  }
138  "/**" / [^/]    {
139     if (nestedComment++ == 0) {
140         yypush(KDOC);
141         onDisjointSpanChanged(HtmlConsts.COMMENT_CLASS, yychar);
142     }
143     onNonSymbolMatched(yytext(), yychar);
144  }
145  "//"    {
146     yypush(SCOMMENT);
147     onDisjointSpanChanged(HtmlConsts.COMMENT_CLASS, yychar);
148     onNonSymbolMatched(yytext(), yychar);
149  }
150 }
151 
152 <STRING> {
153  \\[\"\$\\]    { chkLOC(); onNonSymbolMatched(yytext(), yychar); }
154  \"     {
155     chkLOC();
156     onNonSymbolMatched(yytext(), yychar);
157     yypop();
158  }
159 }
160 
161 <QSTRING> {
162  \\[\'\\] |
163  \' {WhspChar}+ \'    { chkLOC(); onNonSymbolMatched(yytext(), yychar); }
164  \'     {
165     chkLOC();
166     onNonSymbolMatched(yytext(), yychar);
167     yypop();
168  }
169 }
170 
171 <TSTRING> {
172  /*
173   * "raw string ... doesn't support backslash escaping"
174   */
175  \"\"\"    {
176     chkLOC();
177     onNonSymbolMatched(yytext(), yychar);
178     yypop();
179  }
180 }
181 
182 <STRING, TSTRING> {
183     /*
184      * TODO : support template expressions inside curly brackets
185      */
186     \$ {Identifier}    {
187         chkLOC();
188         String capture = yytext();
189         String sigil = capture.substring(0, 1);
190         String id = capture.substring(1);
191         onNonSymbolMatched(sigil, yychar);
192         onDisjointSpanChanged(null, yychar);
193         onFilteredSymbolMatched(id, yychar, Consts.kwd);
194         onDisjointSpanChanged(HtmlConsts.STRING_CLASS, yychar);
195     }
196     {WhspChar}*{EOL}    {
197         onDisjointSpanChanged(null, yychar);
198         onEndOfLineMatched(yytext(), yychar);
199         onDisjointSpanChanged(HtmlConsts.STRING_CLASS, yychar);
200     }
201 }
202 
203 <YYINITIAL, COMMENT, KDOC> {
204     "/*"    {
205         if (nestedComment++ == 0) {
206             yypush(COMMENT);
207             onDisjointSpanChanged(HtmlConsts.COMMENT_CLASS, yychar);
208         }
209         onNonSymbolMatched(yytext(), yychar);
210     }
211 }
212 
213 <COMMENT, KDOC> {
214 "*/"    {
215     onNonSymbolMatched(yytext(), yychar);
216     if (--nestedComment == 0) {
217         yypop();
218     }
219  }
220  {WhspChar}*{EOL}    {
221     onDisjointSpanChanged(null, yychar);
222     onEndOfLineMatched(yytext(), yychar);
223     onDisjointSpanChanged(HtmlConsts.COMMENT_CLASS, yychar);
224  }
225 }
226 
227 <KDOC> {
228   {KdocWithParamNameArg} {WhspChar}+ {ParamName} |
229   {KdocWithClassArg} {WhspChar}+ {ClassName} {
230     String text = yytext();
231     String[] tokens = text.split(WHITE_SPACE, 2);
232     onNonSymbolMatched(tokens[0], EmphasisHint.STRONG, yychar);
233     onNonSymbolMatched(text.substring(tokens[0].length(), text.length() -
234         tokens[1].length()), yychar);
235     onNonSymbolMatched(tokens[1], EmphasisHint.EM, yychar);
236   }
237   "@" {Identifier} {
238     onNonSymbolMatched(yytext(), EmphasisHint.STRONG, yychar);
239   }
240 }
241 
242 <SCOMMENT> {
243   {WhspChar}*{EOL} {
244     yypop();
245     onEndOfLineMatched(yytext(), yychar);
246   }
247 }
248 
249 
250 <YYINITIAL, STRING, COMMENT, SCOMMENT, QSTRING, KDOC, TSTRING> {
251 {WhspChar}*{EOL}    { onEndOfLineMatched(yytext(), yychar); }
252  [[\s]--[\n]]    { onNonSymbolMatched(yytext(), yychar); }
253  [^\n]    { chkLOC(); onNonSymbolMatched(yytext(), yychar); }
254 }
255 
256 <STRING, COMMENT, SCOMMENT, QSTRING, TSTRING, KDOC> {
257  {FPath}    {
258     chkLOC();
259     onPathlikeMatched(yytext(), '/', false, yychar);
260  }
261 
262 {File}
263         {
264         chkLOC();
265         String path = yytext();
266         onFilelikeMatched(path, yychar);
267  }
268 
269 {FNameChar}+ "@" {FNameChar}+ "." {FNameChar}+
270         {
271           chkLOC();
272           onEmailAddressMatched(yytext(), yychar);
273         }
274 }
275 
276 <STRING, SCOMMENT, QSTRING, TSTRING> {
277     {BrowseableURI}    {
278         chkLOC();
279         onUriMatched(yytext(), yychar);
280     }
281 }
282 
283 <COMMENT, KDOC> {
284     {BrowseableURI}    {
285         onUriMatched(yytext(), yychar, StringUtils.END_C_COMMENT);
286     }
287 }
288