mirror of
https://github.com/curioustorvald/tsvm.git
synced 2026-06-12 23:54:04 +09:00
basic: new parser works with correctly entered IF, DEFUN and function_calls
This commit is contained in:
@@ -227,7 +227,7 @@ let BasicAST = function() {
|
|||||||
this.astLeaves = [];
|
this.astLeaves = [];
|
||||||
this.astSeps = [];
|
this.astSeps = [];
|
||||||
this.astValue = undefined;
|
this.astValue = undefined;
|
||||||
this.astType = "null"; // literal, operator, string, number, array, function, null, defun_args (! NOT usrdefun !)
|
this.astType = "null"; // lit, op, string, num, array, function, null, defun_args (! NOT usrdefun !)
|
||||||
}
|
}
|
||||||
let literalTypes = ["string", "num", "bool", "array", "generator"];
|
let literalTypes = ["string", "num", "bool", "array", "generator"];
|
||||||
/*
|
/*
|
||||||
@@ -1608,7 +1608,7 @@ linenumber = digits ;
|
|||||||
stmt =
|
stmt =
|
||||||
"IF" , if_equation , "THEN" , stmt , ["ELSE" , stmt]
|
"IF" , if_equation , "THEN" , stmt , ["ELSE" , stmt]
|
||||||
| "DEFUN" , [ident] , "(" , [ident , {" , " , ident}] , ")" , "=" , stmt
|
| "DEFUN" , [ident] , "(" , [ident , {" , " , ident}] , ")" , "=" , stmt
|
||||||
| "ON" , ident , ident , equation , {"," , equation}
|
| "ON" , if_equation , ident , if_equation , {"," , if_equation}
|
||||||
| "(" , stmt , ")"
|
| "(" , stmt , ")"
|
||||||
| function_call ;
|
| function_call ;
|
||||||
|
|
||||||
@@ -1628,7 +1628,7 @@ if_equation = if_equation , op - ("=") , if_equation
|
|||||||
| lit
|
| lit
|
||||||
| "(" , if_equation , ")" ;
|
| "(" , if_equation , ")" ;
|
||||||
|
|
||||||
(* don't bother looking at these, because you already know the stuff *)
|
(* don't bother looking at these, because you already know the stuff *)
|
||||||
|
|
||||||
function = lit ;
|
function = lit ;
|
||||||
argsep = ","|";" ;
|
argsep = ","|";" ;
|
||||||
@@ -1664,6 +1664,30 @@ hexdigit = "A" | "B" | "C" | "D" | "E" | "F" | "a" | "b"
|
|||||||
bindigit = "0" | "1" ;
|
bindigit = "0" | "1" ;
|
||||||
|
|
||||||
(* all possible token states: lit num op bool qot paren sep *)
|
(* all possible token states: lit num op bool qot paren sep *)
|
||||||
|
|
||||||
|
IF (type: function, value: IF)
|
||||||
|
1. cond
|
||||||
|
2. true
|
||||||
|
[3. false]
|
||||||
|
|
||||||
|
DEFUN (type: function, value: DEFUN)
|
||||||
|
1. funcname
|
||||||
|
1. arg0
|
||||||
|
[2. arg1]
|
||||||
|
[3. argN...]
|
||||||
|
2. stmt
|
||||||
|
|
||||||
|
ON (type: function, value: ON)
|
||||||
|
1. varname
|
||||||
|
2. functionname
|
||||||
|
3. arg0
|
||||||
|
[4. arg1]
|
||||||
|
[5. argN...]
|
||||||
|
|
||||||
|
FUNCTION_CALL (type: function, value: PRINT or something)
|
||||||
|
1. arg0
|
||||||
|
2. arg1
|
||||||
|
[3. argN...]
|
||||||
*/
|
*/
|
||||||
// @return BasicAST
|
// @return BasicAST
|
||||||
bF._parseEquation = functoin(lnum, tokens, states, recDepth) {
|
bF._parseEquation = functoin(lnum, tokens, states, recDepth) {
|
||||||
|
|||||||
@@ -28,6 +28,8 @@ bF._parseStmt = function(lnum, tokens, states, recDepth) {
|
|||||||
let parenDepth = 0;
|
let parenDepth = 0;
|
||||||
let parenStart = -1;
|
let parenStart = -1;
|
||||||
let parenEnd = -1;
|
let parenEnd = -1;
|
||||||
|
let sepsZero = [];
|
||||||
|
let sepsOne = [];
|
||||||
|
|
||||||
// scan for parens that will be used for several rules
|
// scan for parens that will be used for several rules
|
||||||
// also find nearest THEN and ELSE but also take parens into account
|
// also find nearest THEN and ELSE but also take parens into account
|
||||||
@@ -49,6 +51,11 @@ bF._parseStmt = function(lnum, tokens, states, recDepth) {
|
|||||||
else if (-1 == elsePos && "ELSE" == tokens[k].toUpperCase() && "lit" == states[k])
|
else if (-1 == elsePos && "ELSE" == tokens[k].toUpperCase() && "lit" == states[k])
|
||||||
elsePos = k;
|
elsePos = k;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (parenDepth == 0 && states[k] == "sep")
|
||||||
|
sepsZero.push(k);
|
||||||
|
if (parenDepth == 1 && states[k] == "sep")
|
||||||
|
sepsOne.push(k);
|
||||||
}
|
}
|
||||||
|
|
||||||
// unmatched brackets, duh!
|
// unmatched brackets, duh!
|
||||||
@@ -84,7 +91,44 @@ bF._parseStmt = function(lnum, tokens, states, recDepth) {
|
|||||||
|
|
||||||
return treeHead;
|
return treeHead;
|
||||||
}
|
}
|
||||||
|
// ## case for:
|
||||||
|
// | "DEFUN" , [ident] , "(" , [ident , {" , " , ident}] , ")" , "=" , stmt
|
||||||
|
if ("DEFUN" == headTkn && "lit" == headSta &&
|
||||||
|
parenStart == 2 && tokens[parenEnd + 1] == "=" && states[parenEnd + 1] == "op"
|
||||||
|
) {
|
||||||
|
treeHead.astValue = "DEFUN";
|
||||||
|
treeHead.astType = "function";
|
||||||
|
|
||||||
|
// parse function name
|
||||||
|
if (tokens[1] == "(") {
|
||||||
|
// anonymous function
|
||||||
|
treeHead.astLeaves[0] = BasicAST();
|
||||||
|
treeHead.astLeaves[0].astLnum = lnum;
|
||||||
|
treeHead.astLeaves[0].astDepth = recDepth;
|
||||||
|
treeHead.astLeaves[0].astType = "lit";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
treeHead.astLeaves[0] = bF._parseIdent(lnum, [tokens[1]], [states[1]], recDepth + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// parse function arguments
|
||||||
|
treeHead.astLeaves[0].astLeaves = sepsOne.map(i=>i-1).concat([parenEnd - 1])
|
||||||
|
.map(i=>bF._parseIdent(lnum, [tokens[i]], [states[i]], recDepth + 2));
|
||||||
|
|
||||||
|
// parse function body
|
||||||
|
treeHead.astLeaves[1] = bF._parseStmt(lnum,
|
||||||
|
tokens.slice(parenEnd + 2, tokens.length),
|
||||||
|
states.slice(parenEnd + 2, states.length),
|
||||||
|
recDepth + 1
|
||||||
|
);
|
||||||
|
|
||||||
|
return treeHead;
|
||||||
|
}
|
||||||
|
// ## case for:
|
||||||
|
// | "ON" , if_equation , ident , if_equation , {"," , if_equation}
|
||||||
|
if ("ON" == headTkn && "lit" == headSta) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
// ## case for:
|
// ## case for:
|
||||||
// | "(" , stmt , ")"
|
// | "(" , stmt , ")"
|
||||||
if (parenStart == 0 && parenEnd == tokens.length - 1) {
|
if (parenStart == 0 && parenEnd == tokens.length - 1) {
|
||||||
@@ -128,6 +172,7 @@ bF._parseFunctionCall = function(lnum, tokens, states, recDepth) {
|
|||||||
let _argsepsOnLevelOne = []; // argseps collected when parenDepth == 1
|
let _argsepsOnLevelOne = []; // argseps collected when parenDepth == 1
|
||||||
|
|
||||||
// Scan for unmatched parens and mark off the right operator we must deal with
|
// Scan for unmatched parens and mark off the right operator we must deal with
|
||||||
|
// every function_call need to re-scan because it is recursively called
|
||||||
for (let k = 0; k < tokens.length; k++) {
|
for (let k = 0; k < tokens.length; k++) {
|
||||||
// increase paren depth and mark paren start position
|
// increase paren depth and mark paren start position
|
||||||
if (tokens[k] == "(" && states[k] != "qot") {
|
if (tokens[k] == "(" && states[k] != "qot") {
|
||||||
@@ -179,7 +224,7 @@ bF._parseFunctionCall = function(lnum, tokens, states, recDepth) {
|
|||||||
recDepth + 1
|
recDepth + 1
|
||||||
));
|
));
|
||||||
treeHead.astType = "function";
|
treeHead.astType = "function";
|
||||||
treeHead.astSeps = argSeps;
|
treeHead.astSeps = argSeps.map(i => tokens[i]);
|
||||||
|
|
||||||
return treeHead;
|
return treeHead;
|
||||||
}
|
}
|
||||||
@@ -245,6 +290,7 @@ bF._parseEquation = function(lnum, tokens, states, recDepth, ifMode) {
|
|||||||
let parenEnd = -1;
|
let parenEnd = -1;
|
||||||
|
|
||||||
// Scan for unmatched parens and mark off the right operator we must deal with
|
// Scan for unmatched parens and mark off the right operator we must deal with
|
||||||
|
// every function_call need to re-scan because it is recursively called
|
||||||
for (let k = 0; k < tokens.length; k++) {
|
for (let k = 0; k < tokens.length; k++) {
|
||||||
// increase paren depth and mark paren start position
|
// increase paren depth and mark paren start position
|
||||||
if (tokens[k] == "(" && states[k] != "qot") {
|
if (tokens[k] == "(" && states[k] != "qot") {
|
||||||
@@ -355,7 +401,7 @@ let BasicAST = function() {
|
|||||||
this.astLeaves = [];
|
this.astLeaves = [];
|
||||||
this.astSeps = [];
|
this.astSeps = [];
|
||||||
this.astValue = undefined;
|
this.astValue = undefined;
|
||||||
this.astType = "null"; // literal, operator, string, number, array, function, null, defun_args (! NOT usrdefun !)
|
this.astType = "null"; // lit, op, string, num, array, function, null, defun_args (! NOT usrdefun !)
|
||||||
}
|
}
|
||||||
bF._opPrc = {
|
bF._opPrc = {
|
||||||
// function call in itself has highest precedence
|
// function call in itself has highest precedence
|
||||||
@@ -381,8 +427,11 @@ bF._opPrc = {
|
|||||||
};
|
};
|
||||||
bF._opRh = {"^":1,"=":1,"!":1,"IN":1};
|
bF._opRh = {"^":1,"=":1,"!":1,"IN":1};
|
||||||
let lnum = 10;
|
let lnum = 10;
|
||||||
let tokens = ["print","2","+","5","*","3"];
|
// FIXME print's last (;) gets parsed but ignored
|
||||||
let states = ["lit","num","op","num","op","num"];
|
//let tokens = ["if","s","<","2","then","(","nop1",")","else","(","if","s","<","9999","then","nop2","else","nop3",")"];
|
||||||
|
//let states = ["lit","lit","op","num","lit","paren","lit","paren","lit","paren","lit","lit","op","num","lit","lit","lit","lit","paren"];
|
||||||
|
let tokens = ["defun","HYPOT","(","X",",","Y",")","=","SQR","(","X","*","X","+","Y","*","Y",")"];
|
||||||
|
let states = ["lit","lit","paren","lit","sep","lit","paren","op","lit","paren","lit","op","lit","op","lit","op","lit","paren"];
|
||||||
let _debugSyntaxAnalysis = false;
|
let _debugSyntaxAnalysis = false;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ linenumber = digits ;
|
|||||||
stmt =
|
stmt =
|
||||||
"IF" , if_equation , "THEN" , stmt , ["ELSE" , stmt]
|
"IF" , if_equation , "THEN" , stmt , ["ELSE" , stmt]
|
||||||
| "DEFUN" , [ident] , "(" , [ident , {" , " , ident}] , ")" , "=" , stmt
|
| "DEFUN" , [ident] , "(" , [ident , {" , " , ident}] , ")" , "=" , stmt
|
||||||
| "ON" , ident , ident , equation , {"," , equation}
|
| "ON" , if_equation , ident , if_equation , {"," , if_equation}
|
||||||
| "(" , stmt , ")"
|
| "(" , stmt , ")"
|
||||||
| function_call ;
|
| function_call ;
|
||||||
|
|
||||||
@@ -61,7 +61,6 @@ bindigit = "0" | "1" ;
|
|||||||
|
|
||||||
(* all possible token states: lit num op bool qot paren sep *)
|
(* all possible token states: lit num op bool qot paren sep *)
|
||||||
|
|
||||||
|
|
||||||
IF (type: function, value: IF)
|
IF (type: function, value: IF)
|
||||||
1. cond
|
1. cond
|
||||||
2. true
|
2. true
|
||||||
|
|||||||
Reference in New Issue
Block a user