Report error conditions instead of just doing nothing.
[tagua/yd.git] / src / pgnparser.cpp
blobd2f3fa9095008d9f7c6bd7be430d15e278696be0
1 /*
2 Copyright (c) 2006 Paolo Capriotti <p.capriotti@gmail.com>
3 (c) 2006 Maurizio Monge <maurizio.monge@kdemail.net>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9 */
11 #include "pgnparser.h"
12 #include <QRegExp>
13 #include <KDebug>
15 QRegExp PGN::number("^(\\d+)(?:(?:\\.\\s+)?(\\.\\.\\.)|\\.?)?");
16 QRegExp PGN::begin_var("^\\(");
17 QRegExp PGN::end_var("^\\)");
18 QRegExp PGN::comment("^\\{[^}]*\\}");
19 QRegExp PGN::comment2("^;[^\\n]*\\n");
20 QRegExp PGN::wsPattern("^\\s+");
21 QRegExp PGN::tag("^\\[(\\S+)\\s+\"((?:[^\"]|\\\\\")*)\"\\]");
22 QRegExp PGN::move_tag("^\\$(\\d+)");
23 QRegExp PGN::move("^[^$\\{\\(\\[\\s][^\\{\\(\\)\\[\\s]*");
24 QRegExp PGN::result("^(?:\\*|1-0|0-1|1/2-1/2)");
25 QRegExp PGN::time("^\\([\\d:.]*\\)");
26 QRegExp PGN::eol("(?:[ \t]\r?\n\r?|\r?\n\r?[ \t]|\r?\n\r?)");
28 bool PGN::tryRegExp(QRegExp& re, const QString& str, int& offset) {
29 if (re.indexIn(str, offset, QRegExp::CaretAtOffset) != -1) {
30 offset += re.matchedLength();
31 return true;
33 else return false;
36 #define IGNORE(re) if (tryRegExp((re), pgn, offset)) continue;
37 bool PGN::parse(const QString& pgn) {
38 int offset = 0;
40 while (offset < pgn.length()) {
41 IGNORE(wsPattern);
43 // read result
44 if (result.indexIn(pgn, offset, QRegExp::CaretAtOffset) != -1) {
45 QString res = pgn.mid(offset, result.matchedLength());
46 offset += result.matchedLength();
47 return true;
50 IGNORE(comment2);
51 IGNORE(time);
53 // read comment
54 if (tag.indexIn(pgn, offset, QRegExp::CaretAtOffset) != -1) {
55 m_tags[tag.cap(1)] = tag.cap(2);
56 offset += tag.matchedLength();
57 continue;
60 // read comment
61 if (comment.indexIn(pgn, offset, QRegExp::CaretAtOffset) != -1) {
62 m_entries.push_back(pgn.mid(offset + 1, comment.matchedLength() - 2).replace(eol, " "));
63 offset += comment.matchedLength();
64 continue;
67 // read var, 1
68 if (begin_var.indexIn(pgn, offset, QRegExp::CaretAtOffset) != -1) {
69 m_entries.push_back(BeginVariation());
70 offset += begin_var.matchedLength();
71 continue;
74 // read var, 2
75 if (end_var.indexIn(pgn, offset, QRegExp::CaretAtOffset) != -1) {
76 m_entries.push_back(EndVariation());
77 offset += end_var.matchedLength();
78 continue;
81 // read move tag
82 if (move_tag.indexIn(pgn, offset, QRegExp::CaretAtOffset) != -1) {
83 // not nothing :)
84 tryRegExp(wsPattern, pgn, offset);
87 int num = 0;
89 // read number, and do not continue
90 if (number.indexIn(pgn, offset, QRegExp::CaretAtOffset) != -1) {
91 num = number.cap(1).toInt()*2 + (number.cap(2).isEmpty() ? 0 : 1);
92 offset += number.matchedLength();
93 tryRegExp(wsPattern, pgn, offset);
96 // read move
97 if (move.indexIn(pgn, offset, QRegExp::CaretAtOffset) != -1) {
98 m_entries.push_back(Move(num, move.cap(0)));
99 offset += move.matchedLength();
100 continue;
103 // parse error!
104 kDebug() << "pgn parse error! at" << pgn.mid(offset, 100);
105 return false;
108 return true;
110 #undef IGNORE
112 PGN::PGN(const QString& str) {
113 m_valid = parse(str);