分析器捕获所有参数列表

本文关键字:参数 列表 分析器 | 更新日期: 2024-10-19 06:09:34

好吧,我在这方面花了两天时间,在Stack上查看了与ANTLR4有关的所有其他答案,但我无法解决这个问题。

我正在解析一个SQL表定义,它看起来像这样:

CREATE TABLE [dbo].[GeographicZones](
    [GeographicZoneID] [int] IDENTITY(1,1) NOT NULL,
    [Township] [smallint] NOT NULL,
    [Range] [smallint] NOT NULL,
    [Section] [tinyint] NOT NULL,
    [TownshipRange]  AS ((((('T'+CONVERT([varchar](3),[Township],0))+case when [Township]>(0) then 'N' else 'S' end)+'R')+CONVERT([varchar](3),[Range],0))+case when [Range]>(0) then 'E' else 'W' end),
    [LAOZone] [bit] NOT NULL,
    [MSDZone] [bit] NOT NULL,
    [ParrottZone] [bit] NOT NULL,
 CONSTRAINT [PK_GeographicZones] PRIMARY KEY CLUSTERED 
(
    [GeographicZoneID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY],
 CONSTRAINT [UK_GeographicZones_TRS] UNIQUE NONCLUSTERED 
(
    [Township] ASC,
    [Range] ASC,
    [Section] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

我不能解决的关键是TownshipRange计算列。我不关心AS语句之后()之间的内容,并且希望忽略逗号分隔符。

以下是computedColumn规则:

/**
TSql only. In code generation, this is mapped as a read-only
property. In translation, special comments are placed that
indicate that this should be a computed column.
*/
computedColumn
    : columnName AS anyExpr ( PERSISTED ( NOT NULL )? )?
    {
    logInfo( "Computed column {0}",
        $columnName.ctx.GetText() );
    }
    ;

这是anyExpr规则,它曾在ANTLR4 4.0.1:中工作

/**
Use for a parameter list (blah blah) where we don't care
about the contents. Uses a sempred to go until $open == 0.
Note that the right paren is missing from the end of the rule -
this is by design.
*/
anyExpr
locals [int open = 1]
    : Lp
    ( {$open > 0}? 
        ( ~( Lp | Rp )
        | Lp { $open++; }
        | Rp { $open--; }
        )
    )*
    ;

以下是使用ANTLR4 4.3.0:记录的输出

INFO    Computed column [TownshipRange]
line 579:22 extraneous input '(' expecting {Comma, Rp}

它失败的(是第一个嵌套的左paren。但无论开头paren后面的第一个字符是什么,它都会立即失败,并发出相同的警告。

我的"包罗万象"逻辑出了什么问题,在4.0.1和4.3之间发生了什么变化,打破了这一点?

顺便说一句(这可能与问题有关)4.3需要AGES以LL模式解析整个SQL文件,所以我使用SLL。4.0.1识别LL和SLL中的规则,并且解析时间几乎没有差异。

4.0.1是否可能只是忽略了无关的输入,而我的anyExpr一直都被破坏了?

分析器捕获所有参数列表

为什么不引用anyExpr本身?

anyExpr
 : Lp ( ~( Lp | Rp ) | anyExpr )* Rp 
 ;

这可能会导致更快的解析(我自己没有尝试!):

anyExpr
 : Lp ( ~( Lp | Rp )+ | anyExpr )* Rp 
 ;