Skip to content

Commit c263451

Browse files
committed
Fix to fine-tune URI link for Fortran QSTRING
Also: - Fix to recognize proper Fortran escaping of quotation-marks and apostrophe.
1 parent a9fe86f commit c263451

File tree

6 files changed

+152
-25
lines changed

6 files changed

+152
-25
lines changed

src/org/opensolaris/opengrok/analysis/fortran/FortranSymbolTokenizer.lex

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ super(in);
3838
%include CommonTokenizer.lexh
3939
%char
4040

41-
// (OK to exclude LSTRING state used in FortranXref.)
41+
// (OK to exclude LCOMMENT state used in FortranXref.)
4242
%state STRING SCOMMENT QSTRING
4343

4444
%include Common.lexh
@@ -62,12 +62,12 @@ super(in);
6262
}
6363

6464
<STRING> {
65-
\\[\"\\] {}
65+
\"\" {}
6666
\" { yybegin(YYINITIAL); }
6767
}
6868

6969
<QSTRING> {
70-
\\[\'\\] {}
70+
\'\' {}
7171
\' { yybegin(YYINITIAL); }
7272
}
7373

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
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, Chris Fraire <[email protected]>.
22+
*/
23+
24+
package org.opensolaris.opengrok.analysis.fortran;
25+
26+
import java.util.regex.Pattern;
27+
28+
/**
29+
* Represents a container for Fortran-related utility methods.
30+
*/
31+
public class FortranUtils {
32+
33+
/**
34+
* Matches an apostrophe that is not¹ part of a Fortran apostrophe escape
35+
* sequence:
36+
* <pre>
37+
* {@code
38+
* \'((?<=^.(?!\'))|(?<=[^\'].(?!\'))|(?<=^(\'\'){1,3}.(?!\'))|(?<=[^\'](\'\'){1,3}.(?!\')))
39+
* }
40+
* </pre>
41+
* (Edit above and paste below [in NetBeans] for easy String escaping.)
42+
* <p>
43+
* ¹Correctness in a long sequence of apostrophes is limited because Java
44+
* look-behind is not variable length but instead must have a definite
45+
* upper bound in the regex definition.
46+
*/
47+
public static final Pattern CHARLITERAL_APOS_DELIMITER =
48+
Pattern.compile("\\'((?<=^.(?!\\'))|(?<=[^\\'].(?!\\'))|(?<=^(\\'\\'){1,3}.(?!\\'))|(?<=[^\\'](\\'\\'){1,3}.(?!\\')))");
49+
50+
private FortranUtils() {
51+
}
52+
}

src/org/opensolaris/opengrok/analysis/fortran/FortranXref.lex

Lines changed: 28 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
package org.opensolaris.opengrok.analysis.fortran;
2929

3030
import org.opensolaris.opengrok.analysis.JFlexXrefSimple;
31+
import org.opensolaris.opengrok.util.StringUtils;
3132
import org.opensolaris.opengrok.web.HtmlConsts;
3233
import org.opensolaris.opengrok.web.Util;
3334
%%
@@ -110,44 +111,42 @@ File = [a-zA-Z]{FNameChar}* ".inc"
110111
}
111112

112113
<STRING> {
113-
\\[\"\\] |
114-
\" {WhiteSpace} \" { out.write(htmlize(yytext()));}
114+
\"\" { out.write(htmlize(yytext()));}
115115
\" {
116116
out.write(htmlize(yytext()));
117117
yypop();
118118
}
119119
}
120120

121121
<QSTRING> {
122-
\\[\'\\] |
123-
\' {WhiteSpace} \' { out.write(htmlize(yytext())); }
122+
\'\' { out.write(htmlize(yytext())); }
124123
\' {
125124
out.write(htmlize(yytext()));
126125
yypop();
127126
}
128127
}
129128

130-
<SCOMMENT> {
131-
{WhspChar}*{EOL} { yypop();
132-
startNewLine();}
129+
<STRING, QSTRING> {
130+
{WhspChar}*{EOL} {
131+
disjointSpan(null);
132+
startNewLine();
133+
disjointSpan(HtmlConsts.STRING_CLASS);
134+
}
133135
}
134136

135-
<LCOMMENT> {
136-
[&<>\'\"] { out.write(htmlize(yytext())); }
137-
{WhspChar}*{EOL} { yypop();
138-
startNewLine();}
139-
{WhiteSpace} { out.write(yytext()); }
140-
[!-~] { out.write(yycharat(0)); }
141-
[^\n] { writeUnicodeChar(yycharat(0)); }
137+
<SCOMMENT, LCOMMENT> {
138+
{WhspChar}*{EOL} {
139+
yypop();
140+
startNewLine();
141+
}
142142
}
143143

144-
145-
<YYINITIAL, STRING, SCOMMENT, QSTRING> {
144+
<YYINITIAL, STRING, SCOMMENT, QSTRING, LCOMMENT> {
146145
[&<>\'\"] { out.write(htmlize(yytext())); }
147146
{WhspChar}*{EOL} { startNewLine(); }
148147
{WhiteSpace} { out.write(yytext()); }
149148
[!-~] { out.write(yycharat(0)); }
150-
[^\n] { }
149+
[^\n] { writeUnicodeChar(yycharat(0)); }
151150
}
152151

153152
<SCOMMENT, STRING, QSTRING> {
@@ -161,12 +160,20 @@ File = [a-zA-Z]{FNameChar}* ".inc"
161160
out.write(path);out.write("\">");
162161
out.write(path);out.write("</a>");}
163162

164-
{BrowseableURI} {
165-
appendLink(yytext(), true);
166-
}
167-
168163
{FNameChar}+ "@" {FNameChar}+ "." {FNameChar}+
169164
{
170165
writeEMailAddress(yytext());
171166
}
172167
}
168+
169+
<SCOMMENT, STRING> {
170+
{BrowseableURI} {
171+
appendLink(yytext(), true);
172+
}
173+
}
174+
175+
<QSTRING> {
176+
{BrowseableURI} {
177+
appendLink(yytext(), true, FortranUtils.CHARLITERAL_APOS_DELIMITER);
178+
}
179+
}
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
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, Chris Fraire <[email protected]>.
22+
*/
23+
24+
package org.opensolaris.opengrok.analysis.fortran;
25+
26+
import static org.junit.Assert.assertEquals;
27+
import org.junit.Test;
28+
import org.opensolaris.opengrok.util.StringUtils;
29+
30+
/**
31+
* Represents a test class for {@link FortranUtils}.
32+
*/
33+
public class FortranUtilsTest {
34+
35+
@Test
36+
public void shouldMatchNonescapedApostrophe() {
37+
final String value = "''1-2-3'";
38+
int i = StringUtils.patindexOf(value,
39+
FortranUtils.CHARLITERAL_APOS_DELIMITER);
40+
assertEquals("unquoted apostrophe", 7, i);
41+
}
42+
43+
@Test
44+
public void shouldMatchApostropheAfterPairsOfApostrophes() {
45+
final String value = "'''''";
46+
int i = StringUtils.patindexOf(value,
47+
FortranUtils.CHARLITERAL_APOS_DELIMITER);
48+
assertEquals("unquoted apostrophe after apostrophes", 4, i);
49+
}
50+
51+
@Test
52+
public void shouldNotMatchApostropheAfterOddApostrophes() {
53+
final String value = "''''";
54+
int i = StringUtils.patindexOf(value,
55+
FortranUtils.CHARLITERAL_APOS_DELIMITER);
56+
assertEquals("escaped apostrophe pairs", -1, i);
57+
}
58+
59+
@Test
60+
public void shouldMatchInitialApostrophe() {
61+
final String value = "'";
62+
int i = StringUtils.patindexOf(value,
63+
FortranUtils.CHARLITERAL_APOS_DELIMITER);
64+
assertEquals("initial apostrophe", 0, i);
65+
}
66+
}

test/org/opensolaris/opengrok/analysis/fortran/sample.f

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,3 +227,4 @@ SUBROUTINE DGESV( N, NRHS, A, LDA, IPIV, B, LDB, INFO )
227227
* End of DGESV
228228
*
229229
END
230+
CALL 'http://example.com'

test/org/opensolaris/opengrok/analysis/fortran/sample_xref.html

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -235,5 +235,6 @@
235235
<a class="l" name="227" href="#227">227</a><span class="c">* End of DGESV</span>
236236
<a class="l" name="228" href="#228">228</a><span class="c">*</span>
237237
<a class="l" name="229" href="#229">229</a> <b>END</b>
238-
<a class="hl" name="230" href="#230">230</a></body>
238+
<a class="hl" name="230" href="#230">230</a> <b>CALL</b> <span class="s">&apos;<a href="http://example.com">http://example.com</a>&apos;</span>
239+
<a class="l" name="231" href="#231">231</a></body>
239240
</html>

0 commit comments

Comments
 (0)