我正在进行使用antlr4的第一步,并尝试以欧洲格式dd.mm.yyyy
解析部分日期。
我想要识别像15.05.2020
或7.5.20
这样的正常日期,但也要识别像05.2020
或5.20
这样的只包含月份和年份的日期,以及像2020
或20
这样的只包含年份的日期。在我的应用程序中,我希望能够访问日期(日、月和年)的所有部分,其中一些部分可能是空的/空的。
这是我到目前为止的语法。
grammar LogicalDateExpressions;
stmt : date EOF
;
date : (YEAR)
| (MONTH DOT YEAR)
| (DAY DOT MONTH DOT YEAR)
;
YEAR : ([12] [0-9] [0-9] [0-9])
| ([0-9] [0-9])
;
MONTH : ('0'? [1-9])
| ('1' [012])
;
DAY : ('0'? [1-9])
| ([12][0-9])
| ('3'[01])
;
DOT : '.';
WS : [ \t\r\n\u000C]+ -> skip;
该语法适用于单个年份(2020
),但无法识别月份-年份组合(05.2020
)。grun-tokens
告诉我以下内容。
[@0,0:1='05',<YEAR>,1:0]
[@1,2:2='.',<'.'>,1:2]
[@2,3:6='2020',<YEAR>,1:3]
[@3,9:8='<EOF>',<EOF>,2:0]
line 1:2 mismatched input '.' expecting <EOF>
因此,根据我的一点经验,我认为解析器规则date
是问题所在,我将其重写为
date : (
(DAY DOT)?
MONTH DOT
)?
YEAR
;
但我还是犯了同样的错误。然后我想也许我需要重新排序lexer规则。所以我写的不是年->月->日,而是日->月->年。但是grun
告诉我。
[@0,0:1='05',<DAY>,1:0]
[@1,2:2='.',<'.'>,1:2]
[@2,3:6='2020',<YEAR>,1:3]
[@3,9:8='<EOF>',<EOF>,2:0]
line 1:3 mismatched input '2020' expecting MONTH
我还试图更改解析器规则date
中OR'ed选项的顺序,但也没有成功。然后,我尝试更改lexer规则DAY、MONTH和yeary,使其成为解析器规则(DAY,MONTH,yeary)。在得到一些错误之后,因为解析器规则中显然不允许使用[0-9]符号,我将语法更改为这样。
date : (year)
| (month DOT year)
| (day DOT month DOT year)
;
[...]
year : (('1'|'2') DIGIT DIGIT DIGIT)
| (DIGIT DIGIT)
;
month : ('0'? DIGIT_NO_ZERO)
| ('1' ('0'|'1'|'2'))
;
day : ('0'? DIGIT_NO_ZERO)
| (('1'|'2') DIGIT)
| ('3' ('0'|'1'))
;
[...]
DIGIT : [0-9];
DIGIT_NO_ZERO : [1-9];
那也很糟糕。grun
告诉我。
[@0,0:0='0',<'0'>,1:0]
[@1,1:1='5',<DIGIT>,1:1]
[@2,2:2='.',<'.'>,1:2]
[@3,3:3='2',<'2'>,1:3]
[@4,4:4='0',<'0'>,1:4]
[@5,5:5='2',<'2'>,1:5]
[@6,6:6='0',<'0'>,1:6]
[@7,9:8='<EOF>',<EOF>,2:0]
line 1:1 no viable alternative at input '05'
据我所知,我正在寻找的语言是一种正规的语言。并且每一个输入都是明确无误的。因此,我试图将整个“逻辑”融入到lexer中,并成功地使用了下面的语法。
grammar LogicalDateExpressions;
stmt : date EOF
;
date : DT
;
DT : (
((('0'? [1-9])|([12][0-9])|('3'[01])) DOT)? // Day
(('0'? [1-9])|('1' [012])) DOT // Month
)?
((DIGIT DIGIT DIGIT DIGIT)|(DIGIT DIGIT)) // Year
;
DIGIT : [0-9];
DOT : '.';
WS : [ \t\r\n\u000C]+ -> skip;
它解析我给它的每一个输入。但问题是,每个输入都只是一个DT
。
[@0,0:6='05.2020',<DT>,1:0]
[@1,9:8='<EOF>',<EOF>,2:0]
从grun的令牌输出来看,我想我可能会理解这个问题,一天、一个月和/或一年的每一个输入都可能是模棱两可的,但作为一个整体的输入,连同点,它不应该是模棱两可的。我怎么告诉antlr?
所以我的问题是,第一个给定的语法的问题在哪里,我需要改变什么才能使它工作?
问题是lexer不是由解析器驱动的。这意味着当解析器试图匹配标记day DOT month
,并且输入为01.01
时,lexer不会为这两个01
创建day
和month
,而是创建两个month
标记。这就是ANTLR的lexer的工作原理:尝试为一个令牌获取尽可能多的字符,当有2个或更多的令牌匹配相同的字符时(比如01
可以通过日
和month
),让首先定义的令牌“win”(这是month
令牌)。这是没有办法的。
您可以这样做(未经测试):
date
: year
| month DOT year
| day DOT month DOT year
;
day
: N_01_12
| N_13_31
;
month
: N_01_12
;
year
: N_01_12
| N_13_31
| N_32_99
| N_1000_2999
;
N_01_12
: '0'? D // 01-09
| '1' [0-2] // 10-12
;
N_13_31
: '1' [3-9] // 13-19
| '2' D // 20-29
| '3' [01] // 30-31
;
N_32_99
: '3' [2-9] // 32-39
| [4-9] D // 40-99
;
N_1000_2999
: [12] D D D // 1000-2999
;
fragment D : [0-9];
我正在尝试从Cisco IOS配置解析以下命令:
在我的Android项目中,我使用了reverfit2作为API调用和GSON作为转换器。将json转换为POJO并遵循在同一项目的50+API中也使用的常用方法。 但是,在这种特定的情况下,一些项被解析并分配给变量,而其他项则不是。 如何解决这种部分解析?
我使用ANTLR Version4创建编译器。第一阶段是Lexer部分。我创建了“compilerlexer.g4”文件,并在其中输入了lexer规则。 compilerlexer.g4: null 有几十个这样的警告和错误。病因是什么? 一般问题:使用组合语法和单独使用lexer和parser有什么不同?如何连接单独的语法和lexer文件?
问题内容: 我用antlr 4.4编写了这样的语法: 然后我使用antlr 4.4生成解析器和词法分析器,此过程成功 生成类后,我编写了一些使用语法的Java代码 以上所有代码都是CSV字符串的解析器,例如:““ a”,“ b”,c“ 窗口输出: 我想知道如何从代码背后的方法(getErrors()或…)中获取此错误,而不是由于输出窗口的结果 谁能帮我 ? 问题答案: 使用ANTLR进行CSV解析
我想在Java中解析自定义的多种日期格式。这是我的代码 场景1:模式的顺序: yyMMdd'h'HH yyMMdd DateTimeFormatter-formatter=new DateTimeFormatterBuilder().appendOptional(模式的日期时间格式设置工具(“yyMMdd'h'HH”)).appddOptional(格式的日期时间格式化工具(“yyMMdd”).t
问题内容: 我有以下json: 基于的更改。 知道这一点,有没有办法使该字段保持字符串?这个想法是使用调用传递的正确处理程序,然后在其中使用正确的struct 解析字符串。 例: 先感谢您。 问题答案: 使用json.RawMessage获取字段的原始JSON文本: 像这样使用它: 在操场上跑。