html += `<td>${phraseStyle(exp.$_)}</td>`;
html += '</tr>\n';
html += '<tr>';
html += '<td>["$`"]</td>';
html += `<td>${phraseStyle(exp['$`'])}</td>`;
html += '</tr>\n';
html += '<tr>';
html += '<td>["$&"]</td>';
html += `<td>${phraseStyle(exp['$&'], 'match')}</td>`;
html += '</tr>\n';
html += '<tr>';
html += '<td>["$\'"]</td>';
html += `<td>${phraseStyle(exp["$'"])}</td>`;
html += '</tr>\n';
for (const name in exp.rules) {
html += '<tr>';
html += `<td>["\${${name}}"]</td>`;
html += `<td>${phraseStyle(exp[`\${${name}}`])}</td>`;
html += '</tr>\n';
}
html += '</table>\n';
return html;
};
const sLastMatchToHtmlPage = function sLastMatchToHtmlPage(exp) {
return utils.htmlToPage(sLastMatchToHtml(exp), 'apg-exp last result');
};
const getMode = function getMode(modearg) {
let mode = MODE_ASCII;
if (typeof modearg === 'string' && modearg.length >= 3) {
const modein = modearg.toLowerCase().slice(0, 3);
if (modein === 'hex') {
mode = MODE_HEX;
} else if (modein === 'dec') {
mode = MODE_DEC;
} else if (modein === 'uni') {
mode = MODE_UNICODE;
}
}
return mode;
};
const modeToText = function modeToText(mode) {
let txt;
switch (mode) {
case MODE_ASCII:
txt = 'ascii';
break;
case MODE_HEX:
txt = 'hexadecimal';
break;
case MODE_DEC:
txt = 'decimal';
break;
case MODE_UNICODE:
txt = 'Unicode';
break;
default:
throw new Error('recognized mode');
}
return txt;
};
const charToHex = function charToHex(char) {
let ch = char.toString(16);
if (ch.length % 2 !== 0) {
ch = `0${ch}`;
}
return ch;
};
const charsToMode = function charsToMode(chars, mode) {
let txt = '';
if (mode === MODE_ASCII) {
txt += apglib.utils.charsToString(chars);
} else if (mode === MODE_DEC) {
txt += '[';
if (chars.length > 0) {
txt += chars[0];
for (let i = 1; i < chars.length; i += 1) {
txt += `,${chars[i]}`;
}
}
txt += ']';
} else if (mode === MODE_HEX) {
txt += '[';
if (chars.length > 0) {
txt += `\\x${charToHex(chars[0])}`;
for (let i = 1; i < chars.length; i += 1) {
txt += `,\\x${charToHex(chars[i])}`;
}
}
txt += ']';
} else if (mode === MODE_UNICODE) {
txt += '[';
if (chars.length > 0) {
txt += `\\u${charToHex(chars[0])}`;
for (let i = 1; i < chars.length; i += 1) {
txt += `,\\u${charToHex(chars[i])}`;
}
}
txt += ']';
}
return txt;
};
const uResultToText = function uResultToText(result, modeArg) {
const mode = getMode(modeArg);
let txt = '';
txt += ` result(${modeToText(mode)})\n`;
txt += ' [0]: ';
txt += charsToMode(result[0], mode);
txt += '\n';
txt += ` input: ${charsToMode(result.input, mode)}`;
txt += '\n';
txt += ` index: ${result.index}`;
txt += '\n';
txt += ` length: ${result.length}`;
txt += '\n';
txt += `tree depth: ${result.treeDepth}`;
txt += '\n';
txt += ` node hits: ${result.nodeHits}`;
txt += '\n';
txt += ' rules: ';
txt += '\n';
const { rules } = result;
for (const name in rules) {
const rule = rules[name];
if (rule) {
for (let i = 0; i < rule.length; i += 1) {
const ruleobj = rule[i];
txt += ` :${name} : ${ruleobj.index}: `;
txt += charsToMode(ruleobj.phrase, mode);
txt += '\n';
}
} else {
txt += ` :${name}: `;
txt += 'undefined';
txt += '\n';
}
}
return txt;
};
const uResultToHtml = function uResultToHtml(result, modeArg) {
const mode = getMode(modeArg);
let html = '';
let caption = 'result:';
caption += `(${modeToText(mode)})`;
html += `<table class="${style.CLASS_STATE}">\n`;
html += `<caption>${caption}</caption>\n`;
html += '<tr>';
html += '<th>item</th><th>value</th><th>phrase</th>';
html += '</tr>\n';
html += '<tr>';
html += '<td>[0]</td>';
html += `<td>${result.index}</td>`;
html += `<td>${phraseStyle(charsToMode(result[0], mode), 'match')}</td>`;
html += '</tr>\n';
html += '<tr>';
html += '<td>input</td>';
html += '<td>0</td>';
html += `<td>${phraseStyle(charsToMode(result.input, mode))}</td>`;
html += '</tr>\n';
html += '<tr>';
html += `<td>index</td><td>${result.index}</td>`;
html += '<td></td>';
html += '</tr>\n';
html += '<tr>';
html += `<td>length</td><td>${result.length}</td>`;
html += '<td></td>';
html += '</tr>\n';
html += '<tr>';
html += `<td>tree depth</td><td>${result.treeDepth}</td>`;
html += '<td></td>';
html += '</tr>\n';
html += '<tr>';
html += `<td>node hits</td><td>${result.nodeHits}</td>`;
html += '<td></td>';
html += '</tr>\n';
html += '<tr>';
html += '<th>rules</th><th>index</th><th>phrase</th>';
html += '</tr>\n';
const { rules } = result;
for (const name in rules) {
const rule = rules[name];
if (rule) {
for (let i = 0; i < rule.length; i += 1) {
const ruleobj = rule[i];
html += '<tr>';
html += `<td>${name}</td>`;
html += `<td>${ruleobj.index}</td>`;
html += `<td>${phraseStyle(charsToMode(ruleobj.phrase, mode), 'match')}</td>`;
html += '\n';
}
} else {
html += '<tr>';
html += `<td>${name}</td>`;
html += '<td></td>';
html += `<td>${phraseStyle(undefined)}</td>`;
html += '\n';
}
}
html += '</table>\n';
return html;
};
const uResultToHtmlPage = function uResultToHtmlPage(result, mode) {
return utils.htmlToPage(uResultToHtml(result, mode));
};
const uLastMatchToText = function uLastMatchToText(exp, modeArg) {
const mode = getMode(modeArg);
let txt = '';
txt += ` last match(${modeToText(mode)})\n`;
txt += ` lastIndex: ${exp.lastIndex}`;
txt += '\n';
txt += ` flags: "${exp.flags}"`;
txt += '\n';
txt += ` global: ${exp.global}`;
txt += '\n';
txt += ` sticky: ${exp.sticky}`;
txt += '\n';
txt += ` unicode: ${exp.unicode}`;
txt += '\n';
txt += ` debug: ${exp.debug}`;
txt += '\n';
if (exp['$&'] === undefined) {
txt += ' lastMatch: undefined';
txt += '\n';
return txt;
}
txt += ' input: ';
txt += charsToMode(exp.input, mode);
txt += '\n';
txt += ' leftContext: ';
txt += charsToMode(exp.leftContext, mode);
txt += '\n';
txt += ' lastMatch: ';
txt += charsToMode(exp.lastMatch, mode);
txt += '\n';
txt += 'rightContext: ';
txt += charsToMode(exp.rightContext, mode);
txt += '\n';
txt += ' rules:';
let prefix = '';
const indent = ' :';
for (const name in exp.rules) {
txt += `${prefix + name} : `;
txt += exp.rules[name] ? charsToMode(exp.rules[name], mode) : 'undefined';
txt += '\n';
prefix = indent;
}
txt += '\n';
txt += ' alias:\n';
txt += ' ["$_"]: ';
txt += charsToMode(exp.$_, mode);
txt += '\n';
txt += ' ["$`"]: ';
txt += charsToMode(exp['$`'], mode);
txt += '\n';
txt += ' ["$&"]: ';
txt += charsToMode(exp['$&'], mode);
txt += '\n';
txt += ' ["$\'"]: ';
txt += charsToMode(exp["$'"], mode);
txt += '\n';
for (const name in exp.rules) {
txt += ` ["\${${name}}"]: `;
txt += exp[`\${${name}}`] ? charsToMode(exp[`\${${name}}`], mode) : 'undefined';
txt += '\n';
}
return txt;
};
const uLastMatchToHtml = function uLastMatchToHtml(exp, modeArg) {
const mode = getMode(modeArg);
let html = '';
let caption = 'last match:';
caption += `(${modeToText(mode)})`;
html += `<table class="${style.CLASS_STATE}">\n`;
html += `<caption>${caption}</caption>\n`;
html += '<tr>';
html += '<th>item</th><th>value</th>';
html += '</tr>\n';
html += '<tr>';
html += '<td>lastIndex</td>';
html += `<td>${exp.lastIndex}</td>`;
html += '</tr>\n';
html += '<tr>';
html += '<td>flags</td>';
html += `<td>"${exp.flags}"</td>`;
html += '</tr>\n';
html += '<tr>';
html += '<td>global</td>';
html += `<td>${exp.global}</td>`;
html += '</tr>\n';
html += '<tr>';
html += '<td>sticky</td>';
html += `<td>${exp.sticky}</td>`;
html += '</tr>\n';
html += '<tr>';
html += '<td>unicode</td>';
html += `<td>${exp.unicode}</td>`;
html += '</tr>\n';
html += '<tr>';
html += '<td>debug</td>';
html += `<td>${exp.debug}</td>`;
html += '</tr>\n';
html += '<tr>';
html += '<th>item</th><th>phrase</th>';
html += '</tr>\n';
if (exp['$&'] === undefined) {
html += '<tr>';
html += '<td>lastMatch</td>';
html += `<td>${phraseStyle(undefined)}</td>`;
html += '</tr>\n';
html += '</table>\n';
return html;
}
html += '<tr>';
html += '<td>input</td>';
html += `<td>${phraseStyle(charsToMode(exp.input, mode))}</td>`;
html += '</tr>\n';
html += '<tr>';
html += '<td>leftContext</td>';
html += `<td>${phraseStyle(charsToMode(exp.leftContext, mode))}</td>`;
html += '</tr>\n';
html += '<tr>';
html += '<td>lastMatch</td>';
html += `<td>${phraseStyle(charsToMode(exp.lastMatch, mode), 'match')}</td>`;
html += '</tr>\n';
html += '<tr>';
html += '<td>rightContext</td>';
html += `<td>${phraseStyle(charsToMode(exp.rightContext, mode))}</td>`;
html += '</tr>\n';
html += '<tr>';
html += '<th>rules</th><th>phrase</th>';
html += '</tr>\n';
for (const name in exp.rules) {
html += '<tr>';
html += `<td>${name}</td>`;
if (exp.rules[name]) {
html += `<td>${phraseStyle(charsToMode(exp.rules[name], mode))}</td>`;
} else {
html += `<td>${phraseStyle(undefined)}</td>`;
}
html += '</tr>\n';
}
html += '<tr>';
html += '<th>alias</th><th>phrase</th>';
html += '</tr>\n';
html += '<tr>';
html += '<td>["$_"]</td>';
html += `<td>${phraseStyle(charsToMode(exp.$_, mode))}</td>`;
html += '</tr>\n';
html += '<tr>';
html += '<td>["$`"]</td>';
html += `<td>${phraseStyle(charsToMode(exp['$`'], mode))}</td>`;
html += '</tr>\n';
html += '<tr>';
html += '<td>["$&"]</td>';
html += `<td>${phraseStyle(charsToMode(exp['$&'], mode), 'match')}</td>`;
html += '</tr>\n';
html += '<tr>';
html += '<td>["$\'"]</td>';
html += `<td>${phraseStyle(charsToMode(exp["$'"], mode))}</td>`;
html += '</tr>\n';
for (const name in exp.rules) {
html += '<tr>';
html += `<td>["\${${name}}"]</td>`;
if (exp[`\${${name}}`]) {
html += `<td>${phraseStyle(charsToMode(exp[`\${${name}}`], mode))}</td>`;
} else {
html += `<td>${phraseStyle(undefined)}</td>`;
}
html += '</tr>\n';
}
html += '</table>\n';
return html;
};
const uLastMatchToHtmlPage = function uLastMatchToHtmlPage(exp, mode) {
return utils.htmlToPage(uLastMatchToHtml(exp, mode));
};
const sourceToText = function sourceToText(exp) {
return exp.source;
};
const sourceToHtml = function sourceToHtml(exp) {
const rx = /.*(\r\n|\n|\r)/g;
let result;
let chars;
let html;
html = '<pre>\n';
const TRUE = true;
while (TRUE) {
result = rx.exec(exp.source);
if (result === null || result[0] === '') {
break;
}
chars = apglib.utils.stringToChars(result[0]);
html += apglib.utils.charsToAsciiHtml(chars);
html += '\n';
}
html += '</pre>\n';
return html;
};
const sourceToHtmlPage = function sourceToHtmlPage(exp) {
return apglib.utils.htmlToPage(sourceToHtml(exp), 'apg-exp source');
};
module.exports = {
s: {
resultToText: sResultToText,
resultToHtml: sResultToHtml,
resultToHtmlPage: sResultToHtmlPage,
expToText: sLastMatchToText,
expToHtml: sLastMatchToHtml,
expToHtmlPage: sLastMatchToHtmlPage,
sourceToText,
sourceToHtml,
sourceToHtmlPage,
},
u: {
resultToText: uResultToText,
resultToHtml: uResultToHtml,
resultToHtmlPage: uResultToHtmlPage,
expToText: uLastMatchToText,
expToHtml: uLastMatchToHtml,
expToHtmlPage: uLastMatchToHtmlPage,
},
};