ANTLR4 PLSQL 语法 Python 3 缺失函数

Spe*_*dge 3 python parsing plsql lexer antlr4

我正在为 Antlr4使用这个语法https://github.com/antlr/grammars-v4/tree/master/plsql但我收到一个错误,因为它指的是一个不存在的函数。

'NameError: 名称 'IsNewlineAtPos' 未定义 '

我可以看到有人更新了 csharp 版本的两个文件(那些是额外的项目?基本词法分析器和解析器?其中包括引用以下代码中的函数的更新。

// https://docs.oracle.com/cd/E11882_01/server.112/e16604/ch_twelve034.htm#SQPUG054
REMARK_COMMENT:      'REM' {IsNewlineAtPos(-4)}? 'ARK'? (' ' ~('\r' | '\n')*)? NEWLINE_EOF -> channel(HIDDEN);

// https://docs.oracle.com/cd/E11882_01/server.112/e16604/ch_twelve032.htm#SQPUG052
PROMPT_MESSAGE:      'PRO' {IsNewlineAtPos(-4)}? 'MPT'? (' ' ~('\r' | '\n')*)? NEWLINE_EOF;

// TODO: should starts with newline
START_CMD
    //: 'STA' 'RT'? SPACE ~('\r' | '\n')* NEWLINE_EOF
    // https://docs.oracle.com/cd/B19306_01/server.102/b14357/ch12002.htm
    // https://docs.oracle.com/cd/B19306_01/server.102/b14357/ch12003.htm
    : '@' {IsNewlineAtPos(-2)}? '@'? ~('\r' | '\n')* NEWLINE_EOF
    ;
Run Code Online (Sandbox Code Playgroud)

这是 git 的更新

https://github.com/antlr/grammars-v4/commit/94887a3f4c9040578ef01b561e1d5e0ec54cbe9b

我正在使用 Python 来运行它,如果有人能告诉我他们为什么“扩展”以及他们创建的这个函数的作用,我将不胜感激。(如果他们能告诉我如何转换为 python 3,那就太棒了)

Bar*_*ers 5

这些{...}?部分称为语义谓词并包含目标特定代码(在您的情况下为 Python)。因此,这意味着IsNewlineAtPos(...)应该是在 Python 风格中定义的函数PlSqlBaseLexer,就像C#JavaPlSqlBaseLexer实现一样:

# TODO import ANTLR's runtime classes here

class PlSqlBaseLexer(Lexer):

  __init__(self, ...):
    # TODO

  def IsNewlineAtPos(self, pos):
    # TODO
Run Code Online (Sandbox Code Playgroud)

通常,ANTLR 根据您的语法创建一个词法分析器,它扩展了 ANTLR 自己的Lexer类,但是由于 PL-SQL 语法需要更多的目标特定代码,因此将以下内容添加到语法中:

options {
    superClass=PlSqlBaseLexer;
}
Run Code Online (Sandbox Code Playgroud)

它告诉 ANTLR 它需要创建一个PlSqlBaseLexer“位于”ANTLR 自己的Lexer实现和PlSqlLexer. 所以,而不是这个继承树:

Lexer
 '- PlSqlLexer
Run Code Online (Sandbox Code Playgroud)

现在变成:

Lexer
 '- PlSqlBaseLexer (including the `IsNewlineAtPos` function)
   '- PlSqlLexer
Run Code Online (Sandbox Code Playgroud)

因此,除了复制为 Java(或 C#)版本所做的工作之外,它真的没有更多。查看Java实现:

protected boolean IsNewlineAtPos(int pos)
{
    int la = _input.LA(pos);
    return la == -1 || la == '\n';
}
Run Code Online (Sandbox Code Playgroud)

与 predicate 结合{IsNewlineAtPos(-4)}?,那么当从词法分析器的当前字符位置返回 4 个字符(因此为负 4)是 -1(无/EOF)或换行符时,谓词将成功。

另请注意自述文件中的用法、重要说明部分。

  • 这是一个非常详细的回复!而且速度也很快。谢谢。我可以去哪里阅读有关创建 Base Lexers 的信息?它不在 Antlr 4 书中.. (2认同)