Parsing 在任何其他规则的中间匹配规则

Parsing 在任何其他规则的中间匹配规则,parsing,antlr,predicate,greedy,Parsing,Antlr,Predicate,Greedy,我正在开发一种数据定义语言,它使用大括号来标识层次结构 typeA idS { paramX = value typeB idT { paramY = value } } 有大量不同的规则来验证哪些参数和子类型对特定类型的块有效 我想添加功能,以允许在任何现有块或名称/值对集周围放置特殊块类型 BLOCK { typeA idS { BLOCK { paramX

我正在开发一种数据定义语言,它使用大括号来标识层次结构

typeA idS
{
    paramX = value
    typeB idT
    {
        paramY = value
    }       
}
有大量不同的规则来验证哪些参数和子类型对特定类型的块有效

我想添加功能,以允许在任何现有块或名称/值对集周围放置特殊块类型

BLOCK
{
    typeA idS
    {
        BLOCK
        {
            paramX = value
        }
        BLOCK
        {       
            typeB idT
            {
                paramY = value
            }
        }       
    }
 }
有没有一种方法可以创建一个块来允许其中的任何内容,而不必专门向每个现有类型添加块支持,也不必丢失解析器检查子参数/类型是否对给定的父级有效

我试过使用通配符,贪婪和非贪婪都没有用

block: BLOCK '{' (options {greedy=false;} : .* ) '}'
其他答案表明,语法谓词可以解决这个问题,但我不知道如何使用它们(请链接到任何在线来源)

有没有办法做到这一点而不涉及所有其他规则?(希望不需要许多BLOCK_子类型来保持父/子检查完好无损)。我担心可读性和维护问题


谢谢

这似乎需要多次传球

在第一步中,您基本上可以只解析块和数据,而不进行任何验证,例如

blockType: BLOCK OPEN_BRACE type CLOSE_BRACE -> (BLOCK type);
blockParam: BLOCK OPEN_BRACE param CLOSE_BRACE -> (BLOCK param);
type: blockType | (typeName idName OPEN_BRACE param CLOSE_BRACE ->
                 (TYPE typeName idName param));
param: blockParam | (paramName EQUALS value -> (PARAM paramName value));
这将产生一个AST,作为第二次传递的输入。在那里,你需要像这样的规则

paramA: (PARAM paramNameA value) | (BLOCK paramA);
typeB: (TYPE typeNameB idNameB paramB) | (BLOCK typeB);
块结构侵入了您的所有规则,但它是以标准方式这样做的。您甚至可以编写一些东西来修改语法文件以添加它

您也可能希望使用预处理器。用一个特殊的、否则无效的字符串替换块{和匹配的}并不难写。然后每个规则都会有一个表单BLOCK_START?填充块?结束?。您应该能够添加操作,以确保不会无始无终地开始,但如果预处理器正在工作(并拒绝实际的特殊文本),则不可能这样做

所有这些可能比您想要的更具侵入性,但构造相当具有侵入性


我假设额外的标签实际上触发了某种特殊的处理。如果它们只是语法上的糖,那么任何一种解决方案都是局部的。预处理器只会删除块文本。AST解决方案将生成相同的AST,无论它是否匹配块或裸语句。

是。通常形式为:type_param_list:param value | otherType_defn type_defn:type ID'{'type_param_list*'}';问题是,我有几十种类型和数百个参数,以各种组合进行组织。我可以在它们周围手动添加块规则,但我正试图避免它。特别是为了将子对象保持在父对象的上下文中,我需要添加
type_a_block:block'{'type_a_defn'}';类型a参数块:块“{”类型a参数列表“}”;类型a_defn:每种类型的类型a'{(类型a参数列表|类型a参数块)*'}
。我对ANTLR没有什么经验,但它觉得这是可以用某种性感的方式解决的,因为这样你就可以在块中添加无效的子类型。如果A(B(C))和X(Y(Z))是有效的,而BLOCK(A | B | C | X | Y | Z)是有效的,那么A(BLOCK(Z))是有效的。除了在每个规则周围手动添加这些块之外,我看不到任何其他方法。BLOCK部分用于向主文本的段添加上下文。将其视为突出显示的部分。块实际上是一个具有自己的标记和子规则的规则。你是如何看待将多个过程链接在一起的?我不确定我是否理解你关于将过程链接在一起的问题。您需要一个驱动程序来运行解析器。将输入文本传递给解析器。它返回一个AST,您将其传递给树行者。我相信Antr4没有树漫游器,在这种情况下,您必须使用访问者模式来替代它。(我没有使用antlr4,所以我不太清楚它是如何工作的。)我指的是将AST传递给树行者。但我当时并不知道。