mirror of
https://github.com/curioustorvald/tsvm.git
synced 2026-06-14 16:34:04 +09:00
basic: more parser wip
This commit is contained in:
@@ -1602,28 +1602,40 @@ bF._recurseApplyAST = function(tree, action) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
/** EBNF notation:
|
/** EBNF notation:
|
||||||
|
line = linenumber , stmt , {":" , stmt} ;
|
||||||
|
linenumber = digits ;
|
||||||
|
|
||||||
stmt =
|
stmt =
|
||||||
"IF" , equation , "THEN" , stmt , ["ELSE" , stmt]
|
"IF" , if_equation , "THEN" , stmt , ["ELSE" , stmt]
|
||||||
| "DEFUN" , [lit] , "(" , [lit , {" , " , lit}] , ")" , "=" , stmt
|
| "DEFUN" , [lit] , "(" , [lit , {" , " , lit}] , ")" , "=" , stmt
|
||||||
| "ON" , lit , function , equation , [{"," , equation}]
|
| "ON" , lit , lit , equation , {"," , equation}
|
||||||
| function , [equation , {argsep , equation}]
|
| function_call
|
||||||
| function , "(" , [equation , {argsep , equation}] , ")"
|
|
||||||
| equation
|
|
||||||
| "(" , stmt , ")" ;
|
| "(" , stmt , ")" ;
|
||||||
|
|
||||||
equation = lit , op , lit
|
function_call =
|
||||||
| op_uni , lit
|
lit
|
||||||
|
| lit , function_call , {argsep , function_call}
|
||||||
|
| lit , "(" , [function_call , {argsep , function_call}] , ")"
|
||||||
|
| equation
|
||||||
|
|
||||||
|
equation = equation , op , equation
|
||||||
|
| op_uni , equation
|
||||||
| lit
|
| lit
|
||||||
| "(" , equation , ")"
|
| "(" , equation , ")"
|
||||||
|
|
||||||
|
if_equation = if_equation , op - ("=") , if_equation
|
||||||
|
| op_uni , if_equation
|
||||||
|
| lit
|
||||||
|
| "(" , 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 = ","|";" ;
|
||||||
lit = alph , [digits] | num | string ;
|
lit = alph , [digits] | num | string ; (* example: "MyVar_2" *)
|
||||||
op = "^" | "*" | "/" | "MOD" | "+" | "-" | "<<" | ">>" | "<" | ">" | "<="
|
op = "^" | "*" | "/" | "MOD" | "+" | "-" | "<<" | ">>" | "<" | ">" | "<="
|
||||||
| "=<" | ">=" | "=>" | "==" | "<>" | "><" | "BAND" | "BXOR" | "BOR"
|
| "=<" | ">=" | "=>" | "==" | "<>" | "><" | "BAND" | "BXOR" | "BOR"
|
||||||
| "AND" | "OR" | "TO" | "STEP" | "!" | "~" | "#" | "=" | ":" ;
|
| "AND" | "OR" | "TO" | "STEP" | "!" | "~" | "#" | "=" ;
|
||||||
op_uni = "-" | "+" ;
|
op_uni = "-" | "+" ;
|
||||||
|
|
||||||
alph = letter | letter , alph ;
|
alph = letter | letter , alph ;
|
||||||
|
|||||||
@@ -24,6 +24,8 @@ bF._parseStmt = function(lnum, tokens, states, recDepth) {
|
|||||||
treeHead.astDepth = recDepth;
|
treeHead.astDepth = recDepth;
|
||||||
treeHead.astLnum = lnum;
|
treeHead.astLnum = lnum;
|
||||||
|
|
||||||
|
// ## case for:
|
||||||
|
// "IF" , if_equation , "THEN" , stmt , ["ELSE" , stmt]
|
||||||
if ("IF" == headTkn && "lit" == headSta) {
|
if ("IF" == headTkn && "lit" == headSta) {
|
||||||
// find nearest THEN and ELSE but also take parens into account
|
// find nearest THEN and ELSE but also take parens into account
|
||||||
let thenPos = -1;
|
let thenPos = -1;
|
||||||
@@ -59,14 +61,43 @@ bF._parseStmt = function(lnum, tokens, states, recDepth) {
|
|||||||
// "THEN" not found, raise error!
|
// "THEN" not found, raise error!
|
||||||
if (thenPos == -1) throw ParserError("IF without THEN in " + lnum);
|
if (thenPos == -1) throw ParserError("IF without THEN in " + lnum);
|
||||||
|
|
||||||
// TODO gotta go home :)
|
treeHead.astValue = "IF";
|
||||||
|
treeHead.astType = "function";
|
||||||
|
|
||||||
|
treeHead.astLeaves[0] = bF._parseEquation(lnum,
|
||||||
|
tokens.slice(1, thenPos),
|
||||||
|
states.slice(1, thenPos),
|
||||||
|
recDepth + 1,
|
||||||
|
true // if_equation mode
|
||||||
|
);
|
||||||
|
treeHead.astLeaves[1] = bF._parseStmt(lnum,
|
||||||
|
tokens.slice(thenPos + 1, (elsePos != -1) ? elsePos : tokens.length),
|
||||||
|
states.slice(thenPos + 1, (elsePos != -1) ? elsePos : tokens.length),
|
||||||
|
recDepth + 1
|
||||||
|
);
|
||||||
|
if (elsePos != -1)
|
||||||
|
treeHead.astLeaves[2] = bF._parseStmt(lnum,
|
||||||
|
tokens.slice(elsePos + 1, tokens.length),
|
||||||
|
states.slice(elsePos + 1, tokens.length),
|
||||||
|
recDepth + 1
|
||||||
|
);
|
||||||
|
|
||||||
|
return treeHead;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ## case for:
|
||||||
|
// ???
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
|
||||||
}
|
}
|
||||||
/** Parses following EBNF rule:
|
/** Parses following EBNF rule:
|
||||||
* lit (* which is parsed by the tokeniser already *)
|
* lit (* which is parsed by the tokeniser already *)
|
||||||
* @return: BasicAST
|
* @return: BasicAST
|
||||||
*/
|
*/
|
||||||
bF._parseLit = function(lnum, tokens, states, recDepth) {
|
bF._parseLit = function(lnum, tokens, states, recDepth) {
|
||||||
|
if (tokens.length > 1) throw ParserError();
|
||||||
|
|
||||||
let treeHead = new BasicAST();
|
let treeHead = new BasicAST();
|
||||||
treeHead.astDepth = recDepth;
|
treeHead.astDepth = recDepth;
|
||||||
treeHead.astLnum = lnum;
|
treeHead.astLnum = lnum;
|
||||||
@@ -82,7 +113,7 @@ bF._parseLit = function(lnum, tokens, states, recDepth) {
|
|||||||
}
|
}
|
||||||
// else, screw it
|
// else, screw it
|
||||||
else {
|
else {
|
||||||
throw lang.syntaxfehler(lnum, "TRAP_LITERALLY_LITERAL");
|
throw ParserError("TRAP_LITERALLY_LITERAL");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -98,7 +129,7 @@ bF._parseLit = function(lnum, tokens, states, recDepth) {
|
|||||||
* @return: BasicAST
|
* @return: BasicAST
|
||||||
*/
|
*/
|
||||||
bF._EquationIllegalTokens = ["IF","THEN","ELSE","DEFUN","ON"];
|
bF._EquationIllegalTokens = ["IF","THEN","ELSE","DEFUN","ON"];
|
||||||
bF._parseEquation = function(lnum, tokens, states, recDepth) {
|
bF._parseEquation = function(lnum, tokens, states, recDepth, ifMode) {
|
||||||
// scan for operators with highest precedence, use rightmost one if multiple were found
|
// scan for operators with highest precedence, use rightmost one if multiple were found
|
||||||
let topmostOp;
|
let topmostOp;
|
||||||
let topmostOpPrc = 0;
|
let topmostOpPrc = 0;
|
||||||
@@ -156,6 +187,10 @@ bF._parseEquation = function(lnum, tokens, states, recDepth) {
|
|||||||
if (topmostOp !== undefined) {
|
if (topmostOp !== undefined) {
|
||||||
if (_debugSyntaxAnalysis) serial.println("operator: "+topmostOp+", pos: "+operatorPos);
|
if (_debugSyntaxAnalysis) serial.println("operator: "+topmostOp+", pos: "+operatorPos);
|
||||||
|
|
||||||
|
if (ifMode && topmostOp == "=") throw lang.syntaxfehler(lnum, "'=' used on IF, did you mean '=='?");
|
||||||
|
if (ifMode && topmostOp == ":") throw lang.syntaxfehler(lnum, "':' used on IF");
|
||||||
|
|
||||||
|
|
||||||
// this is the AST we're going to build up and return
|
// this is the AST we're going to build up and return
|
||||||
// (other IF clauses don't use this)
|
// (other IF clauses don't use this)
|
||||||
let treeHead = new BasicAST();
|
let treeHead = new BasicAST();
|
||||||
@@ -188,7 +223,7 @@ bF._parseEquation = function(lnum, tokens, states, recDepth) {
|
|||||||
// ## case for:
|
// ## case for:
|
||||||
// lit
|
// lit
|
||||||
let headTkn = tokens[0].toUpperCase();
|
let headTkn = tokens[0].toUpperCase();
|
||||||
if (!bF._EquationIllegalTokens.includes(headTkn)) {
|
if (!bF._EquationIllegalTokens.includes(headTkn) && tokens.length == 1) {
|
||||||
return bF._parseLit(lnum, tokens, states, recDepth + 1);
|
return bF._parseLit(lnum, tokens, states, recDepth + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,25 +1,37 @@
|
|||||||
|
line = linenumber , stmt , {":" , stmt} ;
|
||||||
|
linenumber = digits ;
|
||||||
|
|
||||||
stmt =
|
stmt =
|
||||||
"IF" , equation , "THEN" , stmt , ["ELSE" , stmt]
|
"IF" , if_equation , "THEN" , stmt , ["ELSE" , stmt]
|
||||||
| "DEFUN" , [lit] , "(" , [lit , {" , " , lit}] , ")" , "=" , stmt
|
| "DEFUN" , [lit] , "(" , [lit , {" , " , lit}] , ")" , "=" , stmt
|
||||||
| "ON" , lit , function , equation , [{"," , equation}]
|
| "ON" , lit , lit , equation , {"," , equation}
|
||||||
| function , [equation , {argsep , equation}]
|
| function_call
|
||||||
| function , "(" , [equation , {argsep , equation}] , ")"
|
|
||||||
| equation
|
|
||||||
| "(" , stmt , ")" ;
|
| "(" , stmt , ")" ;
|
||||||
|
|
||||||
|
function_call =
|
||||||
|
lit
|
||||||
|
| lit , function_call , {argsep , function_call}
|
||||||
|
| lit , "(" , [function_call , {argsep , function_call}] , ")"
|
||||||
|
| equation
|
||||||
|
|
||||||
equation = equation , op , equation
|
equation = equation , op , equation
|
||||||
| op_uni , equation
|
| op_uni , equation
|
||||||
| lit
|
| lit
|
||||||
| "(" , equation , ")"
|
| "(" , equation , ")"
|
||||||
|
|
||||||
|
if_equation = if_equation , op - ("=") , if_equation
|
||||||
|
| op_uni , if_equation
|
||||||
|
| lit
|
||||||
|
| "(" , 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 = ","|";" ;
|
||||||
lit = alph , [digits] | num | string ;
|
lit = alph , [digits] | num | string ; (* example: "MyVar_2" *)
|
||||||
op = "^" | "*" | "/" | "MOD" | "+" | "-" | "<<" | ">>" | "<" | ">" | "<="
|
op = "^" | "*" | "/" | "MOD" | "+" | "-" | "<<" | ">>" | "<" | ">" | "<="
|
||||||
| "=<" | ">=" | "=>" | "==" | "<>" | "><" | "BAND" | "BXOR" | "BOR"
|
| "=<" | ">=" | "=>" | "==" | "<>" | "><" | "BAND" | "BXOR" | "BOR"
|
||||||
| "AND" | "OR" | "TO" | "STEP" | "!" | "~" | "#" | "=" | ":" ;
|
| "AND" | "OR" | "TO" | "STEP" | "!" | "~" | "#" | "=" ;
|
||||||
op_uni = "-" | "+" ;
|
op_uni = "-" | "+" ;
|
||||||
|
|
||||||
alph = letter | letter , alph ;
|
alph = letter | letter , alph ;
|
||||||
@@ -47,3 +59,24 @@ 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
|
||||||
|
1. cond
|
||||||
|
2. true
|
||||||
|
[3. false]
|
||||||
|
|
||||||
|
DEFUN
|
||||||
|
1. funcname
|
||||||
|
1. arg0
|
||||||
|
[2. arg1]
|
||||||
|
[3. argN...]
|
||||||
|
2. stmt
|
||||||
|
|
||||||
|
ON
|
||||||
|
1. varname
|
||||||
|
2. functionname
|
||||||
|
3. arg0
|
||||||
|
[4. arg1]
|
||||||
|
[5. argN...]
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user