Parsing 是否可以跟踪先例标记以解决ANTLR4中的歧义?

Parsing 是否可以跟踪先例标记以解决ANTLR4中的歧义?,parsing,antlr,antlr4,lexer,Parsing,Antlr,Antlr4,Lexer,我从ANTLR4开始,我希望在根据令牌读取执行某些操作时识别此格式。 我要做的是: 标识符:Test1([a-zA-Z09]{10}) {在personId列中插入'Test1' 代码:F0101F 全名:名字([A-Z]+)姓([A-Z]+) {在firstName列中插入FIRST_NAME.value,在firstName列中插入LAST_NAME.value lastName列} 地址:数字+街道名称([A-Z]+) {在streetName列中插入STREET_NAME.valu

我从ANTLR4开始,我希望在根据令牌读取执行某些操作时识别此格式。 我要做的是:

  • 标识符:Test1([a-zA-Z09]{10})

    {在personId列中插入'Test1'

  • 代码:F0101F

  • 全名:名字([A-Z]+)姓([A-Z]+) {在firstName列中插入FIRST_NAME.value,在firstName列中插入LAST_NAME.value lastName列}

  • 地址:数字+街道名称([A-Z]+) {在streetName列中插入STREET_NAME.value}

  • 其他信息:([A-Z]+) {在其他列中插入其他信息.value}

我所做的:

prod
:
    read_information+
;

read_information
:
    {getCurrentToken().getType()== ID }?

    idElement
    |
    {getCurrentToken().getType()== CODE }?

    codeElement
    |
    {getCurrentToken().getType()== FULLNAME}?

    fullNameElement
    |
    {getCurrentToken().getType()== STREET}?

    streetElement
    |
    {getCurrentToken().getType()== OTHER}?

    otherElement
;

codeElement
:
    CODE
    {getCurrentToken().getText().matches("[A-F0-9]{6}")}?
    codeInformation
    |
    {/*throw someException*/}
;

codeInformation
:
    HEXCODE
;

HEXCODE
:
    [a-fA-F0-9]+
;

CODE
:
    'CODE:'
;

otherElement
:
    OTHER otherInformation
;

otherInformation
:
    STR
;

OTHER
:
    'OTHER:'
;

streetElement
:
    STREET streetInformation
;

STREET
:
    'STREET:'
;

streetInformation
:
    STR
;

STR
:
    [a-zA-Z0-9]+
;

WORD
:
    [a-zA-Z]+
;

fullNameElement
:
    FULLNAME firstNameInformation lastNameInformation
;

FULLNAME
:
    'FULL_NAME:'
;

firstNameInformation
:
    WORD
;

lastNameInformation
:
    WORD
;

idElement
:
    ID idInformation
;

ID
:
    'ID:'
;

idInformation
:
    {getCurrentToken().getText().length()<=10}?

    STR
;
prod
:
阅读信息+
;
阅读信息
:
{getCurrentToken().getType()==ID}?
元素
|
{getCurrentToken().getType()==CODE}?
代码元素
|
{getCurrentToken().getType()==FULLNAME}?
全名元素
|
{getCurrentToken().getType()==STREET}?
应力元素
|
{getCurrentToken().getType()==OTHER}?
其他元素
;
代码元素
:
代码
{getCurrentToken().getText().matches(“[A-F0-9]{6}”)}?
代码信息
|
{/*抛出一些异常*/}
;
代码信息
:
六进制码
;
六进制码
:
[a-fA-F0-9]+
;
代码
:
'代码:'
;
其他元素
:
其他资料
;
其他信息
:
STR
;
其他
:
“其他:”
;
应力元素
:
街道信息
;
街头
:
“街道:”
;
街道信息
:
STR
;
STR
:
[a-zA-Z0-9]+
;
单词
:
[a-zA-Z]+
;
全名元素
:
全名firstname信息lastname信息
;
全名
:
'全名:'
;
名字信息
:
单词
;
姓氏信息
:
单词
;
元素
:
ID生成
;
身份证件
:
“ID:”
;
碘形成
:

{getCurrentToken().getText().length()为了找出生成的解析器将输入哪些规则(即访问哪个上下文),可以使用ANTLR创建访问者。对此有一个很好的解释(请参阅Bart Kiers的回复)

通常,如果有两个相同的规则,您可以将它们合并为一个,然后标记它们的用法。例如,对于这些规则:

firstNameInformation
:
    WORD
;

lastNameInformation
:
    WORD
;
没有理由实际拥有它们。相反,你可以这样写全名的语法:

fullNameElement
:
    FULLNAME firstname=WORD lastname=WORD
;
在这种情况下,您只使用单词token,但是您可以标记它们,以便在执行树漫游时可以区分它们