created namespace for ast related constructors

This commit is contained in:
overflowerror 2022-04-11 20:29:02 +02:00
parent 741ff1c347
commit 333eb79820

View file

@ -4,111 +4,114 @@
var functions = []; var functions = [];
var file = "[anonymous]"; var file = "[anonymous]";
function executeCommand(args, std) { function executeCommand(args, std) {
console.log(`args: ${args}, std: ${std}`); console.log(`args: ${args}, std: ${std}`);
} }
function astSequence() { const ast = {
let commands = []; sequence: function() {
return { let commands = [];
add: c => commands.push(c), return {
execute: (std) => commands.forEach(c => c.execute(std)), add: c => commands.push(c),
toString: () => "sequence {\n" + commands execute: (std) => commands.forEach(c => c.execute(std)),
.map(c => c.toString()) toString: () => "sequence {\n" + commands
.map(s => s.split("\n")) .map(c => c.toString())
.map(a => a.map(s => " " + s)) .map(s => s.split("\n"))
.map(a => a.join("\n")) .map(a => a.map(s => " " + s))
.join(",\n") + "\n}", .map(a => a.join("\n"))
} .join(",\n") + "\n}",
} }
},
function astCommand() { command: function() {
let args = []; let args = [];
return { return {
add: a => args.push(a), add: a => args.push(a),
size: a => args.length, size: a => args.length,
execute: (std) => { execute: (std) => {
let evaluatedArgs = args.map(a => a.evaluate()); let evaluatedArgs = args.map(a => a.evaluate());
executeCommand(evaluatedArgs, std); executeCommand(evaluatedArgs, std);
},
toString: () => "command {\n" + args
.map(a => a.toString())
.map(s => s.split("\n"))
.map(a => a.map(s => " " + s))
.map(a => a.join("\n"))
.join(",\n") + "\n}",
};
},
assignment: function(name) {
let value = ast.value.string("");
return {
setValue: v => { value = v; },
execute: (std) => {
variables[name] = value.evaluate();
},
toString: () => `assign '${name}'=\n${value.toString().split('\n').map(l => " " + l).join("\n")}`,
};
},
value: {
compound: function() {
let components = [];
const self = {
add: c => components.push(c),
evaluate: () => components.map(c => c.evaluate()).join(""),
toString: () => "compound {\n" + components
.map(a => a.toString())
.map(s => s.split("\n"))
.map(a => a.map(s => " " + s))
.map(a => a.join("\n"))
.join(",\n") + "\n}",
reduce: () => {
if (components.length == 1) {
if (components[0].reduce) {
return components[0].reduce();
} else {
return components[0];
}
} else {
return self;
}
},
};
return self;
}, },
toString: () => "command {\n" + args
.map(a => a.toString())
.map(s => s.split("\n"))
.map(a => a.map(s => " " + s))
.map(a => a.join("\n"))
.join(",\n") + "\n}",
};
}
function astAssignment(name) { string: function(str) {
let value = astValueString(""); return {
return { evaluate: () => str,
setValue: v => { value = v; }, toString: () => "'" + str + "'",
execute: (std) => { };
variables[name] = value.evaluate();
}, },
toString: () => `assign '${name}'=\n${value.toString().split('\n').map(l => " " + l).join("\n")}`,
};
}
function astValueCompound() { variable: function(name) {
let components = []; return {
const self = { // add support for multiple arguments in one variable
add: c => components.push(c), evaluate: () => variables[name],
evaluate: () => components.map(c => c.evaluate()).join(""), toString: () => `var '${name}'`,
toString: () => "compound {\n" + components
.map(a => a.toString())
.map(s => s.split("\n"))
.map(a => a.map(s => " " + s))
.map(a => a.join("\n"))
.join(",\n") + "\n}",
reduce: () => {
if (components.length == 1) {
if (components[0].reduce) {
return components[0].reduce();
} else {
return components[0];
}
} else {
return self;
} }
}, },
};
return self;
}
function astValueString(str) { commandSubstitution: function(ast) {
return { return {
evaluate: () => str, evaluate: () => {
toString: () => "'" + str + "'", // TODO
}; },
} toString: () => "not implemented",
};
function astValueVar(name) {
return {
// add support for multiple arguments in one variable
evaluate: () => variables[name],
toString: () => `var '${name}'`,
}
}
function astValueCommandSubstitution(ast) {
return {
evaluate: () => {
// TODO
}, },
toString: () => "not implemented",
};
}
function astValueProcessSubstitution(ast) { processSubstitution: function(ast) {
return { return {
evaluate: () => { evaluate: () => {
// TODO // TODO
},
toString: () => "not implemented",
};
}, },
toString: () => "not implemented", },
};
} }
function panic(line, message) { function panic(line, message) {
@ -172,7 +175,7 @@
function doubleQuoteToAst(quoteContent, line) { function doubleQuoteToAst(quoteContent, line) {
const length = quoteContent.length; const length = quoteContent.length;
let astRoot = astValueCompound(); let astRoot = ast.value.compound();
let buffer = ""; let buffer = "";
@ -189,7 +192,7 @@
switch(state) { switch(state) {
case QS_INIT: case QS_INIT:
if (c == '$') { if (c == '$') {
astRoot.add(astValueString(buffer)); astRoot.add(ast.value.string(buffer));
buffer = ""; buffer = "";
if (i < length - 1 && quoteContent[i + 1] == '(') { if (i < length - 1 && quoteContent[i + 1] == '(') {
state = QS_SUBSTITUTION; state = QS_SUBSTITUTION;
@ -203,7 +206,7 @@
break; break;
case QS_VARIABLE: case QS_VARIABLE:
if (!("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".includes(c))) { if (!("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".includes(c))) {
astRoot.add(astValueVar(buffer)); astRoot.add(ast.value.variable(buffer));
buffer = ""; buffer = "";
state = QS_INIT; state = QS_INIT;
i--; i--;
@ -223,10 +226,10 @@
if (buffer) { if (buffer) {
switch(state) { switch(state) {
case QS_INIT: case QS_INIT:
astRoot.add(astValueString(buffer)); astRoot.add(ast.value.string(buffer));
break; break;
case QS_VARIABLE: case QS_VARIABLE:
astRoot.add(astValueVar(buffer)); astRoot.add(ast.value.variable(buffer));
break; break;
case QS_SUBSTITUTION: case QS_SUBSTITUTION:
throw "not implemented"; throw "not implemented";
@ -248,7 +251,7 @@
const PS_COMMAND = 1; const PS_COMMAND = 1;
const PS_ASSIGN = 2; const PS_ASSIGN = 2;
let astRoot = astSequence(); let astRoot = ast.sequence();
let current = null; let current = null;
let value = null; let value = null;
@ -265,7 +268,7 @@
} else if (c == '#') { } else if (c == '#') {
state = PS_COMMENT; state = PS_COMMENT;
} else { } else {
current = astCommand(); current = ast.command();
buffer = c; buffer = c;
state = PS_COMMAND; state = PS_COMMAND;
} }
@ -281,9 +284,9 @@
if (value) { if (value) {
if (buffer) { if (buffer) {
if (buffer[0] == '$') { if (buffer[0] == '$') {
value.add(astValueVar(buffer.substring(1))); value.add(ast.value.variable(buffer.substring(1)));
} else { } else {
value.add(astValueString(buffer.replaceAll('\\$', '$'))); value.add(ast.value.string(buffer.replaceAll('\\$', '$')));
} }
buffer = ""; buffer = "";
} }
@ -291,9 +294,9 @@
value = null; value = null;
} else if (buffer) { } else if (buffer) {
if (buffer[0] == '$') { if (buffer[0] == '$') {
current.add(astValueVar(buffer.substring(1))); current.add(ast.value.variable(buffer.substring(1)));
} else { } else {
current.add(astValueString(buffer.replaceAll('\\$', '$'))); current.add(ast.value.string(buffer.replaceAll('\\$', '$')));
} }
buffer = ""; buffer = "";
} }
@ -304,9 +307,9 @@
if (value) { if (value) {
if (buffer) { if (buffer) {
if (buffer[0] == '$') { if (buffer[0] == '$') {
value.add(astValueVar(buffer.substring(1))); value.add(ast.value.variable(buffer.substring(1)));
} else { } else {
value.add(astValueString(buffer.replaceAll('\\$', '$'))); value.add(ast.value.string(buffer.replaceAll('\\$', '$')));
} }
buffer = ""; buffer = "";
} }
@ -314,26 +317,26 @@
value = null; value = null;
} else if (buffer) { } else if (buffer) {
if (buffer[0] == '$') { if (buffer[0] == '$') {
current.add(astValueVar(buffer.substring(1))); current.add(ast.value.variable(buffer.substring(1)));
} else { } else {
current.add(astValueString(buffer.replaceAll('\\$', '$'))); current.add(ast.value.string(buffer.replaceAll('\\$', '$')));
} }
buffer = ""; buffer = "";
} }
} else if (c == '"') { } else if (c == '"') {
if (!value) { if (!value) {
value = astValueCompound(); value = ast.value.compound();
} }
if (buffer) { if (buffer) {
value.add(astValueString(buffer)); value.add(ast.value.string(buffer));
buffer = ""; buffer = "";
} }
const end = findSymbolInScope(content, line, '"', i + 1, length); const end = findSymbolInScope(content, line, '"', i + 1, length);
const [ast, _line] = doubleQuoteToAst(content.substring(i + 1, end), line); const [_ast, _line] = doubleQuoteToAst(content.substring(i + 1, end), line);
line = _line; line = _line;
value.add(ast); value.add(_ast);
i = end; i = end;
} else if (c == "'") { } else if (c == "'") {
@ -345,7 +348,7 @@
} }
i = end; i = end;
} else if (c == '=' && current.size() == 0) { } else if (c == '=' && current.size() == 0) {
current = astAssignment(buffer); current = ast.assignment(buffer);
state = PS_ASSIGN; state = PS_ASSIGN;
buffer = ""; buffer = "";
} else { } else {
@ -358,21 +361,21 @@
if (value) { if (value) {
if (buffer) { if (buffer) {
if (buffer[0] == "$") { if (buffer[0] == "$") {
value.add(astValueVar(buffer.substring(1))); value.add(ast.value.variable(buffer.substring(1)));
} else { } else {
value.add(astValueString(buffer)); value.add(ast.value.string(buffer));
} }
} }
current.setValue(value.reduce()); current.setValue(value.reduce());
value = null; value = null;
} else if (buffer) { } else if (buffer) {
if (buffer[0] == "$") { if (buffer[0] == "$") {
current.setValue(astValueVar(buffer.substring(1))); current.setValue(ast.value.variable(buffer.substring(1)));
} else { } else {
current.setValue(astValueString(buffer)); current.setValue(ast.value.string(buffer));
} }
} else { } else {
current.setValue(astValueString("")); current.setValue(ast.value.string(""));
} }
buffer = ""; buffer = "";
astRoot.add(current); astRoot.add(current);
@ -380,18 +383,18 @@
state = PS_INIT; state = PS_INIT;
} else if (c == '"') { } else if (c == '"') {
if (!value) { if (!value) {
value = astValueCompound(); value = ast.value.compound();
} }
if (buffer) { if (buffer) {
value.add(astValueString(buffer)); value.add(ast.value.string(buffer));
buffer = ""; buffer = "";
} }
const end = findSymbolInScope(content, line, '"', i + 1, length); const end = findSymbolInScope(content, line, '"', i + 1, length);
const [ast, _line] = doubleQuoteToAst(content.substring(i + 1, end), line); const [_ast, _line] = doubleQuoteToAst(content.substring(i + 1, end), line);
line = _line; line = _line;
value.add(ast); value.add(_ast);
i = end; i = end;
} else if (c == "'") { } else if (c == "'") {