使用Antlr解析语义版本

问题描述

我将SemVer 2 BNF grammar转换为以下Antlr语法。

struct QrCodeView: View {
    var body: some View { 
        Text("QrCode")
    }
}

但是解析grammar SemVer; @header { package com.me.semver; } semVer : normal ('-' preRelease)? ('+' build)? ; normal : major '.' minor '.' patch ; major : NUM ; minor : NUM ; patch : NUM ; preRelease : PRE_RELEASE ('.' preRelease)* ; build : BUILD ('.' build)*; NUM : '0' | POSITIVE_DIGIT | POSITIVE_DIGIT DIGITS ; BUILD : ALPHANUM | DIGITS ; PRE_RELEASE : ALPHANUM | NUM ; fragment ALPHANUM : NON_DIGIT | NON_DIGIT CHARS | CHARS NON_DIGIT | CHARS NON_DIGIT CHARS ; fragment CHARS : CHAR+ ; fragment CHAR : DIGIT | NON_DIGIT ; fragment NON_DIGIT : LETTER | '-' ; fragment DIGITS : DIGIT+ ; fragment DIGIT : '0' | POSITIVE_DIGIT ; fragment POSITIVE_DIGIT : [1-9] ; fragment LETTER : [a-zA-Z] ; 会出现以下错误

第1行第4行的输入“ 0-beta”不匹配,期望NUM

侦听器的输出如下:

1.0.0-beta+exp.sha.5114f85

很明显,补丁版本不是应该的。正确的输出应为normal: 1.0.0-beta Major: 1 Minor: 0 Patch: 0-beta Build: exp.sha.5114f85 Build: sha.5114f85 Build: 5114f85 Patch = 0Pre release = beta

我该如何修正语法?

解决方法

您有太多重叠的词法分析器规则。例如,输入0可以通过以下3条规则中的任何一条进行匹配:

NUM : '0'
    | POSITIVE_DIGIT
    | POSITIVE_DIGIT DIGITS
    ;
BUILD : ALPHANUM
      | DIGITS
      ;
PRE_RELEASE : ALPHANUM
            | NUM
            ;

,由于NUM放在首位,因此输入0将始终成为NUM令牌。解析器尝试匹配什么令牌都没有关系,它将始终是NUM令牌。

这就是ANTLR的词法分析器的工作方式:

  1. 它尝试为每个令牌匹配尽可能多的字符,并且
  2. 当两个或多个词法分析器规则匹配相同数量的字符时,第一个定义为“获胜”。

鉴于您的语法和输入"1.0.0-beta+exp.sha.5114f85",将创建以下标记:

NUM                       `1`
null                      `.`
NUM                       `0`
null                      `.`
BUILD                     `0-beta`
null                      `+`
BUILD                     `exp`
null                      `.`
BUILD                     `sha`
null                      `.`
BUILD                     `5114f85`

请注意,0-beta被标记为单个BUILD标记(规则1)。

您应该做的是定义不重叠的词法分析器规则。在您的情况下,这意味着要定义以下规则/令牌:

HYPHEN
 : '-'
 ;

PLUS
 : '+'
 ;

DOT
 : '.'
 ;

ZERO_DIGIT
 : '0'
 ;

POSITIVE_DIGIT
 : [1-9]
 ;

LETTER
 : [a-zA-Z]
 ;

,然后像DIGITDIGITS这样的规则将变成解析器规则:

digits
 : digit+
 ;

digit
 : ZERO_DIGIT
 | POSITIVE_DIGIT
 ;

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...