Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
tree: d9b86481c5
Fetching contributors…

Cannot retrieve contributors at this time

319 lines (278 sloc) 7.961 kb
/~
XPL - eXample Programming Language v0.3
Written 2007 by J.M.K S.F. Software Technologies, Jan Max Meyer
The complete source of this program is in the Public Domain.
This example demonstrates the implementation of XPL, a complete,
interpretered scripting language, written in JS/CC.
XPL provides simple input/output operations and can only handle
numeric values.
Watch out for the *.xpl-files within the example directory, which
contain example scripts to be executed using XPL, for example a
countdown or a calculator.
~/
[*
//process.stdin.resume();
var read_string_exec = false,
read_string_node = false ;
read_string = function(fn){
process.stdin.resume();
process.stdin.setEncoding('utf8');
process.stdin.on('data', function (chunk) {
fn(chunk);
process.stdin.pause();
});
};
//process.stdin.pause();
//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_IF = 1;
var OP_IF_ELSE = 2;
var OP_WHILE_DO = 3;
var OP_DO_WHILE = 4;
var OP_WRITE = 5;
var OP_READ = 6;
var OP_SAY = 7;
var OP_EQU = 10;
var OP_NEQ = 11;
var OP_GRT = 12;
var OP_LOT = 13;
var OP_GRE = 14;
var OP_LOE = 15;
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 )
{
if(read_string_exec){
process.nextTick(function(){try{execute( node );}catch(e){};},1000);
throw "Wait";
}
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_IF:
if( execute( node.children[0] ) )
execute( node.children[1] );
break;
case OP_IF_ELSE:
if( execute( node.children[0] ) )
execute( node.children[1] );
else
execute( node.children[2] );
break;
case OP_WHILE_DO:
while( execute( node.children[0] ) )
execute( node.children[1] );
break;
case OP_DO_WHILE:
do
execute( node.children[0] );
while( execute( node.children[1] ) );
break;
case OP_WRITE:
require('util').print( execute( node.children[0] ) );
break;
case OP_READ:
read_string_exec = true;
read_string(function(val){read_string_exec = false;letvar( node.children[0].toString(), val);});
break;
case OP_SAY:
require('util').print( node.children[0].replace("\\n","\n") );
break;
case OP_EQU:
ret = execute( node.children[0] ) == execute( node.children[1] );
break;
case OP_NEQ:
ret = execute( node.children[0] ) != execute( node.children[1] );
break;
case OP_GRT:
ret = execute( node.children[0] ) > execute( node.children[1] );
break;
case OP_LOT:
ret = execute( node.children[0] ) < execute( node.children[1] );
break;
case OP_GRE:
ret = execute( node.children[0] ) >= execute( node.children[1] );
break;
case OP_LOE:
ret = execute( node.children[0] ) <= execute( node.children[1] );
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 = Number( getvar( node.value ) );
break;
case NODE_CONST:
ret = Number( node.value );
break;
}
return ret;
}
*]
! ' |\r|\n|\t|//[^\n]*\n'
"IF"
"ELSE"
"WHILE"
"DO"
"SAY"
"WRITE"
"READ"
'{'
'}'
';'
'='
'=='
'!='
'<='
'>='
'>'
'<'
'\+'
'\-'
'/'
'\*'
'\('
'\)'
'#'
'[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 [* try{execute( %2 );}catch(e){}; *]
|
;
Stmt_List: Stmt_List Stmt [* %% = createNode( NODE_OP, OP_NONE, %1, %2 ); *]
|
;
Stmt: IF Expression Stmt [* %% = createNode( NODE_OP, OP_IF, %2, %3 ); *]
| IF Expression Stmt ELSE Stmt [* %% = createNode( NODE_OP, OP_IF_ELSE, %2, %3, %5 ); *]
| WHILE Expression DO Stmt [* %% = createNode( NODE_OP, OP_WHILE_DO, %2, %4 ); *]
| DO Stmt WHILE Expression ';' [* %% = createNode( NODE_OP, OP_DO_WHILE, %2, %4 ); *]
| SAY String ';' [* %% = createNode( NODE_OP, OP_SAY, %2 ); *]
| WRITE Expression ';' [* %% = createNode( NODE_OP, OP_WRITE, %2 ); *]
| READ Identifier ';' [* %% = createNode( NODE_OP, OP_READ, %2 ); *]
| Identifier '=' Expression ';' [* %% = createNode( NODE_OP, OP_ASSIGN, %1, %3 ); *]
| '{' Stmt_List '}' [* %% = %2; *]
| ';' [* %% = createNode( NODE_OP, OP_NONE ); *]
;
Expression: Expression '==' AddSubExp [* %% = createNode( NODE_OP, OP_EQU, %1, %3 ); *]
| Expression '<' AddSubExp [* %% = createNode( NODE_OP, OP_LOT, %1, %3 ); *]
| Expression '>' AddSubExp [* %% = createNode( NODE_OP, OP_GRT, %1, %3 ); *]
| Expression '<=' AddSubExp [* %% = createNode( NODE_OP, OP_LOE, %1, %3 ); *]
| Expression '>=' AddSubExp [* %% = createNode( NODE_OP, OP_GRE, %1, %3 ); *]
| Expression '!=' AddSubExp [* %% = createNode( NODE_OP, OP_NEQ, %1, %3 ); *]
| AddSubExp
;
AddSubExp: AddSubExp '-' MulDivExp [* %% = createNode( NODE_OP, OP_SUB, %1, %3 ); *]
| AddSubExp '+' MulDivExp [* %% = createNode( NODE_OP, OP_ADD, %1, %3 ); *]
| MulDivExp
;
MulDivExp: MulDivExp '*' NegExp [* %% = createNode( NODE_OP, OP_MUL, %1, %3 ); *]
| MulDivExp '/' NegExp [* %% = createNode( NODE_OP, OP_DIV, %1, %3 ); *]
| NegExp
;
NegExp: '-' Value [* %% = createNode( NODE_OP, OP_NEG, %2 ); *]
| Value
;
Value: Integer [* %% = createNode( NODE_CONST, %1 ); *]
| Float [* %% = createNode( NODE_CONST, %1 ); *]
| Identifier [* %% = createNode( NODE_VAR, %1 ); *]
| '(' Expression ')' [* %% = %2; *]
;
[*
if(process.argv.length == 3) {
var str = require("fs").readFileSync( process.argv[2] ).toString("utf-8");
var error_cnt = 0;
var error_off = new Array();
var error_la = new Array();
if((error_cnt = __##PREFIX##parse(str, error_off, error_la)) > 0) {
var i;
for( i = 0; i < error_cnt; i++ ) {
console.log( "Parse error near >" + str.substr( error_off[i], 30 ) + "<, expecting \"" + error_la[i].join() + "\"" );
}
}
}
else {
console.log( 'usage: proram <filename>' );
}
*]
Jump to Line
Something went wrong with that request. Please try again.