[LIB-9] Add SAN, NAG, move number and result PGN tokens
[chesshog.git] / chesshog-format / src / main / java / org / hedgecode / chess / pgn / token / Tokenizer.java
index 9a843a0..be3b34d 100644 (file)
@@ -19,8 +19,11 @@ package org.hedgecode.chess.pgn.token;
 import java.util.regex.Pattern;
 
 import org.hedgecode.chess.ParseException;
+import org.hedgecode.chess.pgn.PGNUtils;
 import org.hedgecode.chess.pgn.entity.Game;
 
+import static org.hedgecode.chess.pgn.PGNConstants.*;
+
 /**
  * Tokenizer
  *
@@ -45,18 +48,22 @@ public class Tokenizer {
         }
     }
 
-    private static final Pattern TAG_PATTERN = Pattern.compile("^\\[[^]]+\\]$", Pattern.MULTILINE);
-    private static final Pattern EMPTY_PATTERN = Pattern.compile("^\\s*$", Pattern.MULTILINE);
-    private static final Pattern MOVES_PATTERN = Pattern.compile("^\\s*([^\\s])", Pattern.MULTILINE);
+    private static final Pattern TAG_PATTERN = Pattern.compile("^\\[[^]]+\\]$");
+    private static final Pattern EMPTY_PATTERN = Pattern.compile("^\\s*$");
+    private static final Pattern MOVES_PATTERN = Pattern.compile("^\\s*[0-9{(;*]+");
 
-    private final String pgn;
+    private final String originalPgn;
 
     private Token<Game> token;
     private String tokenPgn;
 
+    private boolean isTagExists = false;
+    private boolean isEmptyExists = false;
+    private boolean isMovesExists = false;
+
     public Tokenizer(String pgn) {
-        this.pgn = pgn;
-        this.tokenPgn = pgn;
+        this.originalPgn = pgn;
+        this.tokenPgn = pgn.endsWith(PGN_CRLF) ? pgn : pgn.concat(PGN_CRLF);
     }
 
     public boolean hasToken() {
@@ -65,29 +72,43 @@ public class Tokenizer {
     }
 
     public void token(Game game) throws ParseException {
-        if (token == null) {
-            throw new ParseException("parse.pgn.null.token");
-        }
+        assertToken();
         int index = token.token(game, tokenPgn);
         tokenPgn = tokenPgn.substring(index);
         token = null;
     }
 
-    public String sourcePgn() {
-        return pgn;
+    public String originalPgn() {
+        return originalPgn;
     }
 
     private void assignToken() {
         token = null;
         if (!tokenPgn.isEmpty()) {
-            if (TAG_PATTERN.matcher(tokenPgn).find()) {
+            String pgnLine = PGNUtils.nextLine(tokenPgn);
+            if (TAG_PATTERN.matcher(pgnLine).find()) {
+                isTagExists = true;
                 token = Type.TAG.token();
-            } else if (EMPTY_PATTERN.matcher(tokenPgn).find()) {
+            } else if (EMPTY_PATTERN.matcher(pgnLine).find()) {
+                isEmptyExists = true;
                 token = Type.EMPTY.token();
-            } else if (MOVES_PATTERN.matcher(tokenPgn).find()) {
+            } else if (MOVES_PATTERN.matcher(pgnLine).find()) {
+                isMovesExists = true;
                 token = Type.MOVES.token();
             }
         }
     }
 
+    private void assertToken() throws ParseException {
+        if (token == null) {
+            throw new ParseException("parse.pgn.null.token");
+        } else {
+            if (!isTagExists && (isEmptyExists || isMovesExists)) {
+                throw new ParseException("parse.pgn.tag.not.exist");
+            } else if (!isEmptyExists && isMovesExists) {
+                throw new ParseException("parse.pgn.missed.empty");
+            }
+        }
+    }
+
 }