antlr / antlr/antlr4

Issue with using ANTLR4 from Julia via PyCall

Open
#4,604 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
Java
Stars
19k
Forks
3.5k
PR merge metrics
No merged PRs in 30d

Description

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)))))
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)))))
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()
```

Contributor guide

Open the contributing guide

Research direction

Start with FSEFortran90.jl's process_source_file and the FSEFortran90Listener definition, then compare the object passed to ParseTreeWalker.walk with the Python runtime's enterEveryRule call in antlr4/tree/Tree.py. Reproduce the reported AttributeError with the supplied Fortran input and establish whether the listener integration is accepted by PyCall; done means a minimal, documented fix or a confirmed ANTLR issue.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
compilers
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.