递归地使用 Antlr4 解析器和监听器

Recursively working with Antlr4 parsers and listeners

我正在从事一个项目来解析类似布尔的 DSL 并将其转换为特定的 JSON 格式。我构建了一个 classes 的一般层次结构来完成此任务,但我不确定从哪里开始将解析树转换为我想要的数据结构。

这是我的语法:

grammar filter;

filter: category EOF;

category
    : LPAREN category RPAREN # ParenCat
    | category AND category # CatAndBlock
    | label COLON expression # CategoryBlock
    ;

expression
    : LPAREN expression RPAREN  # ParenExp
    | NOT expression            # NotBlock
    | expression AND expression  # AndBlock
    | expression OR expression   # OrBlock
    | atom # AtomExp
    ;

label
    : ALPHANUM
    ;

atom 
    : ALPHANUM
    ;

这里是一个输入字符串的例子:

( cat1:( ( (1 OR 2 ) AND ( 3 ) ) ) ) AND cat2:( 4 )

使用以下解析树:

这是我希望实现的 class 层次结构的粗略草图(每个 class 都有自己的 'write' 方法):

CategoryContainer: LinkedList<Category>
    Category: LinkedList<ItemBlock> list, String categoryName #CategoryBlock
        ItemBlock: LinkedList<ItemBlock> list, String type
            AndBlock extends ItemBlock
            OrBlock extends ItemBlock
            NotBlock extends ItemBlock
            AtomBlock extends ItemBlock: list = null, String value = "atomValue"

我一直在为听众浏览一些教程,并且对正在发生的事情有一个非常扎实的了解。但是,我似乎找不到太多关于递归问题的信息,就像我正在处理的问题一样。您对我如何开始有任何建议吗?

编辑:澄清我希望实现的目标,

例如输入字符串:

cat1:(4 AND 5) AND cat2:( 4 )

我想递归生成以下 classes(括号列表符号代表各自的链表):

CategoryContainer: 
[
    Category: categoryName="cat1", # CategoryBlock Listener
    [ 
        AndBlock: [ AtomBlock: value="4", AtomBlock: value="5" ] # AndBlock Listener
    ],
    Category: categoryName="cat2", # CategoryBlock Listener
    [
        AtomBlock: value="4" # AtomBlock Listener
    ]
]

既然您提到您已经回顾了监听器模式,那么我的建议如下:

  1. 创建监听器并将其连接到 TreeWalker
  2. Listener 支持覆盖 "Enter"(沿着树向下)和 "Exit"(回到树上)事件。为每个“可用的退出事件”创建一个简单的硬编码覆盖。
  3. 运行 应用程序。您将看到深度优先遍历和递归在起作用。
  4. 从那里,更新您的 "Exit" 事件覆盖以添加到您的链表结构,或者基于堆栈的结构也适用于展开递归。
  5. 无论哪种情况,完成后,您都会得到与您提议的结构非常相似的东西。

使用 Listener 和 Exit 事件,为您处理递归和遍历。你会发现它非常有用。