Added ANTLR grammar for SGF loading.

This commit is contained in:
2012-11-09 18:41:25 -05:00
parent b60c176d39
commit 9b8693fc3e

184
data/SGF.g Normal file
View 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;};