antlr / antlr4

ANTLR (ANother Tool for Language Recognition) is a powerful parser generator for reading, processing, executing, or translating structured text or binary files.

Home Page:http://antlr.org

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Issue with using ANTLR4 from Julia via PyCall

AkhilAkkapelli opened this issue · comments

I'm attempting to integrate ANTLR4 libraries into my Julia project using the PyCall library.
I encounter an error when running my code:

akhil@KHUSHI:~/FortranStructureExtractor$ julia FSEFortran90.jl TestProgram/TestProgram.f90 TestProgram/TestProgramStructureJulia.DOT 
An unexpected error occurred:PyError ($(Expr(:escape, :(ccall(#= /home/akhil/.julia/packages/PyCall/1gn3u/src/pyfncall.jl:43 =# @pysym(:PyObject_Call), PyPtr, (PyPtr, PyPtr, PyPtr), o, pyargsptr, kw))))) <class 'AttributeError'>
AttributeError("'PyCall.jlwrap' object has no attribute 'enterEveryRule'")
  File "/usr/local/lib/python3.10/dist-packages/antlr4/tree/Tree.py", line 158, in walk
    self.enterRule(listener, t)
  File "/usr/local/lib/python3.10/dist-packages/antlr4/tree/Tree.py", line 177, in enterRule
    listener.enterEveryRule(ctx)
ERROR: LoadError: PyError ($(Expr(:escape, :(ccall(#= /home/akhil/.julia/packages/PyCall/1gn3u/src/pyfncall.jl:43 =# @pysym(:PyObject_Call), PyPtr, (PyPtr, PyPtr, PyPtr), o, pyargsptr, kw))))) <class 'AttributeError'>
AttributeError("'PyCall.jlwrap' object has no attribute 'enterEveryRule'")
  File "/usr/local/lib/python3.10/dist-packages/antlr4/tree/Tree.py", line 158, in walk
    self.enterRule(listener, t)
  File "/usr/local/lib/python3.10/dist-packages/antlr4/tree/Tree.py", line 177, in enterRule
    listener.enterEveryRule(ctx)
Stacktrace:
  [1] pyerr_check
    @ ~/.julia/packages/PyCall/1gn3u/src/exception.jl:75 [inlined]
  [2] pyerr_check
    @ ~/.julia/packages/PyCall/1gn3u/src/exception.jl:79 [inlined]
  [3] _handle_error(msg::String)
    @ PyCall ~/.julia/packages/PyCall/1gn3u/src/exception.jl:96
  [4] macro expansion
    @ ~/.julia/packages/PyCall/1gn3u/src/exception.jl:110 [inlined]
  [5] #107
    @ ~/.julia/packages/PyCall/1gn3u/src/pyfncall.jl:43 [inlined]
  [6] disable_sigint
    @ ./c.jl:473 [inlined]
  [7] __pycall!
    @ ~/.julia/packages/PyCall/1gn3u/src/pyfncall.jl:42 [inlined]
  [8] _pycall!(ret::PyObject, o::PyObject, args::Tuple{FSEFortran90Listener, PyObject}, nargs::Int64, kw::Ptr{Nothing})
    @ PyCall ~/.julia/packages/PyCall/1gn3u/src/pyfncall.jl:29
  [9] _pycall!(ret::PyObject, o::PyObject, args::Tuple{FSEFortran90Listener, PyObject}, kwargs::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
    @ PyCall ~/.julia/packages/PyCall/1gn3u/src/pyfncall.jl:11
 [10] (::PyObject)(::FSEFortran90Listener, ::Vararg{Any}; kwargs::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
    @ PyCall ~/.julia/packages/PyCall/1gn3u/src/pyfncall.jl:86
 [11] (::PyObject)(::FSEFortran90Listener, ::Vararg{Any})
    @ PyCall ~/.julia/packages/PyCall/1gn3u/src/pyfncall.jl:86
 [12] process_source_file(filePath::String, listener::FSEFortran90Listener)
    @ Main ~/FortranStructureExtractor/FSEFortran90.jl:161
 [13] main()
    @ Main ~/FortranStructureExtractor/FSEFortran90.jl:144
 [14] top-level scope
    @ ~/FortranStructureExtractor/FSEFortran90.jl:170
in expression starting at /home/akhil/FortranStructureExtractor/FSEFortran90.jl:170

My Julia Code (FSEFortran90.jl):

include("ProgramNode/ProgramNode.jl")
import .ProgramNodeMod: ProgramNode, ProgramNodeType, addChild, toDOT

using PyCall

antlr4 = pyimport("antlr4")
const ParseTreeWalker = antlr4.ParseTreeWalker

pushfirst!(PyVector(pyimport("sys")."path"), pwd())
Fortran90ParserListener = pyimport("Fortran90ParserListener")

mutable struct FSEFortran90Listener
    root::ProgramNode
    parentStack::Vector{ProgramNode}
end

function FSEFortran90Listener(root::ProgramNode)
    parentStack = Vector{ProgramNode}()
    push!(parentStack, root)
    return FSEFortran90Listener(root, parentStack)
end

function enterMainProgram(listener::FSEFortran90Listener, ctx)
    programStmtContext = ctx.programStmt()
    if programStmtContext !== nothing
        programNameNode = programStmtContext.NAME()
        programName = programNameNode.getText()
        programNode = ProgramNode(programName, ProgramNodeType("Program"))
        currentParent = last(listener.parentStack)
        addChild(currentParent, programNode)
        push!(listener.parentStack, programNode)
    end
end

function exitMainProgram(listener::FSEFortran90Listener, ctx)
    pop!(listener.parentStack)
end

#Some other routines ...

using ArgParse

# Import necessary modules from the local Python files
#FSEFortran90Listener = pyimport("FSEFortran90Listener")
Fortran90Lexer = pyimport("Fortran90Lexer")
Fortran90Parser = pyimport("Fortran90Parser")

# Importing necessary Python packages
const FileStream = antlr4.FileStream
const CommonTokenStream = antlr4.CommonTokenStream

function parse_arguments()
    s = ArgParseSettings()

    @add_arg_table! s begin
        "inputFilePath"
            help = "Path to the input file (.f90)"
            required = true
        "outputFilePath"
            help = "Path to the output file (.dot)"
            required = true
    end

    return parse_args(s)
end

function main()
    parsed_args = parse_arguments()

    inputFilePath = parsed_args["inputFilePath"]
    outputFilePath = parsed_args["outputFilePath"]

    fileName = basename(inputFilePath)
    root = ProgramNode(fileName, ProgramNodeType("File"))
    listener = FSEFortran90Listener(root)

    try
        process_source_file(inputFilePath, listener)
        dotRepresentation = toDOT(root)
        write_to_file(dotRepresentation, outputFilePath)
        println("DOT representation written to file successfully.")
    catch e
        println("An unexpected error occurred:", e)
        rethrow()
    end
end

function process_source_file(filePath, listener)
    input = FileStream(filePath)
    lexer = Fortran90Lexer.Fortran90Lexer(input)
    tokens = CommonTokenStream(lexer)
    parser = Fortran90Parser.Fortran90Parser(tokens)
    tree = parser.program()
    walker = ParseTreeWalker()
    walker.walk(listener, tree)
end

function write_to_file(content, filePath)
    open(filePath, "w") do f
        write(f, content)
    end
end

main()