Bläddra i källkod

better parsing

Zoadian 10 år sedan
förälder
incheckning
f8aeba8b6f
6 ändrade filer med 482 tillägg och 343 borttagningar
  1. 27 6
      instruction.cpp
  2. 4 2
      instruction.h
  3. 16 9
      mainwindow.cpp
  4. 389 221
      parse.cpp
  5. 6 73
      parse.h
  6. 40 32
      simulator.cpp

+ 27 - 6
instruction.cpp

@@ -1,10 +1,31 @@
 #include "instruction.h"
 
-Instruction::Instruction(Command _command, Params _params, Parameter _a, Parameter _b, Parameter _c)
-    : command(_command)
-    , params(_params)
-    , a(_a)
-    , b(_b)
-    , c(_c)
+#include <utility>
+using namespace std;
+
+Instruction::Instruction()
+    : command(DIE)
+    , params(N)
+    , a(0)
+    , b(0)
+    , c(0)
+{
+}
+
+Instruction::Instruction(const Instruction& inst)
+    : command(inst.command)
+    , params(inst.params)
+    , a(inst.a)
+    , b(inst.b)
+    , c(inst.c)
+{
+}
+
+Instruction::Instruction(Command command, Params params, Parameter a, Parameter b, Parameter c)
+    : command(command)
+    , params(params)
+    , a(a)
+    , b(b)
+    , c(c)
 {
 }

+ 4 - 2
instruction.h

@@ -64,7 +64,6 @@ enum Params : uint16_t {
 };
 
 enum Variables {
-    Local_0,
     Local_1,
     Local_2,
     Local_3,
@@ -84,6 +83,7 @@ enum Variables {
     Local_17,
     Local_18,
     Local_19,
+    Local_20,
     LocalActive,
     LocalBanks,
     LocalInstrSet,
@@ -134,7 +134,9 @@ struct Instruction {
     Parameter b = 0;
     Parameter c = 0;
 
-    Instruction(Command _command, Params _params = N, Parameter _a = 0, Parameter _b = 0, Parameter _c = 0);
+    Instruction();
+    Instruction(const Instruction& inst);
+    Instruction(Command command, Params params = N, Parameter a = 0, Parameter b = 0, Parameter c = 0);
 };
 
 #endif // CINSTRUCTION_H

+ 16 - 9
mainwindow.cpp

@@ -16,20 +16,27 @@ MainWindow::MainWindow(QWidget *parent)
     ui->statusBar->addWidget(lblCycles);
 
 
-    QFile file("C:/test.ccp");
-    if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
-        return;
 
-    QTextStream in(&file);
+	QFile file("c:/test.ccp");
+
+	if(!file.open(QIODevice::ReadOnly | QIODevice::Text))
+	{
+		return;
+	}
+
+	QTextStream in(&file);
+
+	QVector<QVector<Instruction>> banks;
+
+	while(!in.atEnd())
+	{
+		QString line = in.readLine();
+		process_line(line, banks);
+	}
 
-    QString code = in.readAll();
 
-    auto tokens = lex(code);
 
-    QVector<ParseError> errors;
-    auto instrbanks = parse(code, tokens, errors);
 
-//    setMinimumSize(simulator.size * 40, simulator.size * 40);
 
     simulator.loadProgram(Qt::red, 10, 10);
     simulator.loadProgram(Qt::blue, 15, 15);

+ 389 - 221
parse.cpp

@@ -1,230 +1,398 @@
 #include "parse.h"
 
 #include <QObject>
+#include <QException>
+#include <QVector>
+
+int32_t process_param(const QString& param, bool& isSepecial)
+{
+	QRegExp regMatchNumber("\\d*");
+
+	isSepecial = true;
+
+	if(param.compare("#1", Qt::CaseInsensitive) == 0)
+	{
+		return Local_1;
+	}
+	else if(param.compare("#2", Qt::CaseInsensitive) == 0)
+	{
+		return Local_2;
+	}
+	else if(param.compare("#3", Qt::CaseInsensitive) == 0)
+	{
+		return Local_3;
+	}
+	else if(param.compare("#4", Qt::CaseInsensitive) == 0)
+	{
+		return Local_4;
+	}
+	else if(param.compare("#5", Qt::CaseInsensitive) == 0)
+	{
+		return Local_5;
+	}
+	else if(param.compare("#6", Qt::CaseInsensitive) == 0)
+	{
+		return Local_6;
+	}
+	else if(param.compare("#7", Qt::CaseInsensitive) == 0)
+	{
+		return Local_7;
+	}
+	else if(param.compare("#8", Qt::CaseInsensitive) == 0)
+	{
+		return Local_8;
+	}
+	else if(param.compare("#9", Qt::CaseInsensitive) == 0)
+	{
+		return Local_9;
+	}
+	else if(param.compare("#10", Qt::CaseInsensitive) == 0)
+	{
+		return Local_10;
+	}
+	else if(param.compare("#11", Qt::CaseInsensitive) == 0)
+	{
+		return Local_11;
+	}
+	else if(param.compare("#12", Qt::CaseInsensitive) == 0)
+	{
+		return Local_12;
+	}
+	else if(param.compare("#13", Qt::CaseInsensitive) == 0)
+	{
+		return Local_13;
+	}
+	else if(param.compare("#14", Qt::CaseInsensitive) == 0)
+	{
+		return Local_14;
+	}
+	else if(param.compare("#15", Qt::CaseInsensitive) == 0)
+	{
+		return Local_15;
+	}
+	else if(param.compare("#16", Qt::CaseInsensitive) == 0)
+	{
+		return Local_16;
+	}
+	else if(param.compare("#17", Qt::CaseInsensitive) == 0)
+	{
+		return Local_17;
+	}
+	else if(param.compare("#18", Qt::CaseInsensitive) == 0)
+	{
+		return Local_18;
+	}
+	else if(param.compare("#19", Qt::CaseInsensitive) == 0)
+	{
+		return Local_19;
+	}
+	else if(param.compare("#20", Qt::CaseInsensitive) == 0)
+	{
+		return Local_20;
+	}
+	else if(param.compare("#Active", Qt::CaseInsensitive) == 0)
+	{
+		return LocalActive;
+	}
+	else if(param.compare("$Banks", Qt::CaseInsensitive) == 0)
+	{
+		return LocalBanks;
+	}
+	else if(param.compare("$InstrSet", Qt::CaseInsensitive) == 0)
+	{
+		return LocalInstrSet;
+	}
+	else if(param.compare("$Mobile", Qt::CaseInsensitive) == 0)
+	{
+		return LocalMobile;
+	}
+	else if(param.compare("$Age", Qt::CaseInsensitive) == 0)
+	{
+		return LocalAge;
+	}
+	else if(param.compare("$Tasks", Qt::CaseInsensitive) == 0)
+	{
+		return LocalTasks;
+	}
+	else if(param.compare("$Generation", Qt::CaseInsensitive) == 0)
+	{
+		return LocalGeneration;
+	}
+	else if(param.compare("$ID", Qt::CaseInsensitive) == 0)
+	{
+		return LocalId;
+	}
+	else if(param.compare("%Active", Qt::CaseInsensitive) == 0)
+	{
+		return RemoteActive;
+	}
+	else if(param.compare("%Banks", Qt::CaseInsensitive) == 0)
+	{
+		return RemoteBanks;
+	}
+	else if(param.compare("%InstrSet", Qt::CaseInsensitive) == 0)
+	{
+		return RemoteInstrSet;
+	}
+	else if(param.compare("%Mobile", Qt::CaseInsensitive) == 0)
+	{
+		return RemoteMobile;
+	}
+	else if(param.compare("%Age", Qt::CaseInsensitive) == 0)
+	{
+		return RemoteAge;
+	}
+	else if(param.compare("%Tasks", Qt::CaseInsensitive) == 0)
+	{
+		return RemoteTasks;
+	}
+	else if(param.compare("%Generation", Qt::CaseInsensitive) == 0)
+	{
+		return RemoteGeneration;
+	}
+	else if(param.compare("#Pub", Qt::CaseInsensitive) == 0)
+	{
+		return GlobalPub;
+	}
+	else if(param.compare("#Team", Qt::CaseInsensitive) == 0)
+	{
+		return GlobalTeam;
+	}
+	else if(param.compare("$Own", Qt::CaseInsensitive) == 0)
+	{
+		return GlobalOwn;
+	}
+	else if(param.compare("$Others", Qt::CaseInsensitive) == 0)
+	{
+		return GlobalOthers;
+	}
+	else if(param.compare("$Fields", Qt::CaseInsensitive) == 0)
+	{
+		return GlobalFields;
+	}
+	else if(param.compare("$Time", Qt::CaseInsensitive) == 0)
+	{
+		return GlobalTime;
+	}
+	else if(param.compare("$Timeout", Qt::CaseInsensitive) == 0)
+	{
+		return GlobalTimeout;
+	}
+	else if(regMatchNumber.exactMatch(param))
+	{
+		isSepecial = false;
+		return param.toInt();
+	}
+	else
+	{
+		throw QException();
+	}
+}
+
+
+Instruction process_0(const QString& cmd)
+{
+	if(cmd.compare("MOVE", Qt::CaseInsensitive) == 0)
+	{
+		return {MOVE, N, 0, 0, 0};
+	}
+	else if(cmd.compare("DIE", Qt::CaseInsensitive) == 0)
+	{
+		return {DIE, N, 0, 0, 0};
+	}
+	else if(cmd.compare("BREAK", Qt::CaseInsensitive) == 0)
+	{
+		return {BREAK, N, 0, 0, 0};
+	}
+	else if(cmd.compare("RESUME", Qt::CaseInsensitive) == 0)
+	{
+		return {RESUME, N, 0, 0, 0};
+	}
+	else if(cmd.compare("SEIZE", Qt::CaseInsensitive) == 0)
+	{
+		return {SEIZE, N, 0, 0, 0};
+	}
+	else if(cmd.compare("QUIT", Qt::CaseInsensitive) == 0)
+	{
+		return {QUIT, N, 0, 0, 0};
+	}
+	throw QException();
+}
+
+Instruction process_1(const QString& cmd, const QString& a)
+{
+	bool isSpecialA;
+	auto vA = process_param(a, isSpecialA);
+	Params params = isSpecialA ? V : L;
+
+	if(cmd.compare("TURN", Qt::CaseInsensitive) == 0)
+	{
+		return {TURN, params, vA};
+	}
+	else if(cmd.compare("JUMP", Qt::CaseInsensitive) == 0)
+	{
+		return {JUMP, params, vA};
+	}
+	else if(cmd.compare("AJUMP", Qt::CaseInsensitive) == 0)
+	{
+		return {AJUMP, params, vA};
+	}
+	else if(cmd.compare("SCAN", Qt::CaseInsensitive) == 0)
+	{
+		return {SCAN, params, vA};
+	}
+	else if(cmd.compare("SLEEP", Qt::CaseInsensitive) == 0)
+	{
+		return {SLEEP, params, vA};
+	}
+	throw QException();
+}
 
-QVector<Token> lex(const QString& code) {
-    QVector<Token> tokens;
-    size_t i = 0;
-    size_t lineCounter = 0;
-    size_t columnCounter = 0;
-    while(i < code.size()) {
-        if(code[i] == '\n') {
-            tokens.push_back({lineCounter, columnCounter, TokenTypeEOL, i, i + 1});
-            ++lineCounter;
-            columnCounter = 0;
-            ++i;
-        }
-        else if(code[i] == ',') {
-            tokens.push_back({lineCounter, columnCounter, TokenTypeComma, i, i + 1});
-            ++i;
-        }
-        else if(code[i] == '#') {
-            tokens.push_back({lineCounter, columnCounter, TokenTypeHash, i, i + 1});
-            ++i;
-        }
-        else if(code[i] == '%') {
-            tokens.push_back({lineCounter, columnCounter, TokenTypePercent, i, i + 1});
-            ++i;
-        }
-        else if(code[i] == '$') {
-            tokens.push_back({lineCounter, columnCounter, TokenTypeDollar, i, i + 1});
-            ++i;
-        }
-        else if(code[i] == '/' && (i+1) < code.size() && code[i+1] == '/') {
-            size_t s = i + 2;
-            while(s < code.size() && code[s] != '\n') {
-                 ++s;
-            }
-            i = s;
-        }
-        else if(code[i].isSpace()) {
-            ++i;
-        }
-        else if(code[i].isDigit()) {
-            size_t s = i + 1;
-            while(s < code.size() && code[s].isDigit()){
-                 ++s;
-            }
-
-            tokens.push_back({lineCounter, columnCounter, TokenTypeNumber, i, s});
-            i = s;
-        }
-        else if(code[i].isLetter()) {
-            size_t s = i + 1;
-            while(s < code.size() && code[s].isLetter()){
-                 ++s;
-            }
-
-            tokens.push_back({lineCounter, columnCounter, TokenTypeWord, i, s});
-            i = s;
-        }
-        else {
-            tokens.push_back({lineCounter, columnCounter, TokenTypeError, i, i + 1});
-            ++i;
-        }
-
-        ++columnCounter;
-    }
-
-    return tokens;
+Instruction process_2(const QString& cmd, const QString& a, const QString& b)
+{
+	bool isSpecialA;
+	bool isSpecialB;
+	auto vA = process_param(a, isSpecialA);
+	auto vB = process_param(b, isSpecialB);
+	Params params = isSpecialA ? ( isSpecialB ? VV : VL) : ( isSpecialB ? LV : LL);
+
+	if(cmd.compare("TRANS", Qt::CaseInsensitive) == 0)
+	{
+		return {TRANS, params, vA, vB};
+	}
+	else if(cmd.compare("RTRANS", Qt::CaseInsensitive) == 0)
+	{
+		return {RTRANS, params, vA, vB};
+	}
+	else if(cmd.compare("BJUMP", Qt::CaseInsensitive) == 0)
+	{
+		return {BJUMP, params, vA, vB};
+	}
+	else if(cmd.compare("SET", Qt::CaseInsensitive) == 0)
+	{
+		return {SET, params, vA, vB};
+	}
+	else if(cmd.compare("ADD", Qt::CaseInsensitive) == 0)
+	{
+		return {ADD, params, vA, vB};
+	}
+	else if(cmd.compare("SUB", Qt::CaseInsensitive) == 0)
+	{
+		return {SUB, params, vA, vB};
+	}
+	else if(cmd.compare("MUL", Qt::CaseInsensitive) == 0)
+	{
+		return {MUL, params, vA, vB};
+	}
+	else if(cmd.compare("DIV", Qt::CaseInsensitive) == 0)
+	{
+		return {DIV, params, vA, vB};
+	}
+	else if(cmd.compare("MOD", Qt::CaseInsensitive) == 0)
+	{
+		return {MOD, params, vA, vB};
+	}
+	else if(cmd.compare("MIN", Qt::CaseInsensitive) == 0)
+	{
+		return {MIN, params, vA, vB};
+	}
+	else if(cmd.compare("MAX", Qt::CaseInsensitive) == 0)
+	{
+		return {MAX, params, vA, vB};
+	}
+	else if(cmd.compare("IF", Qt::CaseInsensitive) == 0)
+	{
+		return {IF, params, vA, vB};
+	}
+	else if(cmd.compare("IFN", Qt::CaseInsensitive) == 0)
+	{
+		return {IFN, params, vA, vB};
+	}
+	else if(cmd.compare("IFG", Qt::CaseInsensitive) == 0)
+	{
+		return {IFG, params, vA, vB};
+	}
+	else if(cmd.compare("IFL", Qt::CaseInsensitive) == 0)
+	{
+		return {IFL, params, vA, vB};
+	}
+	else if(cmd.compare("IFGE", Qt::CaseInsensitive) == 0)
+	{
+		return {IFGE, params, vA, vB};
+	}
+	else if(cmd.compare("IFLE", Qt::CaseInsensitive) == 0)
+	{
+		return {IFLE, params, vA, vB};
+	}
+	else if(cmd.compare("INIT", Qt::CaseInsensitive) == 0)
+	{
+		return {INIT, params, vA, vB};
+	}
+	throw QException();
 }
 
+Instruction process_3(const QString& cmd, const QString& a, const QString& b, const QString& c)
+{
+	bool isSpecialA;
+	bool isSpecialB;
+	bool isSpecialC;
+	auto vA = process_param(a, isSpecialA);
+	auto vB = process_param(b, isSpecialB);
+	auto vC = process_param(c, isSpecialC);
+	Params params = isSpecialA ? ( isSpecialB ? ( isSpecialC ? VVV: VVL) : ( isSpecialC ? VLV: VLL)) : ( isSpecialB ? ( isSpecialC ? LVV : LVL) : ( isSpecialC ? LLV : LLL));
+
+	if(cmd.compare("CREATE", Qt::CaseInsensitive) == 0)
+	{
+		return {CREATE, params, vA, vB, vC};
+	}
+	else if(cmd.compare("FARSCAN", Qt::CaseInsensitive) == 0)
+	{
+		return {FARSCAN, params, vA, vB, vC};
+	}
+	else if(cmd.compare("RANDOM", Qt::CaseInsensitive) == 0)
+	{
+		return {RANDOM, params, vA, vB, vC};
+	}
+	throw QException();
+}
+
+Instruction process_parts(const QStringList& parts)
+{
+	if(parts.size() == 1)
+	{
+		return process_0(parts[0]);
+	}
+	else if(parts.size() == 2)
+	{
+		return process_1(parts[0], parts[1]);
+	}
+	else if(parts.size() == 3)
+	{
+		return process_2(parts[0], parts[1], parts[2]);
+	}
+	else if(parts.size() == 4)
+	{
+		return process_3(parts[0], parts[1], parts[2], parts[3]);
+	}
+	throw QException();
+}
+
+void process_line(QString line, QVector<QVector<Instruction>>& banks)
+{
+	line = line.mid(0, line.indexOf("//"));
+
+	if(line.isEmpty())
+	{
+		return;
+	}
+
+	if(line.startsWith("BANK ", Qt::CaseInsensitive))
+	{
+		banks.resize(banks.size() + 1);
+		return;
+	}
 
 
-QVector<QVector<Instruction>> parse(const QString& code, const QVector<Token>& tokens, QVector<ParseError>& errors) {
-    size_t i = 0;
-
-    auto skipToEol = [&tokens, &i](){
-        while(i < tokens.size() && tokens[i].tokenType != TokenTypeEOL) {
-            ++i;
-        }
-        ++i;
-    };
-
-    while(i < tokens.size()) {
-        if(tokens[i].tokenType != TokenTypeWord) {
-            errors += ParseError(tokens[i].line, tokens[i].column, QObject::tr("is not a valid Instruction"));
-            //lets fast forward to next line
-            skipToEol();
-            continue;
-        }
-        else {
-            auto getTokenText = [&](size_t k){
-                return code.mid(tokens[k].begin, tokens[k].end - tokens[k].begin).toUpper();
-            };
-
-            QString word = getTokenText(i);
-
-            if(word.compare("CREATE", Qt::CaseInsensitive)) {
-            }
-            else if(word.compare("MOVE", Qt::CaseInsensitive)) {
-            }
-            else if(word.compare("DIE", Qt::CaseInsensitive)) {
-                if(i + 1 >= tokens.size() || tokens[i + 1].tokenType != TokenTypeEOL) {
-                    errors += ParseError(tokens[i - 1].line, tokens[i - 1].column, QObject::tr("error"));
-                }
-                skipToEol();
-            }
-            else if(word.compare("TRANS", Qt::CaseInsensitive)) {
-
-                skipToEol();
-            }
-            else if(word.compare("RTRANS", Qt::CaseInsensitive)) {
-
-                skipToEol();
-            }
-            else if(word.compare("TURN", Qt::CaseInsensitive)) {
-
-                skipToEol();
-            }
-            else if(word.compare("JUMP", Qt::CaseInsensitive)) {
-
-                skipToEol();
-            }
-            else if(word.compare("AJUMP", Qt::CaseInsensitive)) {
-
-                skipToEol();
-            }
-            else if(word.compare("BJUMP", Qt::CaseInsensitive)) {
-
-                skipToEol();
-            }
-            else if(word.compare("TURN", Qt::CaseInsensitive)) {
-
-                skipToEol();
-            }
-            else if(word.compare("SCAN", Qt::CaseInsensitive)) {
-
-                skipToEol();
-            }
-            else if(word.compare("FARSCAN", Qt::CaseInsensitive)) {
-
-                skipToEol();
-            }
-            else if(word.compare("SET", Qt::CaseInsensitive)) {
-
-                skipToEol();
-            }
-            else if(word.compare("ADD", Qt::CaseInsensitive)) {
-
-                skipToEol();
-            }
-            else if(word.compare("SUB", Qt::CaseInsensitive)) {
-
-                skipToEol();
-            }
-            else if(word.compare("MUL", Qt::CaseInsensitive)) {
-
-                skipToEol();
-            }
-            else if(word.compare("DIV", Qt::CaseInsensitive)) {
-
-                skipToEol();
-            }
-            else if(word.compare("MOD", Qt::CaseInsensitive)) {
-
-                skipToEol();
-            }
-            else if(word.compare("MIN", Qt::CaseInsensitive)) {
-
-                skipToEol();
-            }
-            else if(word.compare("MAX", Qt::CaseInsensitive)) {
-
-                skipToEol();
-            }
-            else if(word.compare("RANDOM", Qt::CaseInsensitive)) {
-
-                skipToEol();
-            }
-            else if(word.compare("IF", Qt::CaseInsensitive)) {
-
-                skipToEol();
-            }
-            else if(word.compare("IFN", Qt::CaseInsensitive)) {
-
-                skipToEol();
-            }
-            else if(word.compare("IFG", Qt::CaseInsensitive)) {
-
-                skipToEol();
-            }
-            else if(word.compare("IFL", Qt::CaseInsensitive)) {
-
-                skipToEol();
-            }
-            else if(word.compare("IFGE", Qt::CaseInsensitive)) {
-
-                skipToEol();
-            }
-            else if(word.compare("IFLE", Qt::CaseInsensitive)) {
-
-                skipToEol();
-            }
-            else if(word.compare("INIT", Qt::CaseInsensitive)) {
-
-                skipToEol();
-            }
-            else if(word.compare("BREAK", Qt::CaseInsensitive)) {
-
-                skipToEol();
-            }
-            else if(word.compare("RESUME", Qt::CaseInsensitive)) {
-
-                skipToEol();
-            }
-            else if(word.compare("SLEEP", Qt::CaseInsensitive)) {
-
-                skipToEol();
-            }
-            else if(word.compare("QUIT", Qt::CaseInsensitive)) {
-
-                skipToEol();
-            }
-            else {
-                errors += ParseError(tokens[i].line, tokens[i].column, QObject::tr("is not a valid Instruction"));
-                skipToEol();
-            }
-        }
-    }
+	auto parts = line.split(QRegExp("[\\s,]"), QString::SplitBehavior::SkipEmptyParts);
+	banks.back() += process_parts(parts);
 }

+ 6 - 73
parse.h

@@ -2,80 +2,13 @@
 #define PARSE_H
 
 #include <QString>
-#include <QVector>
-using namespace std;
-
 #include "instruction.h"
 
-enum TokenType {
-    TokenTypeError,
-    TokenTypeEOL,
-    TokenTypeComma,
-    TokenTypeHash,
-    TokenTypePercent,
-    TokenTypeDollar,
-    TokenTypeNumber,
-    TokenTypeWord,
-};
-
-struct Token {
-    size_t line = 0;
-    size_t column = 0;
-    TokenType tokenType = TokenTypeError;
-    size_t begin = 0;
-    size_t end = 0;
-
-    Token()
-        : line(0)
-        , column(0)
-        , tokenType(TokenTypeError)
-        , begin(0)
-        , end(0)
-    {}
-
-    Token(const Token& tok)
-        : line(tok.line)
-        , column(tok.column)
-        , tokenType(tok.tokenType)
-        , begin(tok.begin)
-        , end(tok.end)
-    {}
-
-    Token(size_t line, size_t column, TokenType tokenType, size_t begin, size_t end)
-        : line(line)
-        , column(column)
-        , tokenType(tokenType)
-        , begin(begin)
-        , end(end)
-    {}
-};
-
-QVector<Token> lex(const QString& code);
-
-struct ParseError {
-    size_t line = 0;
-    size_t column = 0;
-    QString text;
-
-    ParseError()
-        : line(0)
-        , column(0)
-        , text("")
-    {}
-
-    ParseError(const ParseError& par)
-        : line(par.line)
-        , column(par.column)
-        , text(par.text)
-    {}
-
-    ParseError(size_t line, size_t column, const QString& text)
-        : line(line)
-        , column(column)
-        , text(text)
-    {}
-};
-
-QVector<QVector<Instruction>> parse(const QString& code, const QVector<Token>& tokens, QVector<ParseError>& errors);
+int32_t process_param(const QString& cmd, bool& isSepecial);
+Instruction process_0(const QString& cmd);
+Instruction process_2(const QString& cmd, const QString& a, const QString& b);
+Instruction process_3(const QString& cmd, const QString& a, const QString& b, const QString& c);
+Instruction process_parts(const QStringList& parts);
+void process_line(QString line, QVector<QVector<Instruction>>& banks);
 
 #endif // PARSE_H

+ 40 - 32
simulator.cpp

@@ -22,26 +22,26 @@ void Simulator::decode(Program& program, Task& task, int& v, int*& var_v, int pa
     var_v = nullptr;
 
     switch(param) {
-        case Local_0:  v = program.vars[0];  var_v = &program.vars[0]; break;
-        case Local_1:  v = program.vars[1];  var_v = &program.vars[1]; break;
-        case Local_2:  v = program.vars[2];  var_v = &program.vars[2]; break;
-        case Local_3:  v = program.vars[3];  var_v = &program.vars[3]; break;
-        case Local_4:  v = program.vars[4];  var_v = &program.vars[4]; break;
-        case Local_5:  v = program.vars[5];  var_v = &program.vars[5]; break;
-        case Local_6:  v = program.vars[6];  var_v = &program.vars[6]; break;
-        case Local_7:  v = program.vars[7];  var_v = &program.vars[7]; break;
-        case Local_8:  v = program.vars[8];  var_v = &program.vars[8]; break;
-        case Local_9:  v = program.vars[9];  var_v = &program.vars[9]; break;
-        case Local_10: v = program.vars[10]; var_v = &program.vars[10]; break;
-        case Local_11: v = program.vars[11]; var_v = &program.vars[11]; break;
-        case Local_12: v = program.vars[12]; var_v = &program.vars[12]; break;
-        case Local_13: v = program.vars[13]; var_v = &program.vars[13]; break;
-        case Local_14: v = program.vars[14]; var_v = &program.vars[14]; break;
-        case Local_15: v = program.vars[15]; var_v = &program.vars[15]; break;
-        case Local_16: v = program.vars[16]; var_v = &program.vars[16]; break;
-        case Local_17: v = program.vars[17]; var_v = &program.vars[17]; break;
-        case Local_18: v = program.vars[18]; var_v = &program.vars[18]; break;
-        case Local_19: v = program.vars[19]; var_v = &program.vars[19]; break;
+        case Local_1 : v = program.vars[0];  var_v = &program.vars[0]; break;
+        case Local_2 : v = program.vars[1];  var_v = &program.vars[1]; break;
+        case Local_3 : v = program.vars[2];  var_v = &program.vars[2]; break;
+        case Local_4 : v = program.vars[3];  var_v = &program.vars[3]; break;
+        case Local_5 : v = program.vars[4];  var_v = &program.vars[4]; break;
+        case Local_6 : v = program.vars[5];  var_v = &program.vars[5]; break;
+        case Local_7 : v = program.vars[6];  var_v = &program.vars[6]; break;
+        case Local_8 : v = program.vars[7];  var_v = &program.vars[7]; break;
+        case Local_9 : v = program.vars[8];  var_v = &program.vars[8]; break;
+        case Local_10: v = program.vars[9];  var_v = &program.vars[9]; break;
+        case Local_11: v = program.vars[10]; var_v = &program.vars[10]; break;
+        case Local_12: v = program.vars[11]; var_v = &program.vars[11]; break;
+        case Local_13: v = program.vars[12]; var_v = &program.vars[12]; break;
+        case Local_14: v = program.vars[13]; var_v = &program.vars[13]; break;
+        case Local_15: v = program.vars[14]; var_v = &program.vars[14]; break;
+        case Local_16: v = program.vars[15]; var_v = &program.vars[15]; break;
+        case Local_17: v = program.vars[16]; var_v = &program.vars[16]; break;
+        case Local_18: v = program.vars[17]; var_v = &program.vars[17]; break;
+        case Local_19: v = program.vars[18]; var_v = &program.vars[18]; break;
+        case Local_20: v = program.vars[19]; var_v = &program.vars[19]; break;
         case LocalActive:
             v = program.active;
             var_v = &program.active;
@@ -237,8 +237,8 @@ void Simulator::loadProgram(QColor color, size_t x, size_t y) {
     programs.back().banks[1] = make_shared<Bank>(team, vector<Instruction>{
                                                      Instruction(SCAN, V, 1),
                                                      Instruction(CREATE, LLL, 2, 50, 1),
-                                                     Instruction(TRANS, LL, 0, 0),
                                                      Instruction(TRANS, LL, 1, 1),
+                                                     Instruction(TRANS, LL, 2, 2),
                                                      Instruction(SET, VL, RemoteActive, 1),
                                                      Instruction(TURN, L, 0),
                                                      Instruction(AJUMP, L, 0)
@@ -357,31 +357,35 @@ void Simulator::beginInstruction(Program& program, Task& task) {
             break;
 
         case TRANS: {
+            int ar = task.a - 1;
+            int br = task.b - 1;
             if(program.instructionSet < 1) {
                 program.error = HigherInstructionSetRequired;
                 break;
             }
-            if(task.a < 0 || task.a >= program.banks.size()) {
+            if(ar < 0 || ar >= program.banks.size()) {
                 program.error = InvalidBankNumber;
                 break;
             }
-            const auto& bank = program.banks[task.a];
+            const auto& bank = program.banks[ar];
             task.remainingCycles = 14 + (bank ? bank->instructions.size() : 0);
             break;
         }
 
         case RTRANS: {
+            int ar = task.a - 1;
+            int br = task.b - 1;
             if(program.instructionSet < 1) {
                 program.error = HigherInstructionSetRequired;
                 break;
             }
-            if(task.a < 0 || task.a >= 50 || task.b < 0 || task.b >= program.banks.size()) {
+            if(ar < 0 || ar >= 50 || br < 0 || br >= program.banks.size()) {
                 program.error = InvalidBankNumber;
                 break;
             }
             auto remotePosition = calcPosition(program.position, task.direction, 1);
             auto remoteProgram = findProgram(remotePosition);
-            task.remainingCycles = 14 + remoteProgram ? (task.a < remoteProgram->banks.size() ? (remoteProgram->banks[task.a] ? remoteProgram->banks[task.a]->instructions.size() : 0): 0): 0;
+            task.remainingCycles = 14 + remoteProgram ? (ar < remoteProgram->banks.size() ? (remoteProgram->banks[ar] ? remoteProgram->banks[ar]->instructions.size() : 0): 0): 0;
             break;
         }
 
@@ -554,20 +558,24 @@ void Simulator::endInstruction(Program& program, Task& task) {
         }
 
         case TRANS: {
+            int ar = task.a - 1;
+            int br = task.b - 1;
             auto remotePosition = calcPosition(program.position, task.direction, 1);
             auto remoteProgram = findProgram(remotePosition);
-            if(remoteProgram && task.b < remoteProgram->banks.size() && task.a < program.banks.size()) {
-                remoteProgram->banks[task.b] = program.banks[task.a];
+            if(remoteProgram && br < remoteProgram->banks.size() && ar < program.banks.size()) {
+                remoteProgram->banks[br] = program.banks[ar];
             }
             task.instIndex += 1;
             break;
         }
 
         case RTRANS: {
+            int ar = task.a - 1;
+            int br = task.b - 1;
             auto remotePosition = calcPosition(program.position, task.direction, 1);
             auto remoteProgram = findProgram(remotePosition);
-            if(remoteProgram && task.a < remoteProgram->banks.size() && task.b < program.banks.size()) {
-                program.banks[task.b] = remoteProgram->banks[task.a];
+            if(remoteProgram && ar < remoteProgram->banks.size() && br < program.banks.size()) {
+                program.banks[br] = remoteProgram->banks[ar];
             }
             task.instIndex += 1;
             break;
@@ -585,13 +593,13 @@ void Simulator::endInstruction(Program& program, Task& task) {
         }
 
         case AJUMP: {
-            task.instIndex = task.a;
+            task.instIndex = task.a - 1;
             break;
         }
 
         case BJUMP: {
-            task.bankIndex = task.a;
-            task.instIndex = task.b;
+            task.bankIndex = task.a - 1;
+            task.instIndex = task.b - 1;
             break;
         }