Skip to content

Commit 813f63c

Browse files
committed
Add support for OCaml.
1 parent 11e2e0a commit 813f63c

File tree

8 files changed

+816
-1
lines changed

8 files changed

+816
-1
lines changed

opengrok-indexer/src/main/java/org/opengrok/indexer/analysis/AnalyzerGuru.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919

2020
/*
2121
* Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved.
22-
* Portions Copyright (c) 2017, 2021, Chris Fraire <cfraire@me.com>.
22+
* Portions Copyright (c) 2025, Yelisey Romanov <progoramur@gmail.com>.
2323
*/
2424
package org.opengrok.indexer.analysis;
2525

@@ -89,6 +89,7 @@
8989
import org.opengrok.indexer.analysis.kotlin.KotlinAnalyzerFactory;
9090
import org.opengrok.indexer.analysis.lisp.LispAnalyzerFactory;
9191
import org.opengrok.indexer.analysis.lua.LuaAnalyzerFactory;
92+
import org.opengrok.indexer.analysis.ocaml.OCamlAnalyzerFactory;
9293
import org.opengrok.indexer.analysis.pascal.PascalAnalyzerFactory;
9394
import org.opengrok.indexer.analysis.perl.PerlAnalyzerFactory;
9495
import org.opengrok.indexer.analysis.php.PhpAnalyzerFactory;
@@ -298,6 +299,7 @@ public class AnalyzerGuru {
298299
new HaskellAnalyzerFactory(),
299300
new GolangAnalyzerFactory(),
300301
new LuaAnalyzerFactory(),
302+
new OCamlAnalyzerFactory(),
301303
new PascalAnalyzerFactory(),
302304
new AdaAnalyzerFactory(),
303305
new RubyAnalyzerFactory(),
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
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) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
22+
* Portions Copyright (c) 2025, Yelisey Romanov <[email protected]>.
23+
*/
24+
package org.opengrok.indexer.analysis.ocaml;
25+
26+
import java.util.HashSet;
27+
import java.util.Set;
28+
29+
/**
30+
* Represents a container for a set of OCaml keywords.
31+
*/
32+
public class Consts {
33+
34+
static final Set<String> kwd = new HashSet<>();
35+
36+
static {
37+
/* OCaml 5.3.0 keywords */
38+
kwd.add("and");
39+
kwd.add("as");
40+
kwd.add("assert");
41+
kwd.add("begin");
42+
kwd.add("class");
43+
kwd.add("constraint");
44+
kwd.add("do");
45+
kwd.add("done");
46+
kwd.add("downto");
47+
kwd.add("effect");
48+
kwd.add("else");
49+
kwd.add("end");
50+
kwd.add("exception");
51+
kwd.add("external");
52+
kwd.add("false");
53+
kwd.add("for");
54+
kwd.add("fun");
55+
kwd.add("function");
56+
kwd.add("functor");
57+
kwd.add("if");
58+
kwd.add("in");
59+
kwd.add("include");
60+
kwd.add("inherit");
61+
kwd.add("initializer");
62+
kwd.add("lazy");
63+
kwd.add("let");
64+
kwd.add("match");
65+
kwd.add("method");
66+
kwd.add("module");
67+
kwd.add("mutable");
68+
kwd.add("new");
69+
kwd.add("nonrec");
70+
kwd.add("object");
71+
kwd.add("of");
72+
kwd.add("open");
73+
kwd.add("or");
74+
kwd.add("parser");
75+
kwd.add("private");
76+
kwd.add("ref");
77+
kwd.add("rec");
78+
kwd.add("sig");
79+
kwd.add("struct");
80+
kwd.add("then");
81+
kwd.add("to");
82+
kwd.add("true");
83+
kwd.add("try");
84+
kwd.add("type");
85+
kwd.add("val");
86+
kwd.add("virtual");
87+
kwd.add("when");
88+
kwd.add("while");
89+
kwd.add("with");
90+
kwd.add("lor");
91+
kwd.add("lxor");
92+
kwd.add("mod");
93+
kwd.add("land");
94+
kwd.add("lsl");
95+
kwd.add("lsr");
96+
kwd.add("asr");
97+
98+
/* OCaml 5.3.0 predefined types */
99+
/* it is possible to make a variable of such a name,
100+
though people mostly do not use this opportunity */
101+
kwd.add("bool");
102+
kwd.add("char");
103+
kwd.add("float");
104+
kwd.add("int");
105+
106+
kwd.add("bytes");
107+
kwd.add("string");
108+
109+
kwd.add("array");
110+
kwd.add("list");
111+
kwd.add("option");
112+
/* "result" is often a variable, so not adding */
113+
114+
kwd.add("unit");
115+
}
116+
117+
/** Private to enforce static. */
118+
private Consts() {
119+
}
120+
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
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) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
22+
* Portions Copyright (c) 2025, Yelisey Romanov <[email protected]>.
23+
*/
24+
package org.opengrok.indexer.analysis.ocaml;
25+
26+
import org.opengrok.indexer.analysis.AbstractAnalyzer;
27+
import org.opengrok.indexer.analysis.FileAnalyzerFactory;
28+
import org.opengrok.indexer.analysis.JFlexTokenizer;
29+
import org.opengrok.indexer.analysis.JFlexXref;
30+
import org.opengrok.indexer.analysis.plain.AbstractSourceCodeAnalyzer;
31+
32+
import java.io.Reader;
33+
34+
/**
35+
* Represents an analyzer for the OCaml language.
36+
*/
37+
@SuppressWarnings("java:S110")
38+
public class OCamlAnalyzer extends AbstractSourceCodeAnalyzer {
39+
40+
/**
41+
* Creates a new instance of {@link OCamlAnalyzer}.
42+
* @param factory instance
43+
*/
44+
protected OCamlAnalyzer(FileAnalyzerFactory factory) {
45+
super(factory, () -> new JFlexTokenizer(new OCamlSymbolTokenizer(
46+
AbstractAnalyzer.DUMMY_READER)));
47+
}
48+
49+
/**
50+
* @return {@code "ocaml"}
51+
*/
52+
@Override
53+
public String getCtagsLang() {
54+
return "ocaml";
55+
}
56+
57+
/**
58+
* Gets a version number to be used to tag processed documents so that
59+
* re-analysis can be re-done later if a stored version number is different
60+
* from the current implementation.
61+
* @return 20250403_00
62+
*/
63+
@Override
64+
protected int getSpecializedVersionNo() {
65+
return 20250403_00; // Edit comment above too!
66+
}
67+
68+
/**
69+
* Creates a wrapped {@link OCamlXref} instance.
70+
* @return a defined instance
71+
*/
72+
@Override
73+
protected JFlexXref newXref(Reader reader) {
74+
return new JFlexXref(new OCamlXref(reader));
75+
}
76+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
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) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
22+
* Portions Copyright (c) 2025, Yelisey Romanov <[email protected]>.
23+
*/
24+
package org.opengrok.indexer.analysis.ocaml;
25+
26+
import org.opengrok.indexer.analysis.AbstractAnalyzer.Genre;
27+
import org.opengrok.indexer.analysis.FileAnalyzer;
28+
import org.opengrok.indexer.analysis.FileAnalyzerFactory;
29+
30+
/**
31+
* Represents a factory to create {@link OCamlAnalyzer} instances.
32+
*/
33+
public class OCamlAnalyzerFactory extends FileAnalyzerFactory {
34+
35+
private static final String NAME = "OCaml";
36+
37+
private static final String[] SUFFIXES = {"ML", "MLI"};
38+
39+
/**
40+
* Initializes a factory instance to associate a file extensions ".ml",
41+
* ".mli" with {@link OCamlAnalyzer}.
42+
*/
43+
public OCamlAnalyzerFactory() {
44+
super(null, null, SUFFIXES, null, null, "text/plain", Genre.PLAIN,
45+
NAME, true);
46+
}
47+
48+
/**
49+
* Creates a new {@link OCamlAnalyzer} instance.
50+
* @return a defined instance
51+
*/
52+
@Override
53+
protected FileAnalyzer newAnalyzer() {
54+
return new OCamlAnalyzer(this);
55+
}
56+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
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) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
22+
* Portions Copyright (c) 2025, Yelisey Romanov <[email protected]>.
23+
*/
24+
package org.opengrok.indexer.analysis.ocaml;
25+
26+
import org.opengrok.indexer.analysis.JFlexJointLexer;
27+
import org.opengrok.indexer.analysis.JFlexSymbolMatcher;
28+
import org.opengrok.indexer.analysis.Resettable;
29+
30+
/**
31+
* Represents an abstract base class for OCaml lexers.
32+
*/
33+
@SuppressWarnings("Duplicates")
34+
abstract class OCamlLexer extends JFlexSymbolMatcher
35+
implements JFlexJointLexer, Resettable {
36+
37+
/**
38+
* Calls {@link #phLOC()} if the yystate is not COMMENT or SCOMMENT.
39+
*/
40+
public void chkLOC() {
41+
if (yystate() != COMMENT() && yystate() != SCOMMENT()) {
42+
phLOC();
43+
}
44+
}
45+
46+
/**
47+
* Subclasses must override to get the constant value created by JFlex to
48+
* represent COMMENT.
49+
*/
50+
@SuppressWarnings("java:S100")
51+
abstract int COMMENT();
52+
53+
/**
54+
* Subclasses must override to get the constant value created by JFlex to
55+
* represent SCOMMENT.
56+
*/
57+
@SuppressWarnings("java:S100")
58+
abstract int SCOMMENT();
59+
}

0 commit comments

Comments
 (0)