In regards to my last question How would I write an interpreter for this in javascript? I'm attempting to create a JS/CC grammar. They have a live install of the program if you want to try my grammar out, just copy and paste it into the top box, click Build
and then Run
.
The result should run the little program at the bottom of the grammar, which is:
popup 'String Literal'
popup 42
set myVariable to 10
popup myVariable
When run you should get 3 alerts, the last one should be 10, but its 0. my full grammar is below, its a trimmed down, modified version of their sample. I could use some help on why the last alert is 0 and not 10 as I would have expected.
[*
//Structs
function NODE()
{
var type;
var value;
var children;
}
//Defines
var NODE_OP = 0;
var NODE_VAR = 1;
var NODE_CONST = 2;
var OP_NONE = -1;
var OP_ASSIGN = 0;
var OP_POPUP = 7;
var OP_ADD = 16;
var OP_SUB = 17;
var OP_DIV = 18;
var OP_MUL = 19;
var OP_NEG = 20;
//Management functions
function createNode(type, value, childs) {
var n = new NODE();
n.type = type;
n.value = value;
n.children = new Array();
for(var i = 2; i < arguments.length; i++)
n.children.push(arguments[i]);
return n;
}
var v_names = new Array();
var v_values = new Array();
//Interpreting function
function letvar(vname, value) {
var i;
for(i = 0; i < v_names.length; i++)
if(v_names[i].toString() == vname.toString())
break;
if(i == v_names.length) {
v_names.push(vname);
v_values.push(0);
}
v_values[i] = value;
}
function getvar(vname) {
var i;
for(i = 0; i < v_names.length; i++)
if(v_names[i].toString() == vname.toString())
return v_values[i];
return 0;
}
function execute(node) {
var ret = 0;
if(!node)
return 0;
switch(node.type)
{
case NODE_OP:
switch( node.value )
{
case OP_NONE:
if(node.children[0])
execute(node.children[0]);
if(node.children[1])
ret = execute(node.children[1]);
break;
case OP_ASSIGN:
letvar(node.children[0], execute(node.children[1]));
break;
case OP_POPUP:
alert(execute(node.children[0]));
break;
case OP_ADD:
ret = execute( node.children[0] ) + execute( node.children[1] );
break;
case OP_SUB:
ret = execute( node.children[0] ) - execute( node.children[1] );
break;
case OP_DIV:
ret = execute( node.children[0] ) / execute( node.children[1] );
break;
case OP_MUL:
ret = execute( node.children[0] ) * execute( node.children[1] );
break;
case OP_NEG:
ret = execute( node.children[0] ) * -1;
break;
}
break;
case NODE_VAR:
ret = getvar(node.value);
break;
case NODE_CONST:
ret = node.value;
break;
}
return ret;
}
*]
! ' |\r|\t'
"SET"
"POPUP"
"BEGIN"
"END"
'\n' EOL
"TO"
"ADD"
"SUB"
"NEG"
"DIV"
"MUL"
'\('
'\)'
'#'
'[A-Za-z_][A-Za-z0-9_]*' Identifier
'\'([^\']|\'\')*\'' String [* %match = %match.substr(1, %match.length - 2);
%match = %match.replace(/''/g, "\'"); *]
'[0-9]+' Integer
'[0-9]+\.[0-9]*|[0-9]*\.[0-9]+' Float
;
##
Program:
Program Stmt [* execute(%2); *]
|
;
Stmt:
POPUP Expression EOL [* %% = createNode(NODE_OP, OP_POPUP, %2); *]
| SET Identifier TO Expression EOL [* %% = createNode(NODE_OP, OP_ASSIGN, %1, %3); *]
| "BEGIN" Stmt_List "END" [* %% = %2; *]
| EOL [* %% = createNode(NODE_OP, OP_NONE); *]
;
Stmt_List:
Stmt_List Stmt [* %% = createNode(NODE_OP, OP_NONE, %1, %2); *]
|
;
Expression:
AddSubExp
;
AddSubExp:
AddSubExp "SUB" MulDivExp [* %% = createNode(NODE_OP, OP_SUB, %1, %3); *]
| AddSubExp "ADD" MulDivExp [* %% = createNode(NODE_OP, OP_ADD, %1, %3); *]
| MulDivExp
;
MulDivExp:
MulDivExp "MUL" NegExp [* %% = createNode(NODE_OP, OP_MUL, %1, %3); *]
| MulDivExp "DIV" NegExp [* %% = createNode(NODE_OP, OP_DIV, %1, %3); *]
| NegExp
;
NegExp:
"NEG" Value [* %% = createNode(NODE_OP, OP_NEG, %2); *]
| Value
;
Value:
Integer [* %% = createNode(NODE_CONST, %1); *]
| Float [* %% = createNode(NODE_CONST, %1); *]
| String [* %% = createNode(NODE_CONST, %1); *]
| Identifier [* %% = createNode(NODE_VAR, %1); *]
| '(' Expression ')' [* %% = %2; *]
;
[*
var str = "";
str += "popup 'String Literal'\n";
str += "popup 42\n";
str += "set myVariable to 10\n";
str += "popup myVariable\n";
var error_cnt = 0;
var error_off = new Array();
var error_la = new Array();
if( ( error_cnt = __parse( str, error_off, error_la ) ) > 0 )
{
for( i = 0; i < error_cnt; i++ )
alert( "Parse error near >"
+ str.substr( error_off[i], 30 ) + "<, expecting \"" + error_la[i].join() + "\"" );
}
*]