Skip to content

Commit

Permalink
much functionality / documentation wip
Browse files Browse the repository at this point in the history
  • Loading branch information
AchoDev committed Jan 4, 2023
1 parent d1d2c45 commit c308b69
Show file tree
Hide file tree
Showing 13 changed files with 253 additions and 82 deletions.
2 changes: 1 addition & 1 deletion src/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ const tokens = lexer.createTokens()
const parser = new Parser(tokens)
const tree = parser.parse()

// console.log(tree)
console.log(tree)

const interpreter = new Interpreter()
interpreter.interpret(tree)
Expand Down
23 changes: 22 additions & 1 deletion src/nodes.js
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,13 @@ class StringNode {
repr = () => this.value
}

class ReturnNode {
value
constructor(value) {
this.value = value
}
}

class FuncCreateNode {
returnNode = []
statementNode
Expand Down Expand Up @@ -180,6 +187,15 @@ class LogNode {
}
}

class InputNode {
outputNode
questionNode
constructor(output, question) {
this.outputNode = output
this.questionNode = question
}
}

class MutateNode {
ident
value
Expand All @@ -206,6 +222,7 @@ class LoopNode {
constructor(condition, statements) {
this.conditionNode = condition
this.statementNode = statements

}
}

Expand All @@ -220,10 +237,12 @@ class BooleanNode {
class ConditionNode {
condition
statementNode
elseNode

constructor(condition, statements) {
constructor(condition, statements, elseStatement) {
this.condition = condition
this.statementNode = statements
this.elseNode = elseStatement
}
}

Expand Down Expand Up @@ -260,11 +279,13 @@ module.exports = {
StatementSequence,
FuncCallNode,
LogNode,
InputNode,
MutateNode,
ModuloNode,
LoopNode,
BooleanNode,
ConditionNode,
CompareNode,
AndNode,
ReturnNode
}
81 changes: 71 additions & 10 deletions src/syntaxtree/interpreter.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@

const { SubtractNode, MultiplyNode, DivideNode, MinusNode } = require("../nodes")
const { SubtractNode, MultiplyNode, DivideNode, MinusNode, StringNode, VarAssignNode, ReferenceNode } = require("../nodes")
const { SymbolTable, Variable, _Function } = require("../variable")
const rls = require("readline-sync")

class Interpreter {

Expand Down Expand Up @@ -57,6 +58,9 @@ class Interpreter {
case 'LogNode':
result = this.printValue(node, localTable)
break
case 'InputNode':
result = this.getInput(node, localTable)
break
case 'MutateNode':
result = this.mutateVariable(node, localTable)
break
Expand All @@ -75,6 +79,9 @@ class Interpreter {
case 'AndNode':
result = this.andValues(node, localTable)
break
case 'ReturnNode':
result = this.open(node.value, localTable)
break
default:
console.log('\x1b[31m', `CRITICAL NODE ERROR: [${node.constructor.name} cannot be interpreted], '\x1b[37m'`)
}
Expand All @@ -93,9 +100,19 @@ class Interpreter {
openBooleanNode = (node) => node.bool

openStatementSequence(node, localTable) {
node.nodes.forEach(element => {
// node.nodes.forEach(element => {
// this.open(element, localTable)
// });

for(let element of node.nodes) {

if(element.constructor.name == 'ReturnNode') {
return this.open(element, localTable)
}

this.open(element, localTable)
});
}
return false
}

openAddNode(node, localTable) {
Expand Down Expand Up @@ -140,14 +157,28 @@ class Interpreter {
}

createVariable(node, localTable) {
localTable.add(new Variable('any', node.nodeA, this.open(node.nodeB)))

return node.nodeB.value

let value
if(node.nodeB) {
value = this.open(node.nodeB)
}

localTable.add(new Variable('any', node.nodeA, value))
}

createFunction(node, localTable) {

let returns = node.returnNode

if(node.returnNode.constructor.name == "VarAssignNode") {
node.statementNode.nodes.unshift(node.returnNode)
returns = new ReferenceNode(returns.nodeA)
}



let result
result = new _Function(node.returnNode, node.identifierNode, node.statementNode, localTable)
result = new _Function(returns, node.identifierNode, node.statementNode, localTable)
// console.log("RETURN -> " + node.returnNode)
localTable.add(result)
return result
Expand All @@ -163,16 +194,36 @@ class Interpreter {
}

const table = new SymbolTable()


table.setParent(localTable)

let result = this.open(func.body, table)
return result

if(result) {
return result
}

return this.open(func.returns, table)
}

loop(node, localTable) {
for(let i = this.open(node.conditionNode, localTable); i > 0; i--) {
this.open(node.statementNode, new SymbolTable(localTable))

const condition = this.open(node.conditionNode, localTable)

switch(typeof condition) {
case "boolean":
while(this.open(node.conditionNode, localTable)) {
this.open(node.statementNode, new SymbolTable(localTable))
}
break
case "number":
for(let i = this.open(node.conditionNode, localTable); i > 0; i--) {
this.open(node.statementNode, new SymbolTable(localTable))
}
break
}

}

openStringNode = (node) => node.value
Expand All @@ -192,9 +243,19 @@ class Interpreter {
console.log(this.open(node.node, localTable))
}

getInput(node, localTable) {
const input = rls.question(node.questionNode)
// const input = "here have me some absolutely beautiful input mate"

this.mutateVariable({"ident": node.outputNode.varName, "value": new StringNode(input)}, localTable)
return true
}

checkCondition(node, localTable) {
if(this.open(node.condition, localTable)) {
this.open(node.statementNode, new SymbolTable(localTable))
} else if(node.elseNode) {
this.open(node.elseNode, new SymbolTable(localTable))
}
}

Expand Down
69 changes: 49 additions & 20 deletions src/syntaxtree/lexer.js
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,10 @@ class Lexer {
tokens.push(new fToken.Token(fToken.TokenType.types.MOD))
} else if(this.currentChar == "&") {
this.advance()
if (this.currentChar == "&") tokens.push(new fToken.Token(fToken.TokenType.types.AND))
if (this.currentChar == "&") {
this.advance()
tokens.push(new fToken.Token(fToken.TokenType.types.AND))
}
else console.log("& --> ?????")
}

Expand Down Expand Up @@ -212,26 +215,52 @@ class Lexer {
if(string.slice(-1) == "'" || string.slice(-1) == '"') {
result = new fToken.Token(fToken.TokenType.types.STRING, string.slice(1, -1))
}
} else if(string == "func") {
result = new fToken.Token(fToken.TokenType.types.FUNCKEY)
} else if(string == "return") {
result = new fToken.Token(fToken.TokenType.types.RETURN)
} else if(string == "log") {
result = new fToken.Token(fToken.TokenType.types.LOG)
} else if(string == "loop") {
result = new fToken.Token(fToken.TokenType.types.LOOPKEY)
} else if(string == "if") {
result = new fToken.Token(fToken.TokenType.types.CONDKEY)
} else if(string == "true") {
result = new fToken.Token(fToken.TokenType.types.TRUE)
} else if(string == "false") {
result = new fToken.Token(fToken.TokenType.types.FALSE)
}
else {
result = new fToken.Token(fToken.TokenType.types.IDENT, string)
// console.log("think its an identifier thats the string ----->" + string)
} else {
switch(string) {
case 'func':
result = new fToken.Token(fToken.TokenType.types.FUNCKEY)
break

case 'return':
result = new fToken.Token(fToken.TokenType.types.RETURN)
break

case 'log':
result = new fToken.Token(fToken.TokenType.types.LOG)
break

case 'loop':
result = new fToken.Token(fToken.TokenType.types.LOOPKEY)
break

case 'if':
result = new fToken.Token(fToken.TokenType.types.CONDKEY)
break

case 'true':
result = new fToken.Token(fToken.TokenType.types.TRUE)
break

case 'false':
result = new fToken.Token(fToken.TokenType.types.FALSE)
break

case 'elseif':
result = new fToken.Token(fToken.TokenType.types.ELSEIF)
break

case 'else':
result = new fToken.Token(fToken.TokenType.types.ELSE)
break

case 'input':
result = new fToken.Token(fToken.TokenType.types.INPUT)
break

default:
result = new fToken.Token(fToken.TokenType.types.IDENT, string)
}
}
// console.log("ich bin ein " + JSON.stringify(result))
return result
}

Expand Down
Loading

0 comments on commit c308b69

Please sign in to comment.