【问题标题】:ANTLR4 PLSQL Grammar Python 3 Missing FunctionANTLR4 PLSQL 语法 Python 3 缺少函数
【发布时间】:2018-10-08 20:53:04
【问题描述】:

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

'NameError: name '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
    ;

这是 git 的更新

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

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

【问题讨论】:

    标签: python parsing plsql antlr4 lexer


    【解决方案1】:

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

    # TODO import ANTLR's runtime classes here
    
    class PlSqlBaseLexer(Lexer):
    
      __init__(self, ...):
        # TODO
    
      def IsNewlineAtPos(self, pos):
        # TODO
    

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

    options {
        superClass=PlSqlBaseLexer;
    }
    

    它告诉 ANTLR 它需要创建一个“位于”ANTLR 自己的Lexer 实现和PlSqlLexer 之间的PlSqlBaseLexer。所以代替这个继承树:

    Lexer
     '- PlSqlLexer
    

    现在变成:

    Lexer
     '- PlSqlBaseLexer (including the `IsNewlineAtPos` function)
       '- PlSqlLexer
    

    因此,除了复制为 Java(或 C#)版本所做的工作外,没有什么比这更重要的了。查看 Java 实现:

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

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

    还要注意自述文件中的Usage, important note 部分。

    【讨论】:

    • 那是一个非常详细的回复!也很快。谢谢你。我可以去任何地方阅读有关创建 Base Lexers 的信息吗?它不在 Antlr 4 书中..
    • @SpencerAttridge 结帐我的编辑,我在其中添加了有关superClass的更多信息
    • 首先是我的 BaseParser 工作和第二个 BaseLister .. 但仍然存在问题......恐怕我只是在挣扎。 import sys from typing.io import TextIO from antlr4 import * class PlSqlBaseParser(Parser): def __init__(self, input:TokenStream, output:TextIO = sys.stdout): super().__init__(input) import sys from antlr4 import * class PlSqlBaseLexer(Lexer): def __init__(self,CharStream,output): super().__init__(input) def IsNewlineAtPos(self,pos): if self._input.LA(pos) -1: if la == '\n': return True
    • 仔细查看 Java 和 C# 示例类 PlSqlBase...:有一个用于词法分析器,一个用于解析器。 IsNewlineAtPos(...) 函数应该放在词法分析器中。
    • @SpencerAttridge 我在你的另一个问题中发布了一个小演示:stackoverflow.com/questions/52673751/…HTH
    猜你喜欢
    • 2019-03-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-30
    相关资源
    最近更新 更多