More MACRO-10 parsing improvements

This commit is contained in:
Jeff 2017-03-19 12:03:45 -07:00 committed by Jeff Parsons
commit fb83d1e503
8 changed files with 869 additions and 806 deletions

View file

@ -492,11 +492,12 @@ class Macro10 {
case Macro10.PSEUDO_OP.IRP:
case Macro10.PSEUDO_OP.IRPC:
case Macro10.PSEUDO_OP.REPEAT:
this.addMacro(sOperator, sOperands);
this.addMacro(sOperator, sRemainder);
break;
case Macro10.PSEUDO_OP.PAGE: // TODO
case Macro10.PSEUDO_OP.SUBTTL: // TODO
case Macro10.PSEUDO_OP.TITLE: // TODO
break;
default:
@ -899,7 +900,7 @@ class Macro10 {
/*
* This is a DEFINE (macro) block.
*/
match = sOperands.match(/([A-Z$%.][0-9A-Z$%.]*)\s*(\([^)]*\)|)\s*(<|)(.*)/i);
match = sOperands.match(/([A-Z$%.][0-9A-Z$%.]*)\s*(\([^)]*\)|)\s*(<|)([\s\S]*)/i);
if (!match) {
this.error("unrecognized " + sOperator + ": " + sOperands);
return sOperands;
@ -940,7 +941,7 @@ class Macro10 {
if (!this.macroCall) {
this.error(sOperator + " outside of macro");
}
match = sOperands.match(/([A-Z$%.][0-9A-Z$%.]*)\s*,\s*(<|)(.*)/i);
match = sOperands.match(/([A-Z$%.][0-9A-Z$%.]*)\s*,\s*(<|)([\s\S]*)/i);
if (!match) {
this.error("unrecognized " + sOperator + ": " + sOperands);
return sOperands;
@ -973,7 +974,7 @@ class Macro10 {
}
sOperands = sOperands.substr(sOperand.length + 1);
sOperand = sOperand.trim();
match = sOperands.match(/\s*(<|)(.*)/i);
match = sOperands.match(/\s*(<|)([\s\S]*)/i);
name = '?' + sOperator;
/*
* The expression is either a repeat count or a condition. Either way, we must be able to
@ -990,24 +991,14 @@ class Macro10 {
*/
name = name.toUpperCase();
this.nMacroDef = 1;
this.sMacroDef = name;
this.tblMacros[name] = {name, nOperand, aParms, aDefaults, aValues, sText: "", nLine: this.nLine};
var sText = "";
if (match[iMatch]) { // if there IS also an opening bracket...
this.nMacroDef = 2; // then the macro definition has begun
sText = match[iMatch + 1];
if (sText.slice(-1) == this.chMacroClose) { // and if there is ALSO a closing bracket...
this.nMacroDef = 0; // the macro definition has ended as well
sText = sText.slice(0, -1);
}
if (match[iMatch]) { // if there is an opening bracket
this.nMacroDef = 2; // then the macro definition has started
this.appendMacro(match[iMatch + 1]);
}
this.tblMacros[name] = {name, nOperand, aParms, aDefaults, aValues, sText, nLine: this.nLine};
if (!this.nMacroDef) {
this.parseMacro(name);
} else {
this.sMacroDef = name;
}
return name;
}
@ -1087,7 +1078,7 @@ class Macro10 {
addWord(sOperator, sOperands)
{
var w;
var sExp = sOperator + sOperands;
var sExp = sOperator + ' ' + sOperands;
if (sExp.indexOf(",,") >= 0 || !sOperator && sExp.indexOf('@') < 0 && sExp.indexOf('(') < 0) {
w = this.parseExpression(sExp, true);
} else {
@ -1232,6 +1223,7 @@ Macro10.PSEUDO_OP = {
REPEAT: "REPEAT",
SIXBIT: "SIXBIT",
SUBTTL: "SUBTTL",
TITLE: "TITLE",
XWD: "XWD"
};

View file

@ -617,7 +617,7 @@ class Debugger extends Component
* - - - - - - - - - - -- -- -- -- --
* 2 * { 3 + { 4 / 2 } }
*
* This function takes care of recursively processing sub-expressions, by processing subsets of the array,
* This function takes care of recursively processing grouped expressions, by processing subsets of the array,
* as well as handling certain base overrides (eg, temporarily switching to base-10 for binary shift suffixes).
*
* @param {Array.<string>} asValues
@ -720,6 +720,39 @@ class Debugger extends Component
return value;
}
/**
* parseASCII(sExp, chDelim, nBits, nMax)
*
* @this {Debugger}
* @param {string} sExp
* @param {string} chDelim
* @param {number} nBits
* @param {number} nMax
* @return {string}
*/
parseASCII(sExp, chDelim, nBits, nMax)
{
var i;
while ((i = sExp.indexOf(chDelim)) >= 0) {
var v = 0;
var n = nMax;
var j = i + 1;
while (n--) {
var ch = sExp[j++];
if (ch == chDelim) break;
var c = ch.charCodeAt(0);
if (nBits == 7) {
c &= 0x7F;
} else {
c = (c - 0x20) & 0x3F;
}
v = this.truncate(v * Math.pow(2, nBits) + c, nBits * nMax, true);
}
sExp = sExp.substr(0, i) + this.toStrBase(v, -1) + sExp.substr(j);
}
return sExp;
}
/**
* parseExpression(sExp, fQuiet)
*
@ -754,19 +787,26 @@ class Debugger extends Component
if (sExp) {
/*
* The default grouping characters for sub-expressions are braces; they can be changed by altering
* The default delimiting characters for grouped expressions are braces; they can be changed by altering
* achGroup, but when that happens, instead of changing our regular expressions and operator tables,
* we simply replace all achGroup characters with braces in the given expression.
*
* Why not just always use parentheses for sub-expressions? Because some debuggers use parseReference()
* to perform parenthetical value replacements in message strings, and they don't want parentheses taking
* on a different meaning. And for some machines, like the PDP-10, the convention is to use parentheses
* for indexed addressing and angle brackets for sub-expressions.
* Why not use parentheses for grouped expressions? Because some debuggers use parseReference() to perform
* parenthetical value replacements in message strings, and they don't want parentheses taking on a different
* meaning. And for some machines, like the PDP-10, the convention is to use parentheses for other things,
* like indexed addressing, and to use angle brackets for grouped expressions.
*/
if (this.achGroup[0] != '{') {
sExp = sExp.split(this.achGroup[0]).join('{').split(this.achGroup[1]).join('}');
}
/*
* Quoted ASCII characters can have a numeric value, too, which must be converted now, to avoid any
* conflicts with the operators below.
*/
sExp = this.parseASCII(sExp, '"', 7, 5); // MACRO-10 packs up to 5 7-bit ASCII codes in the value
sExp = this.parseASCII(sExp, "'", 6, 6); // MACRO-10 packs up to 6 6-bit ASCII (SIXBIT) codes in the value
/*
* All browsers (including, I believe, IE9 and up) support the following idiosyncrasy of a RegExp split():
* when the RegExp uses a capturing pattern, the resulting array will include entries for all the pattern
@ -903,17 +943,24 @@ class Debugger extends Component
} else {
value = this.getVariable(sValue);
if (value == null) {
/*
* A feature of MACRO-10 is that any single-digit number is automatically interpreted as base-10.
*/
var nBase = sValue.length > 1? this.nBase : 10;
if (iNegate < 0) {
sValue = '-' + sValue;
iNegate = 0;
}
value = Str.parseInt(sValue, this.nBase);
value = Str.parseInt(sValue, nBase);
}
}
if (value != null) {
if (iNegate < 0) {
value = -value;
} else if (iNegate > 0) {
/*
* This is easier than adding an evalNOT()....
*/
value = this.evalXOR(value, -1);
}
} else {
@ -1101,8 +1148,8 @@ if (DEBUGGER) {
'*': 9, // multiplication
'_': 10, // MACRO-10 shift operator
'^_': 10, // MACRO-10 internal shift operator (converted from 'B' suffix form that MACRO-10 uses)
'{': 11, // open sub-expression (achGroup[0] default)
'}': 11 // close sub-expression (achGroup[1] default)
'{': 11, // open grouped expression (achGroup[0] default)
'}': 11 // close grouped expression (achGroup[1] default)
};
/*