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) 2008, 2021, Oracle and/or its affiliates. All rights reserved. 22 * Portions Copyright (c) 2017, Chris Fraire <cfraire@me.com>. 23 */ 24 25 /* 26 * Cross reference a C++ file 27 */ 28 29 package org.opengrok.indexer.analysis.c; 30 31 import java.io.IOException; 32 import java.util.regex.Matcher; 33 import java.util.regex.Pattern; 34 import org.opengrok.indexer.analysis.JFlexSymbolMatcher; 35 import org.opengrok.indexer.analysis.ScopeAction; 36 import org.opengrok.indexer.util.StringUtils; 37 import org.opengrok.indexer.web.HtmlConsts; 38 %% 39 %public 40 %class CxxXref 41 %extends JFlexSymbolMatcher 42 %unicode 43 %int 44 %char 45 %include ../CommonLexer.lexh 46 %include ../CommonXref.lexh 47 %{ 48 private static final Pattern MATCH_INCLUDE = Pattern.compile( 49 "^(#.*)(include)(.*)([<\"])(.*)([>\"])$"); 50 private static final int INCL_HASH_G = 1; 51 private static final int INCLUDE_G = 2; 52 private static final int INCL_POST_G = 3; 53 private static final int INCL_PUNC0_G = 4; 54 private static final int INCL_PATH_G = 5; 55 private static final int INCL_PUNCZ_G = 6; 56 57 @Override yypop()58 public void yypop() throws IOException { 59 onDisjointSpanChanged(null, yychar); 60 super.yypop(); 61 } 62 chkLOC()63 protected void chkLOC() { 64 switch (yystate()) { 65 case COMMENT: 66 case SCOMMENT: 67 break; 68 default: 69 phLOC(); 70 break; 71 } 72 } 73 %} 74 75 File = [a-zA-Z]{FNameChar}* "." ([cChHsStT] | [Cc][Oo][Nn][Ff] | 76 [Jj][Aa][Vv][Aa] | [CcHh][Pp][Pp] | [Cc][Cc] | [Tt][Xx][Tt] | 77 [Hh][Tt][Mm][Ll]? | [Pp][Ll] | [Xx][Mm][Ll] | [CcHh][\+][\+] | [Hh][Hh] | 78 [CcHh][Xx][Xx] | [Dd][Ii][Ff][Ff] | [Pp][Aa][Tt][Cc][Hh]) 79 80 %state STRING COMMENT SCOMMENT QSTRING 81 82 %include ../Common.lexh 83 %include ../CommonURI.lexh 84 %include ../CommonPath.lexh 85 %include Cxx.lexh 86 %% 87 <YYINITIAL>{ 88 \{ { chkLOC(); onScopeChanged(ScopeAction.INC, yytext(), yychar); } 89 \} { chkLOC(); onScopeChanged(ScopeAction.DEC, yytext(), yychar); } 90 \; { chkLOC(); onScopeChanged(ScopeAction.END, yytext(), yychar); } 91 92 {Identifier} { 93 chkLOC(); 94 String id = yytext(); 95 onFilteredSymbolMatched(id, yychar, CxxConsts.kwd); 96 } 97 98 "#" {WhspChar}* "include" {WhspChar}* ("<"[^>\n\r]+">" | \"[^\"\n\r]+\") { 99 chkLOC(); 100 String capture = yytext(); 101 Matcher match = MATCH_INCLUDE.matcher(capture); 102 if (match.matches()) { 103 onNonSymbolMatched(match.group(INCL_HASH_G), yychar); 104 onFilteredSymbolMatched(match.group(INCLUDE_G), yychar, CxxConsts.kwd); 105 onNonSymbolMatched(match.group(INCL_POST_G), yychar); 106 onNonSymbolMatched(match.group(INCL_PUNC0_G), yychar); 107 String path = match.group(INCL_PATH_G); 108 onPathlikeMatched(path, '/', false, yychar); 109 onNonSymbolMatched(match.group(INCL_PUNCZ_G), yychar); 110 } else { 111 onNonSymbolMatched(capture, yychar); 112 } 113 } 114 115 /*{Hier} 116 { onPathlikeMatched(yytext(), '.', false, yychar); } 117 */ 118 {Number} { 119 chkLOC(); 120 onDisjointSpanChanged(HtmlConsts.NUMBER_CLASS, yychar); 121 onNonSymbolMatched(yytext(), yychar); 122 onDisjointSpanChanged(null, yychar); 123 } 124 125 \" { 126 chkLOC(); 127 yypush(STRING); 128 onDisjointSpanChanged(HtmlConsts.STRING_CLASS, yychar); 129 onNonSymbolMatched(yytext(), yychar); 130 } 131 \' { 132 chkLOC(); 133 yypush(QSTRING); 134 onDisjointSpanChanged(HtmlConsts.STRING_CLASS, yychar); 135 onNonSymbolMatched(yytext(), yychar); 136 } 137 "/*" { 138 yypush(COMMENT); 139 onDisjointSpanChanged(HtmlConsts.COMMENT_CLASS, yychar); 140 onNonSymbolMatched(yytext(), yychar); 141 } 142 "//" { 143 yypush(SCOMMENT); 144 onDisjointSpanChanged(HtmlConsts.COMMENT_CLASS, yychar); 145 onNonSymbolMatched(yytext(), yychar); 146 } 147 } 148 149 <STRING> { 150 \\[\"\\] | 151 \" {WhspChar}+ \" { chkLOC(); onNonSymbolMatched(yytext(), yychar); } 152 \" { chkLOC(); onNonSymbolMatched(yytext(), yychar); yypop(); } 153 } 154 155 <QSTRING> { 156 \\[\'\\] | 157 \' {WhspChar}+ \' { chkLOC(); onNonSymbolMatched(yytext(), yychar); } 158 \' { chkLOC(); onNonSymbolMatched(yytext(), yychar); yypop(); } 159 } 160 161 <COMMENT> { 162 "*/" { onNonSymbolMatched(yytext(), yychar); yypop(); } 163 } 164 165 <SCOMMENT> { 166 {WhspChar}*{EOL} { 167 yypop(); 168 onEndOfLineMatched(yytext(), yychar);} 169 } 170 171 172 <YYINITIAL, STRING, COMMENT, SCOMMENT, QSTRING> { 173 {WhspChar}*{EOL} { onEndOfLineMatched(yytext(), yychar); } 174 [[\s]--[\n]] { onNonSymbolMatched(yytext(), yychar); } 175 [^\n] { chkLOC(); onNonSymbolMatched(yytext(), yychar); } 176 } 177 178 <STRING, COMMENT, SCOMMENT, QSTRING> { 179 {FPath} { 180 chkLOC(); 181 onPathlikeMatched(yytext(), '/', false, yychar); 182 } 183 184 {File} 185 { 186 chkLOC(); 187 String path = yytext(); 188 onFilelikeMatched(path, yychar); 189 } 190 191 {FNameChar}+ "@" {FNameChar}+ "." {FNameChar}+ 192 { 193 chkLOC(); 194 onEmailAddressMatched(yytext(), yychar); 195 } 196 } 197 198 <STRING, SCOMMENT> { 199 {BrowseableURI} { 200 chkLOC(); 201 onUriMatched(yytext(), yychar); 202 } 203 } 204 205 <COMMENT> { 206 {BrowseableURI} { 207 onUriMatched(yytext(), yychar, StringUtils.END_C_COMMENT); 208 } 209 } 210 211 <QSTRING> { 212 {BrowseableURI} { 213 chkLOC(); 214 onUriMatched(yytext(), yychar, StringUtils.APOS_NO_BSESC); 215 } 216 } 217