Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for Julia lang #90

Merged
merged 1 commit into from
Nov 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/hash/extensions.gperf
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ java, LANG_JAVA
jpeg, BINARY
jpg, BINARY
js, LANG_JAVASCRIPT
jl, LANG_JULIA
jsp, LANG_JSP
kdebuild-1, LANG_EBUILD
kt, LANG_KOTLIN
Expand Down
1 change: 1 addition & 0 deletions src/hash/languages.gperf
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ idl_pvwave, LANG_IDL_PVWAVE, "IDL/PV-WAVE/GDL", 0
jam, LANG_JAM, "Jam", 2
java, LANG_JAVA, "Java", 0
javascript, LANG_JAVASCRIPT, "JavaScript", 0
julia, LANG_JULIA, "Julia", 0
jsp, LANG_JSP, "", 0
kotlin, LANG_KOTLIN, "Kotlin", 0
limbo, LANG_LIMBO, "Limbo", 0
Expand Down
2 changes: 2 additions & 0 deletions src/hash/parsers.gperf
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
#include "../parsers/jam.h"
#include "../parsers/java.h"
#include "../parsers/javascript.h"
#include "../parsers/julia.h"
#include "../parsers/jsp.h"
#include "../parsers/kotlin.h"
#include "../parsers/lisp.h"
Expand Down Expand Up @@ -169,6 +170,7 @@ idl_pvwave, parse_idl_pvwave
jam, parse_jam
java, parse_java
javascript, parse_javascript
julia, parse_julia
jsp, parse_jsp
kotlin, parse_kotlin
lisp, parse_lisp
Expand Down
1 change: 1 addition & 0 deletions src/languages.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@
#define LANG_JAM "jam"
#define LANG_JAVA "java"
#define LANG_JAVASCRIPT "javascript"
#define LANG_JULIA "julia"
#define LANG_JSP "jsp"
#define LANG_KOTLIN "kotlin"
#define LANG_LIMBO "limbo"
Expand Down
140 changes: 140 additions & 0 deletions src/parsers/julia.rl
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
/************************* Required for every parser *************************/
#ifndef OHCOUNT_JULIA_PARSER_H
#define OHCOUNT_JULIA_PARSER_H

#include "../parser_macros.h"

// the name of the language
const char *JULIA_LANG = LANG_JULIA;

// the languages entities
const char *julia_entities[] = {
"space", "comment", "string", "any"
};

// constants associated with the entities
enum {
JULIA_SPACE = 0, JULIA_COMMENT, JULIA_STRING, JULIA_ANY
};

/*****************************************************************************/

%%{
machine julia;
write data;
include common "common.rl";

# Line counting machine

action julia_ccallback {
switch(entity) {
case JULIA_SPACE:
ls
break;
case JULIA_ANY:
code
break;
case INTERNAL_NL:
std_internal_newline(JULIA_LANG)
break;
case NEWLINE:
std_newline(JULIA_LANG)
}
}

julia_line_comment = '#' @comment nonnewline*;
julia_block_comment =
'#=' @comment (
newline %{ entity = INTERNAL_NL; } %julia_ccallback
|
ws
|
(nonnewline - ws) @comment
)* :>> '=#';
julia_sq_doc_str =
'\'\'\'' @comment (
newline %{ entity = INTERNAL_NL; } %julia_ccallback
|
ws
|
(nonnewline - ws) @comment
)* :>> '\'\'\'' @comment;
julia_dq_doc_str =
'"""' @comment (
newline %{ entity = INTERNAL_NL; } %julia_ccallback
|
ws
|
(nonnewline - ws) @comment
)* :>> '"""' @comment;
julia_comment = julia_line_comment | julia_block_comment |
julia_sq_doc_str | julia_dq_doc_str;

# make sure it's not ''' or """
julia_sq_str =
'\'' ([^'] | '\'' [^'] @{ fhold; }) @{ fhold; }
([^\r\n\f'\\] | '\\' nonnewline)* '\'';
julia_dq_str =
'"' ([^"] | '"' [^"] @{ fhold; }) @{ fhold; }
([^\r\n\f"\\] | '\\' nonnewline)* '"';
julia_string = (julia_sq_str | julia_dq_str) @code;

julia_line := |*
spaces ${ entity = JULIA_SPACE; } => julia_ccallback;
julia_comment;
julia_string;
newline ${ entity = NEWLINE; } => julia_ccallback;
^space ${ entity = JULIA_ANY; } => julia_ccallback;
*|;

# Entity machine

action julia_ecallback {
callback(JULIA_LANG, julia_entities[entity], cint(ts), cint(te), userdata);
}

julia_line_comment_entity = '#' nonnewline*;
julia_block_comment_entity = '#=' any* :>> '=#';
julia_sq_doc_str_entity = '\'\'\'' any* :>> '\'\'\'';
julia_dq_doc_str_entity = '"""' any* :>> '"""';
julia_comment_entity = julia_line_comment_entity | julia_block_comment_entity |
julia_sq_doc_str_entity | julia_dq_doc_str_entity;

julia_entity := |*
space+ ${ entity = JULIA_SPACE; } => julia_ecallback;
julia_comment_entity ${ entity = JULIA_COMMENT; } => julia_ecallback;
^space;
*|;
}%%

/************************* Required for every parser *************************/

/* Parses a string buffer with julia code.
*
* @param *buffer The string to parse.
* @param length The length of the string to parse.
* @param count Integer flag specifying whether or not to count lines. If yes,
* uses the Ragel machine optimized for counting. Otherwise uses the Ragel
* machine optimized for returning entity positions.
* @param *callback Callback function. If count is set, callback is called for
* every line of code, comment, or blank with 'lcode', 'lcomment', and
* 'lblank' respectively. Otherwise callback is called for each entity found.
*/
void parse_julia(char *buffer, int length, int count,
void (*callback) (const char *lang, const char *entity, int s,
int e, void *udata),
void *userdata
) {
init

%% write init;
cs = (count) ? julia_en_julia_line : julia_en_julia_entity;
%% write exec;

// if no newline at EOF; callback contents of last line
if (count) { process_last_line(JULIA_LANG) }
}

#endif

/*****************************************************************************/
61 changes: 61 additions & 0 deletions test/expected_dir/julia.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
julia code module SampleOperations
julia blank
julia code export ∂x, ∂y, @binary, @multiary
julia code export Δx, Δy, Ax, Ay, volume
julia blank
julia code using Base: @propagate_inbounds
julia blank
julia code import Foobar.BoundaryConditions: fill_halo_regions!
julia blank
julia comment #####
julia comment ##### Regex
julia code regex = r"\bhello\b"
julia code string = "this is not a comment"
julia code ismatch = occursin(regex, "hello world")
julia blank
julia code abstract type AbstractOperation{LX, LY, LZ, G, T} <: AbstractField{LX, LY, LZ, G, T, 3} end
julia code const AF = AbstractField # used in unary_operations.jl, binary_operations.jl, etc
julia blank
julia code function Base.axes(f::AbstractOperation)
julia code if idx === (:, : ,:)
julia code return Base.OneTo.(size(f))
julia code else
julia code return Tuple(idx[i] isa Colon ? Base.OneTo(size(f, i)) : idx[i] for i = 1:3)
julia code end
julia code end
julia blank
julia code @inline fill_halo_regions!(::AbstractOperation, args...; kwargs...) = nothing
julia code architecture(a::AbstractOperation) = architecture(a.grid)
julia blank
julia comment """
julia comment at(loc, abstract_operation)
julia comment multline string literal
julia comment """
julia code at(loc, f) = f # fallback
julia blank
julia code include("barfoo.jl")
julia blank
julia comment # Make some operators!
julia comment #
julia comment # Some operators:
julia code import Base: sqrt, sin, cos, exp, tanh, abs, -, +, /, ^, *
julia blank
julia code @unary sqrt sin cos exp tanh abs
julia code @unary -
julia code @unary +
julia blank
julia code @binary /
julia code @binary ^
julia blank
julia comment #=
julia comment Some multiline
julia comment comment here
julia comment =#
julia blank
julia code atan(1 #=inline comment=#,0)
julia blank
julia comment # Another multiline
julia comment # comment here
julia code import Base: *
julia blank
julia code end # module
61 changes: 61 additions & 0 deletions test/src_dir/julia.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
module SampleOperations

export ∂x, ∂y, @binary, @multiary
export Δx, Δy, Ax, Ay, volume

using Base: @propagate_inbounds

import Foobar.BoundaryConditions: fill_halo_regions!

#####
##### Regex
regex = r"\bhello\b"
string = "this is not a comment"
ismatch = occursin(regex, "hello world")

abstract type AbstractOperation{LX, LY, LZ, G, T} <: AbstractField{LX, LY, LZ, G, T, 3} end
const AF = AbstractField # used in unary_operations.jl, binary_operations.jl, etc

function Base.axes(f::AbstractOperation)
if idx === (:, : ,:)
return Base.OneTo.(size(f))
else
return Tuple(idx[i] isa Colon ? Base.OneTo(size(f, i)) : idx[i] for i = 1:3)
end
end

@inline fill_halo_regions!(::AbstractOperation, args...; kwargs...) = nothing
architecture(a::AbstractOperation) = architecture(a.grid)

"""
at(loc, abstract_operation)
multline string literal
"""
at(loc, f) = f # fallback

include("barfoo.jl")

# Make some operators!
#
# Some operators:
import Base: sqrt, sin, cos, exp, tanh, abs, -, +, /, ^, *

@unary sqrt sin cos exp tanh abs
@unary -
@unary +

@binary /
@binary ^

#=
Some multiline
comment here
=#

atan(1 #=inline comment=#,0)

# Another multiline
# comment here
import Base: *

end # module
1 change: 1 addition & 0 deletions test/unit/detector_test.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ void test_detector_detect_polyglot() {
ASSERT_DETECT(LANG_CPP, "uses_cpp_headers.h");
ASSERT_DETECT(LANG_CPP, "uses_cpp_stdlib_headers.h");
ASSERT_DETECT(LANG_CPP, "uses_cpp_keywords.h");
ASSERT_DETECT(LANG_JULIA, "foo.jl");
ASSERT_DETECT(LANG_RUBY, "foo.rb");
ASSERT_DETECT(LANG_CRYSTAL, "foo.cr");
ASSERT_DETECT(LANG_MAKE, "foo.mk");
Expand Down
2 changes: 2 additions & 0 deletions test/unit/parser_test.h
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ void test_parser_verify_entity(SourceFile *sf, const char *entity,
#include "parsers/test_jam.h"
#include "parsers/test_java.h"
#include "parsers/test_javascript.h"
#include "parsers/test_julia.h"
#include "parsers/test_jsp.h"
#include "parsers/test_lisp.h"
#include "parsers/test_livecode.h"
Expand Down Expand Up @@ -317,6 +318,7 @@ void all_parser_tests() {
all_jam_tests();
all_java_tests();
all_javascript_tests();
all_julia_tests();
all_jsp_tests();
all_lisp_tests();
all_livecode_tests();
Expand Down
23 changes: 23 additions & 0 deletions test/unit/parsers/test_julia.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@

void test_julia_comments() {
test_parser_verify_parse(
test_parser_sourcefile("julia", " #comment"),
"julia", "", "#comment", 0
);
}

void test_julia_comment_entities() {
test_parser_verify_entity(
test_parser_sourcefile("julia", " #comment"),
"comment", "#comment"
);
test_parser_verify_entity(
test_parser_sourcefile("julia", "#=\ncomment\n=#"),
"comment", "#=\ncomment\n=#"
);
}

void all_julia_tests() {
test_julia_comments();
test_julia_comment_entities();
}
Loading