我需要一个Java游戏描述语言解析器(GDL)
为此,我目前正在尝试使用ANTLR4。
下面给出的我当前的语法似乎不正确,或者至少生成的解析器不识别游戏描述,我将在下面提供这些描述。
ANTLR4-语法:
grammar GDL;
description : (gdlRule | sentence)+ ;
gdlRule : '(' SP? '<=' SP? sentence (SP literal)* SP? ')';
sentence : propLit | ( '(' relLit ')' );
literal : ( '(' SP? (orLit | notLit | distinctLit | relLit) SP? ')' )
| ( '(' (orLit | notLit | distinctLit | relLit) ')' )
| propLit;
notLit : 'not' SP literal | '~' literal;
orLit : 'or' SP literal* ;
distinctLit : 'distinct' SP term SP term;
propLit : constant;
relLit : constant (SP term)+;
term : ( '(' funcTerm ')' ) | varTerm | constTerm;
funcTerm : constant (SP term)*;
varTerm : '?' constant;
constTerm : constant;
constant : ident | number;
/* ident is any string of letters, digits, and underscores */
ident: ID;
number: NR;
NR : [0-9]+;
ID : [a-zA-Z] [a-zA-Z0-9]* ;
SP : ' '+;
COMMENT : ';'[A-Za-z0-9; \r\t]*'\n' -> skip;
WS : [ ;\t\r\n]+ -> skip
;GDL中给出的游戏描述:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; Tictictoe
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(role white)
(role black)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(init (cell 1 1 b))
(init (cell 1 2 b))
(init (cell 1 3 b))
(init (cell 2 1 b))
(init (cell 2 2 b))
(init (cell 2 3 b))
(init (cell 3 1 b))
(init (cell 3 2 b))
(init (cell 3 3 b))
(init (step 1))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(<= (next (cell ?j ?k x))
(true (cell ?j ?k b))
(does white (mark ?j ?k))
(does black (mark ?m ?n))
(or (distinct ?j ?m) (distinct ?k ?n)))
(<= (next (cell ?m ?n o))
(true (cell ?m ?n b))
(does white (mark ?j ?k))
(does black (mark ?m ?n))
(or (distinct ?j ?m) (distinct ?k ?n)))
(<= (next (cell ?m ?n b))
(true (cell ?m ?n b))
(does white (mark ?m ?n))
(does black (mark ?m ?n)))
(<= (next (cell ?p ?q b))
(true (cell ?p ?q b))
(does white (mark ?j ?k))
(does black (mark ?m ?n))
(or (distinct ?j ?p) (distinct ?k ?q))
(or (distinct ?m ?p) (distinct ?n ?q)))
(<= (next (cell ?m ?n ?w))
(true (cell ?m ?n ?w))
(distinct ?w b))
(<= (next (step ?y))
(true (step ?x))
(succ ?x ?y))
(succ 1 2)
(succ 2 3)
(succ 3 4)
(succ 4 5)
(succ 5 6)
(succ 6 7)
(<= (row ?m ?x)
(true (cell ?m 1 ?x))
(true (cell ?m 2 ?x))
(true (cell ?m 3 ?x)))
(<= (column ?n ?x)
(true (cell 1 ?n ?x))
(true (cell 2 ?n ?x))
(true (cell 3 ?n ?x)))
(<= (diagonal ?x)
(true (cell 1 1 ?x))
(true (cell 2 2 ?x))
(true (cell 3 3 ?x)))
(<= (diagonal ?x)
(true (cell 1 3 ?x))
(true (cell 2 2 ?x))
(true (cell 3 1 ?x)))
(<= (line ?x) (row ?m ?x))
(<= (line ?x) (column ?m ?x))
(<= (line ?x) (diagonal ?x))
(<= nolinex
(not (line x)))
(<= nolineo
(not (line o)))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(<= (legal white (mark ?x ?y))
(true (cell ?x ?y b)))
(<= (legal black (mark ?x ?y))
(true (cell ?x ?y b)))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(<= (goal white 50)
(line x)
(line o))
(<= (goal white 100)
(line x)
nolineo)
(<= (goal white 0)
nolinex
(line o))
(<= (goal white 50)
nolinex
nolineo)
(<= (goal black 50)
(line x)
(line o))
(<= (goal black 100)
nolinex
(line o))
(<= (goal black 0)
(line x)
nolineo)
(<= (goal black 50)
nolinex
nolineo)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(<= terminal
(true (step 7)))
(<= terminal
(line x))
(<= terminal
(line o))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;生成的解析器的错误输出:
line 24:6 mismatched input '(' expecting {')', SP}
line 27:7 no viable alternative at input '(or'我不知道我需要改变什么,也不知道如何得到正确的语法
如能提供任何帮助,将不胜感激。
发布于 2016-05-13 10:39:18
(至少)有三件事是不正确的:
;规则中包括WS,它是COMMENT的开始。COMMENT规则说,它需要以中断行结束。但是,WS规则中已经包含了行中断,它将不允许以EOF结尾的注释(没有行中断)。SP:空间需要跳过,并且不包括在解析器规则中。试着做这样的事情:
grammar GDL;
description : (gdlRule | sentence)+ ;
gdlRule : '(' '<=' sentence literal* ')';
sentence : propLit | ( '(' relLit ')' );
literal
: ( '(' (orLit | notLit | distinctLit | relLit) ')' )
| ( '(' (orLit | notLit | distinctLit | relLit) ')' )
| propLit
;
notLit : 'not' literal | '~' literal;
orLit : 'or' literal* ;
distinctLit : 'distinct' term term;
propLit : constant;
relLit : constant (term)+;
term : ( '(' funcTerm ')' ) | varTerm | constTerm;
funcTerm : constant (term)*;
varTerm : '?' constant;
constTerm : constant;
constant : ident | number;
ident: ID;
number: NR;
NR : [0-9]+;
ID : [a-zA-Z] [a-zA-Z0-9]*;
COMMENT : ';'[A-Za-z0-9; \r\t]* -> skip;
WS : [ \t\r\n]+ -> skip;发布于 2016-05-13 10:25:03
问题在于您对空格的处理。
您有两个规则,其中一个规则创建一个令牌:
SP : ' '+;另一个简单地忽略了空格:
WS : [ ;\t\r\n]+ -> skip如果空格以空格字符开头,则第一个规则将适用,您将得到一个SP令牌。如果空格以WS规则中列出的换行符或其他字符开头,则将忽略整个空白运行。
由于语法在某些点坚持使用SP标记,忽略的空格将导致语法错误。
我看不出有什么理由用明确的空格使你的语法复杂化。我会去掉SP,删除语法中对它的所有引用,让WS忽略空格。
我还将从WS中删除分号,以避免与COMMENT的交互。注1和我将简化COMMENT,使其只忽略在行尾设置一个分号,而不是生成一个有效注释字符的列表。(如果您想在注释中添加逗号或*,该怎么办?)
备注
COMMENT在第一个字符上不匹配,但WS匹配,您就会看到这个问题。然后,WS将匹配(并忽略)换行符、分号行、下一行、下一行开始处的分号以及下面的空格,使Tictictoe被扫描为ID,这将导致解析错误。
如果任何其他注释不是一行分号,您也会看到它。目前,这些都被扫描为WS,在评论前以换行符作为主角。这恰好是好的,因为注释只包含分号。但是任何其他非空格字符都会终止WS,然后意外地被解析为程序文本。https://stackoverflow.com/questions/37204950
复制相似问题