我正在使用 ANTLR4 来读取 C# 文件,因为我需要获取方法中的所有条件语句。为此,我重写了
visitIfStatement
方法,但该方法没有当前方法的上下文。因为我需要首先解析每个方法,然后按顺序检查其条件语句。下面的方法给了我输入文件的所有IF
条件。但我需要逐个方法的IF
条件。
问题 - 有没有办法在
IfStatementContext
内设置 visitMethod_declaration
,以便我只能在方法内获取条件。我需要这样做,因为我们正在构造的对象具有方法主体,然后它在方法主体中具有 if 条件
def visitIfStatement(self, ctx: CSharpParser.IfStatementContext):
if_statement = self.getAllText(ctx.getPayload())
for i in range(ctx.start.line, ctx.stop.line):
if i not in self.codeLineNumbers:
self.codeLineNumbers.append(i)
else:
self.presentFlag = True
if not self.presentFlag:
print("Before adding to dict" + if_statement)
result = dict(conditional_stmt=if_statement,
start_line=ctx.start.line,
end_line=ctx.stop.line,
number_of_conditionals=self.ifcounter(if_statement)
)
self.Program.DecisionNodeList.append(result)
return self.visitChildren(ctx)
您可以创建 2 个单独的侦听器:第一个侦听器在调用
enterMethod_declaration
时触发,然后调用覆盖 enterIfStatement
的第二个侦听器。第一个监听器将其 ctx: CSharpParser.Method_declarationContext
传递给第二个监听器。
快速演示:
import antlr4
from CSharpLexer import CSharpLexer
from CSharpParser import CSharpParser
from CSharpParserListener import CSharpParserListener
class MethodListener(CSharpParserListener):
def enterMethod_declaration(self, ctx: CSharpParser.Method_declarationContext):
antlr4.ParseTreeWalker.DEFAULT.walk(IfListener(), ctx)
class IfListener(CSharpParserListener):
def enterIfStatement(self, ctx:CSharpParser.IfStatementContext):
print(ctx.getText())
def main(source):
lexer = CSharpLexer(antlr4.InputStream(source))
parser = CSharpParser(antlr4.CommonTokenStream(lexer))
root = parser.compilation_unit()
antlr4.ParseTreeWalker.DEFAULT.walk(MethodListener(), root)
if __name__ == '__main__':
main("""
using System;
public class Foo
{
static Foo()
{
if (1 + 1 == 2)
{
Console.WriteLine("inside a static code block");
}
}
void Method()
{
if (1 + 1 == 2)
{
Console.WriteLine("inside a method");
}
}
}
""")
运行上面的代码时,会打印以下内容:
if(1+1==2){Console.WriteLine("inside a method");}