如何在听 Antlr4 语法时匹配标记?

问题描述 投票:0回答:1

我一直在研究基于别人写的非常大的语法的语言实现。我正在使用 Antlr 4.12 并以 C# 为目标。一切进展顺利,我取得了很大进步。我正在使用监听器,因为我认为这是将语法树转换为适合我的语言的操作的最简单方法。

困扰我的一件事是某种结构似乎比在 C# 中更难解析。例如,我可能正在解析表达式,其中涉及文字、运算符和函数——所有常见的东西。对于函数,有几种不同类型的函数,组合在一起作为

function_call
.

    function_call
        : ranking_windowed_function                         #RANKING_WINDOWED_FUNC
        | aggregate_windowed_function                       #AGGREGATE_WINDOWED_FUNC
        | analytic_windowed_function                        #ANALYTIC_WINDOWED_FUNC
        | built_in_functions                                #BUILT_IN_FUNC
        | scalar_function_name '(' expression_list? ')'     #SCALAR_FUNCTION
        | freetext_function                                 #FREE_TEXT
        | partition_function                                #PARTITION_FUNC
        | hierarchyid_static_method                         #HIERARCHYID_METHOD
        ;

我可能会实现

EnterSomeExpression_Context()
并在语法树中获取表达式的根。当我遍历它时,我最终会找到一个
function_callContext
。该上下文本身并不是特别有用,因为我需要知道我正在使用这些类型中的哪一种。

我如何在 C# 中发现它?我现在唯一的方法是使用

is
比较运行时类型:

    if (obj is RANKING_WINDOWEDFUNCTContext) 
    {
       // handle a ranking windowing function ...
    }
    else if (obj is BUILT_IN_FUNCContext)
    {
       // handle a built-in ...
    }
    else if (obj is FREE_TEXTContext)
    {
       // handle a free-text query ...
    }
    // and so on ...

适用于少量选择,但经过几次之后,我渴望有一种查找表的方法。而且我总是想要更直接的比较(比如与整数或枚举)而不是检查类型和转换。

这段代码应该怎么写?或者我实际上是在以正确的方式做事吗?

如果有帮助,语法是针对 T-SQL 的,在这里:https://github.com/antlr/grammars-v4/tree/master/sql/tsql 我所有的代码都在我的 JankSQL 项目中: https://github.com/mikeblas/JankSQL

c# compiler-construction antlr antlr4 abstract-syntax-tree
1个回答
0
投票

“评论”使用替代标签语法。该链接详细说明了它是如何工作的,但简而言之,您应该为语法规则中的每个替代方案设置

enterRANKING_WINDOWED_FUNC
exitRANKING_WINDOWED_FUNC
等的侦听器。每个方法都会收到一个特定于替代方案的上下文,这将更容易使用。

(注意:不确定为什么他们全部使用大写字母,这会产生奇怪的名字......)

© www.soinside.com 2019 - 2024. All rights reserved.