Added ANTLR grammar for SGF loading.
This commit is contained in:
184
data/SGF.g
Normal file
184
data/SGF.g
Normal file
@@ -0,0 +1,184 @@
|
|||||||
|
grammar SGF;
|
||||||
|
|
||||||
|
@header {package net.woodyfolsom.msproj.sgf;}
|
||||||
|
|
||||||
|
@lexer::header {package net.woodyfolsom.msproj.sgf;}
|
||||||
|
|
||||||
|
collection returns [SGFNodeCollection sgfNodeCollection]
|
||||||
|
@init {
|
||||||
|
$sgfNodeCollection = new SGFNodeCollection();
|
||||||
|
}
|
||||||
|
: (gameTree{$sgfNodeCollection.add($gameTree.sgfGameTree);})+
|
||||||
|
;
|
||||||
|
|
||||||
|
gameTree returns [SGFGameTree sgfGameTree]
|
||||||
|
@init {
|
||||||
|
$sgfGameTree = new SGFGameTree();
|
||||||
|
}
|
||||||
|
: LPAREN sequence{$sgfGameTree.setNodeSequence($sequence.nodeSequence);} (gameTree{$sgfGameTree.addSubTree(sgfGameTree);})* RPAREN
|
||||||
|
;
|
||||||
|
|
||||||
|
sequence returns [List<SGFNode> nodeSequence]
|
||||||
|
@init {
|
||||||
|
$nodeSequence = new ArrayList<SGFNode>();
|
||||||
|
}
|
||||||
|
: (node{$nodeSequence.add($node.sgfNode);})+;
|
||||||
|
|
||||||
|
node returns [SGFNode sgfNode]
|
||||||
|
@init {
|
||||||
|
$sgfNode = new SGFNode();
|
||||||
|
}
|
||||||
|
: SEMICOLON (property{$sgfNode.addProperty($property.sgfProperty);})*;
|
||||||
|
|
||||||
|
property returns [SGFProperty sgfProperty]
|
||||||
|
@init {
|
||||||
|
$sgfProperty = new SGFProperty();
|
||||||
|
}
|
||||||
|
: (numIdent{$sgfProperty.setIdentifier($numIdent.sgfIdent);}) ((LBRACKET numValue RBRACKET){$sgfProperty.addValue($numValue.sgfValue);})+
|
||||||
|
|
||||||
|
//an empty coord is a pass move
|
||||||
|
| (playerIdent{$sgfProperty.setIdentifier($playerIdent.sgfPlayer);}) ((LBRACKET RBRACKET){sgfProperty.addValue(SGFValue.EMPTY);})+
|
||||||
|
| (playerIdent{$sgfProperty.setIdentifier($playerIdent.sgfPlayer);}) ((LBRACKET coordValue RBRACKET){sgfProperty.addValue(new SGFValue<SGFCoord>($coordValue.sgfCoord));})+
|
||||||
|
|
||||||
|
// 2 rules here because the disambiguating semantic pred. for 'player' would throw NPE
|
||||||
|
| (strIdent{$sgfProperty.setIdentifier($strIdent.sgfIdent);}) ((LBRACKET RBRACKET){$sgfProperty.addValue(SGFValue.EMPTY);})
|
||||||
|
| (strIdent{$sgfProperty.setIdentifier($strIdent.sgfIdent);}) ((LBRACKET strValue RBRACKET){$sgfProperty.addValue(new SGFValue<String>($strValue.text));})+
|
||||||
|
|
||||||
|
| (result{$sgfProperty.setIdentifier(SGFIdentifier.RESULT);}) ((LBRACKET resValue RBRACKET){$sgfProperty.addValue(new SGFValue<SGFResult>(new SGFResult($resValue.text)));})+
|
||||||
|
| (komi{$sgfProperty.setIdentifier(SGFIdentifier.KOMI);}) ((LBRACKET realValue RBRACKET){$sgfProperty.addValue(new SGFValue<Double>(Double.parseDouble($realValue.text)));})+
|
||||||
|
| (coordIdent{$sgfProperty.setIdentifier($coordIdent.sgfIdent);})((LBRACKET coordValue RBRACKET){$sgfProperty.addValue(new SGFValue<SGFCoord>(new SGFCoord($coordValue.text)));})+
|
||||||
|
;
|
||||||
|
|
||||||
|
//playerIdent is a disambiguating rule
|
||||||
|
playerIdent returns [SGFIdentifier sgfPlayer]
|
||||||
|
: {(input.LT(1).getText().equals("W"))}? strIdent {$sgfPlayer = $strIdent.sgfIdent;}
|
||||||
|
| {(input.LT(1).getText().equals("B"))}? strIdent {$sgfPlayer = $strIdent.sgfIdent;}
|
||||||
|
;
|
||||||
|
|
||||||
|
strIdent returns [SGFIdentifier sgfIdent]
|
||||||
|
: charEnc{$sgfIdent = SGFIdentifier.CHARSET;}
|
||||||
|
| source
|
||||||
|
| blackCountry
|
||||||
|
| whiteCountry
|
||||||
|
| event
|
||||||
|
| playerBlack
|
||||||
|
| playerWhite
|
||||||
|
| blackRank
|
||||||
|
| whiteRank
|
||||||
|
| result
|
||||||
|
| rules
|
||||||
|
| place
|
||||||
|
| application
|
||||||
|
| copyright
|
||||||
|
| username
|
||||||
|
| date
|
||||||
|
| 'B'{$sgfIdent = SGFIdentifier.MOVE_BLACK;}
|
||||||
|
| 'W'{$sgfIdent = SGFIdentifier.MOVE_WHITE;}
|
||||||
|
//SGF grammar proper allows extensions, but this reader does not
|
||||||
|
; //if this is matched from rule playerIdent, the value is thrown away - this rule alone
|
||||||
|
//lack the context to disambiguate the single-character player movement IDs.
|
||||||
|
|
||||||
|
coordIdent returns [SGFIdentifier sgfIdent]
|
||||||
|
: addBlack{$sgfIdent = $addBlack.sgfIdent;}
|
||||||
|
| addWhite{$sgfIdent = $addWhite.sgfIdent;}
|
||||||
|
;
|
||||||
|
|
||||||
|
numIdent returns [SGFIdentifier sgfIdent]
|
||||||
|
: fileFormat{$sgfIdent = SGFIdentifier.FILE_FORMAT;}
|
||||||
|
| game{$sgfIdent = SGFIdentifier.GAME;}
|
||||||
|
| size{$sgfIdent = SGFIdentifier.SIZE;}
|
||||||
|
| time{$sgfIdent = SGFIdentifier.TIME;};
|
||||||
|
|
||||||
|
numValue returns [SGFValue<Integer> sgfValue]
|
||||||
|
: (DIGIT+){$sgfValue = new SGFValue<Integer>(Integer.parseInt($numValue.text));};
|
||||||
|
|
||||||
|
realIdent
|
||||||
|
: komi;
|
||||||
|
|
||||||
|
resValue //'R' is resign
|
||||||
|
: playerIdent PLUS ('R' | realValue);
|
||||||
|
|
||||||
|
realValue
|
||||||
|
: DIGIT+ PERIOD DIGIT+;
|
||||||
|
|
||||||
|
coordValue returns [SGFCoord sgfCoord]
|
||||||
|
: LCLETTER LCLETTER {$sgfCoord = new SGFCoord($text);}
|
||||||
|
;
|
||||||
|
|
||||||
|
fileFormat
|
||||||
|
: 'FF';
|
||||||
|
game : 'GM';
|
||||||
|
size : 'SZ';
|
||||||
|
charEnc : 'CA';
|
||||||
|
source : 'SO';
|
||||||
|
blackCountry
|
||||||
|
: 'BC';
|
||||||
|
whiteCountry
|
||||||
|
: 'WC';
|
||||||
|
event : 'EV';
|
||||||
|
playerBlack
|
||||||
|
: 'PB';
|
||||||
|
playerWhite
|
||||||
|
: 'PW';
|
||||||
|
blackRank
|
||||||
|
: 'BR';
|
||||||
|
whiteRank
|
||||||
|
: 'WR';
|
||||||
|
komi : 'KM';
|
||||||
|
result : 'RE';
|
||||||
|
rules : 'RU';
|
||||||
|
place : 'PC';
|
||||||
|
application
|
||||||
|
: 'AP';
|
||||||
|
time : 'TM';
|
||||||
|
date : 'DT';
|
||||||
|
|
||||||
|
addBlack returns [SGFIdentifier sgfIdent]
|
||||||
|
: 'AB'{$sgfIdent = SGFIdentifier.ADD_BLACK;}
|
||||||
|
;
|
||||||
|
|
||||||
|
addWhite returns [SGFIdentifier sgfIdent]
|
||||||
|
: 'AW'{$sgfIdent = SGFIdentifier.ADD_WHITE;}
|
||||||
|
;
|
||||||
|
|
||||||
|
copyright
|
||||||
|
: 'CP';
|
||||||
|
username: 'US';
|
||||||
|
|
||||||
|
strValue : (UCLETTER | LCLETTER | MINUS | DIGIT | SPACE | PERIOD | COMMA | PLUS | SLASH | COLON)+;
|
||||||
|
|
||||||
|
LPAREN : '(' ;
|
||||||
|
|
||||||
|
SEMICOLON : ';' ;
|
||||||
|
|
||||||
|
UCLETTER : 'A'..'Z';
|
||||||
|
|
||||||
|
LCLETTER : 'a'..'z';
|
||||||
|
|
||||||
|
DIGIT : '0'..'9';
|
||||||
|
|
||||||
|
LBRACKET
|
||||||
|
: '[';
|
||||||
|
|
||||||
|
RBRACKET
|
||||||
|
: ']';
|
||||||
|
|
||||||
|
RPAREN : ')';
|
||||||
|
|
||||||
|
COLON : ':';
|
||||||
|
|
||||||
|
MINUS : '-';
|
||||||
|
|
||||||
|
SPACE : ' ';
|
||||||
|
|
||||||
|
PERIOD : '.';
|
||||||
|
|
||||||
|
COMMA : ',';
|
||||||
|
|
||||||
|
PLUS : '+';
|
||||||
|
|
||||||
|
SLASH : '/';
|
||||||
|
|
||||||
|
CR : '\r'{$channel=HIDDEN;};
|
||||||
|
|
||||||
|
NEWLINE : '\n'{$channel=HIDDEN;};
|
||||||
Reference in New Issue
Block a user