Modification of the modifier parsing strategy to allow for a lot more leeway in how you enter the values in. Previously the syntax was *VERY* strict. Now it's easier to get it to accept your modifier strings.

This commit is contained in:
Collin Kidder
2015-08-17 21:19:12 -04:00
parent 7f0c077891
commit 248538e943
2 changed files with 84 additions and 49 deletions
+47 -43
View File
@@ -375,7 +375,7 @@ void FrameSenderWindow::doModifiers(int idx)
if (sendData->modifiers.count() == 0) return; //if no modifiers just leave right now if (sendData->modifiers.count() == 0) return; //if no modifiers just leave right now
qDebug() << "Doin' dem mods son"; qDebug() << "Executing mods";
for (int i = 0; i < sendData->modifiers.count(); i++) for (int i = 0; i < sendData->modifiers.count(); i++)
{ {
@@ -465,14 +465,19 @@ void FrameSenderWindow::processModifierText(int line)
{ {
qDebug() << "processModifierText"; qDebug() << "processModifierText";
QString modString; QString modString;
int numOps; bool firstOp = true;
bool abort = false;
//Example line: //Example line:
//d0 = D0 + 1,d1 = id:0x200:d3 + id:0x200:d4 AND 0xF0 //d0 = D0 + 1,d1 = id:0x200:d3 + id:0x200:d4 AND 0xF0 - Original version
//D0=D0+1,D1=ID:0x200:D3+ID:0x200:D4&0xF0
//This is certainly much harder to parse than the trigger definitions. //This is certainly much harder to parse than the trigger definitions.
//the left side of the = has to be D0 to D7. After that there is a string of //the left side of the = has to be D0 to D7. After that there is a string of
//data that for ease of parsing will require spaces between tokens //data. Spaces used to be required but no longer are. This makes parsing harder but data entry easier
modString = ui->tableSender->item(line, 6)->text().toUpper();
//yeah, lots of operations on this one line but it's for a good cause. Removes the convenience English versions of the
//logical operators and replaces them with the math equivs. Also uppercases and removes all superfluous whitespace
modString = ui->tableSender->item(line, 6)->text().toUpper().trimmed().replace("AND", "&").replace("XOR", "^").replace("OR", "|").replace(" ", "");
if (modString != "") if (modString != "")
{ {
QStringList mods = modString.split(','); QStringList mods = modString.split(',');
@@ -482,57 +487,55 @@ void FrameSenderWindow::processModifierText(int line)
{ {
Modifier thisMod; Modifier thisMod;
thisMod.destByte = 0; thisMod.destByte = 0;
//now split by space to extract tokens
QStringList modToks = mods[i].split(' '); QString leftSide = Utility::grabAlphaNumeric(mods[i]);
if (modToks.length() >= 5) //any valid modifier that this code can process has at least 5 tokens (D0 = D0 + 1) if (leftSide.startsWith("D") && leftSide.length() == 2)
{ {
//valid token assignment will have a data byte as the first token and = as the second thisMod.destByte = leftSide.right(1).toInt();
if (modToks[0].length() == 2 && modToks[0].startsWith('D'))
{
numOps = ((modToks.length() - 5) / 2) + 1;
thisMod.operations.clear(); thisMod.operations.clear();
thisMod.operations.reserve(numOps); }
thisMod.destByte = modToks[0].right(modToks[0].length() - 1).toInt(); else continue;
//Now start at token 2 and extract all operations. All ops past the first one if (!(Utility::grabOperation(mods[i]) == "=")) continue;
//use the implicit shadow register as the first operand.The contents of the shadow abort = false;
//register are what is copied to the destination byte at the end. while (!abort)
//each op is of the form <first> <op> <second>. first and second could have more subtokens
int currToken = 2;
QStringList firstToks, secondToks;
for (int j = 0; j < numOps; j++)
{ {
QString token = Utility::grabAlphaNumeric(mods[i]);
ModifierOp thisOp; ModifierOp thisOp;
if (j == 0) if (firstOp)
{ {
firstToks = modToks[currToken++].toUpper().split(':'); parseOperandString(token.split(":"), thisOp.first);
parseOperandString(firstToks, thisOp.first); firstOp = false;
} }
else else
{ {
thisOp.first.ID = -1; thisOp.first.ID = -1; //shadow register
} }
thisOp.operation = parseOperation(modToks[currToken++].toUpper()); if (mods[i].length() == 0) //if this thing had no actual operation or second operand then fake it
secondToks = modToks[currToken++].toUpper().split(':');
thisOp.second.bus = sendingData[line].bus;
thisOp.second.ID = sendingData[line].ID;
parseOperandString(secondToks, thisOp.second);
thisMod.operations.append(thisOp);
}
}
}
else
{ {
QStringList firstToks; abort = true;
numOps = 1;
thisMod.destByte = modToks[0].right(modToks[0].length() - 1).toInt();
ModifierOp thisOp;
thisOp.operation = ADDITION; thisOp.operation = ADDITION;
thisOp.second.ID = 0; thisOp.second.ID = 0;
thisOp.second.databyte = 0; thisOp.second.databyte = 0;
firstToks = modToks[2].toUpper().split(':');
parseOperandString(firstToks, thisOp.first);
thisMod.operations.append(thisOp); thisMod.operations.append(thisOp);
} }
else //otherwise try to grab them
{
QString operation = Utility::grabOperation(mods[i]);
if (operation == "")
{
abort = true;
}
else
{
thisOp.operation = parseOperation(operation);
QString secondOp = Utility::grabAlphaNumeric(mods[i]);
thisOp.second.bus = sendingData[line].bus;
thisOp.second.ID = sendingData[line].ID;
parseOperandString(secondOp.split(":"), thisOp.second);
thisMod.operations.append(thisOp);
}
}
}
sendingData[line].modifiers.append(thisMod); sendingData[line].modifiers.append(thisMod);
} }
@@ -546,9 +549,10 @@ void FrameSenderWindow::processTriggerText(int line)
QString trigger; QString trigger;
//Example line: //Example line:
//id=0x200 5ms 10x bus0,1000ms //id0x200 5ms 10x bus0,1000ms
//trigger has two levels of syntactic parsing. First you split by comma to get each //trigger has two levels of syntactic parsing. First you split by comma to get each
//actual trigger. Then you split by spaces to get the tokens within each trigger //actual trigger. Then you split by spaces to get the tokens within each trigger
//trigger = ui->tableSender->item(line, 5)->text().toUpper().trimmed().replace(" ", "");
trigger = ui->tableSender->item(line, 5)->text().toUpper(); trigger = ui->tableSender->item(line, 5)->text().toUpper();
if (trigger != "") if (trigger != "")
{ {
@@ -571,7 +575,7 @@ void FrameSenderWindow::processTriggerText(int line)
for (int x = 0; x < trigToks.length(); x++) for (int x = 0; x < trigToks.length(); x++)
{ {
QString tok = trigToks.at(x); QString tok = trigToks.at(x);
if (tok.left(3) == "ID=") if (tok.left(2) == "ID")
{ {
thisTrigger.ID = Utility::ParseStringToNum(tok.right(tok.length() - 3)); thisTrigger.ID = Utility::ParseStringToNum(tok.right(tok.length() - 3));
if (thisTrigger.maxCount == -1) thisTrigger.maxCount = 10000000; if (thisTrigger.maxCount == -1) thisTrigger.maxCount = 10000000;
+31
View File
@@ -72,6 +72,37 @@ public:
} }
else return formatHexNum(value); else return formatHexNum(value);
} }
//parses the input string to grab as much of it as possible while staying alpha numeric
static QString grabAlphaNumeric(QString &input)
{
QString builder;
QChar thisChar;
for (int i = 0; i < input.length(); i++)
{
thisChar = input[i];
if (thisChar.isLetterOrNumber() || thisChar == ':') builder.append(input[i]);
else
{
input = input.right(input.length() - i);
return builder;
}
}
return builder;
}
static QString grabOperation(QString &input)
{
QString builder;
QChar thisChar = input[0];
if (thisChar == '+' || thisChar == '-' || thisChar == '*' || thisChar == '/' || thisChar == '^' || thisChar == '&' || thisChar == '|' || thisChar == "=")
{
input = input.right(input.length() - 1);
builder = thisChar;
}
return builder;
}
}; };
#endif // UTILITY_H #endif // UTILITY_H