使用 Antlr4 解析 PlSQL 时如何提取带有语法错误的行
Posted
技术标签:
【中文标题】使用 Antlr4 解析 PlSQL 时如何提取带有语法错误的行【英文标题】:How to extract line with syntax error when parsing PlSQL using Antlr4 【发布时间】:2020-08-27 07:05:37 【问题描述】:我正在使用来自 Github repository 的 PlSql 语法文件。如果它有语法错误,我想在我解析的 plsql 文件中加下划线。我有以下 sn-p 这样做:
public static class UnderlineListener extends BaseErrorListener
public void syntaxError(Recognizer<?, ?> recognizer,
Object offendingSymbol,
int line, int charPositionInLine,
String msg,
RecognitionException e)
System.err.println("line "+line+":"+charPositionInLine+" "+msg);
underlineError(recognizer,(Token)offendingSymbol,
line, charPositionInLine);
protected void underlineError(Recognizer recognizer,
Token offendingToken, int line,
int charPositionInLine)
CommonTokenStream tokens =
(CommonTokenStream)recognizer.getInputStream();
String input = tokens.getTokenSource().getInputStream().toString();
String[] lines = input.split("\n");
String errorLine = lines[line - 1];
System.err.println(errorLine);
for (int i=0; i<charPositionInLine; i++) System.err.print(" ");
int start = offendingToken.getStartIndex();
int stop = offendingToken.getStopIndex();
if ( start>=0 && stop>=0 )
for (int i=start; i<=stop; i++) System.err.print("^");
System.err.println();
虽然这在大多数情况下都可以正常工作,但某些脚本语言,如 PlSql,需要special handling for case-sensitivity。这意味着我必须使用CaseChangingCharStream,如下所示:
CharStream s = CharStreams.fromPath(Paths.get('test.sql'));
CaseChangingCharStream upper = new CaseChangingCharStream(s, true);
Lexer lexer = new SomeSQLLexer(upper);
现在,当我尝试使用String input = tokens.getTokenSource().getInputStream().toString();
获取UnderlineListener
中的输入文本时,我没有得到test.sql
的实际文本。这是因为 getInputStream()
正在返回 CaseChangingCharStream
对象,它没有给出我的 test.sql
所需的实际文本。
在我的案例中,如何获取实际的文件文本?一种方法是将文件内容传递给UnderlineListener
的构造函数,但我更愿意坚持上述获取实际文件文本的方法,因为它可以用于不使用CaseChangingCharStream
的情况。
【问题讨论】:
【参考方案1】:我找到了解决方法。 CaseChangingCharStream.java 的当前实现没有像 getCharStream()
这样的 getter 方法来访问 final CharStream stream;
属性。只需为其添加一个 getter 方法,我们就可以访问底层的 CharStream
对象,如下所示:
CaseChangingCharStream modifiedCharStream = (CaseChangingCharStream) tokens.getTokenSource().getInputStream();
String input = modifiedCharStream.getCharStream().toString();
【讨论】:
以上是关于使用 Antlr4 解析 PlSQL 时如何提取带有语法错误的行的主要内容,如果未能解决你的问题,请参考以下文章
如何将生成的解析树保存为 IntelliJ 上 ANTLR4 插件的 .svg 文件?