Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- function stack( )
- {
- this.inner = [ ];
- this.rstack = [ ];
- this.states = {
- running: 0,
- defining: 1,
- };
- this.words = { };
- this.parsers = { };
- this.state = [ this.states.running ];
- this.word_name = "";
- this.word_current = [ ];
- this.parsing = "";
- this.state_push = function( state )
- {
- this.state.push( state );
- }
- this.state_current = function( )
- {
- return this.state[ this.state.length - 1 ];
- }
- this.state_done = function( )
- {
- this.state.pop( );
- }
- this.define = function( name, func, parsing )
- {
- this.parsers[ name ] = parsing != null && parsing;
- if ( typeof( func ) == "function" )
- this.words[ name ] = func;
- else if ( typeof( func ) == "string" )
- this.words[ name ] = func.split( " " );
- else
- this.words[ name ] = func;
- return this;
- }
- this.parse = function( input )
- {
- var tokens = input.split( " " );
- for ( var index in tokens )
- {
- var token = tokens[ index ];
- if ( this.state_current( ) == this.states.running )
- {
- if ( token == ":" )
- this.state_push( this.states.defining );
- else
- this.push( token );
- }
- else if ( this.state_current( ) == this.states.defining )
- {
- if ( this.word_name == "" )
- this.word_name = token;
- else if ( token == ":" )
- this.state_push( this.states.defining );
- else if ( token != ";" )
- this.word_current.push( token );
- else
- this.state_done( );
- if ( this.state_current( ) == this.states.running )
- {
- this.words[ this.word_name ] = this.word_current;
- this.word_current = [ ];
- this.word_name = "";
- }
- }
- }
- return this;
- }
- this.push = function( object )
- {
- if ( this.parsing == "" && typeof( object ) == "string" && object in this.parsers && this.parsers[ object ] )
- {
- this.inner.push( object );
- this.parsing = object;
- }
- else if ( this.parsing != "" )
- {
- this.inner.push( object );
- object = this.parsing;
- }
- if ( typeof( object ) == "string" && object in this.words && typeof( this.words[ object ] ) == "function" )
- this.words[ object ]( this.inner, this.rstack );
- else if ( typeof( object ) == "string" && object in this.words )
- this.execute( object );
- else
- this.inner.push( object );
- if ( this.parsing != "" )
- {
- var ret = parseInt( this.inner.pop( ) );
- if ( ret == 0 )
- this.parsing = "";
- }
- return this;
- }
- this.execute = function( name )
- {
- var word = this.words[ name ];
- for ( var index in word )
- this.parse( word[ index ] );
- }
- this.pop = function( )
- {
- return this.inner.pop( );
- }
- }
- function grammar( )
- {
- var result = new stack( );
- // Basic maths
- return result
- .define( "*", function( s ) { s.push( parseFloat( s.pop( ) ) * parseFloat( s.pop( ) ) ); } )
- .define( "+", function( s ) { s.push( parseFloat( s.pop( ) ) + parseFloat( s.pop( ) ) ); } )
- .define( "-", function( s ) { var a = parseFloat( s.pop( ) ); s.push( parseFloat( s.pop( ) ) - a ); } )
- .define( "/", function( s ) { var a = parseFloat( s.pop( ) ); s.push( parseFloat( s.pop( ) ) / a ); } )
- // Basic stack manipulations
- .define( "pick", function( s ) { var index = parseInt( s.pop( ) ); s.push( s[ s.length - index - 1 ] ); } )
- .define( "roll", function( s ) { var index = parseInt( s.pop( ) ); var a = s.splice( s.length - index - 1, 1 ); s.push( a[ 0 ] ); } )
- .define( "pack", function( s ) { var length = parseInt( s.pop( ) ); var pack = s.splice( s.length - length, length ); echo( "pack: " + pack ); s[ s.length ] = pack; } )
- .define( "drop", function( s ) { s.pop( ); } )
- // Standard FORTH words
- .define( "dup", "0 pick" )
- .define( "over", "1 pick" )
- .define( "swap", "1 roll" )
- // Vector/array words
- .define( "[", function( s, r ) { r.push( s.length ); } )
- .define( "]", function( s, r ) { var start = r.pop( ); result.push( s.length - start ); result.push( "pack" ); } )
- // Map words
- .define( "{", function( s, r ) { r.push( { } ); } )
- .define( "}", function( s, r ) { s.push( r.pop( ) ); } )
- .define( "::", function( s, r ) { var n = s.pop( ); if ( n != "::" ) r[ r.length - 1 ][ n ] = parseFloat( s.pop( ) ); s.push( n == "::" ? 1 : 0 ); }, true )
- // OpenJSCad words
- .define( "cube", function( s ) { s.push( cube( s.pop( ) ) ); } )
- .define( "sphere", function( s ) { s.push( sphere( s.pop( ) ) ); } )
- .define( "union", function( s ) { var a = s.pop( ); s.push( union( s.pop( ), a ) ); } )
- .define( "difference", function( s ) { var a = s.pop( ); s.push( difference( s.pop( ), a ) ); } )
- .define( "intersection", function( s ) { var a = s.pop( ); s.push( intersection( s.pop( ), a ) ); } )
- .define( "translate", function( s ) { var a = s.pop( ); s.push( s.pop( ).translate( a ) ); } )
- .define( "scale", function( s ) { var a = s.pop( ); s.push( s.pop( ).scale( a ) ); } )
- // Debug
- .define( "dump", function( s ) { echo( "dump: " + s ); } )
- ;
- }
- function main( )
- {
- return grammar( )
- .parse( "{ 3 :: size 1 :: center } cube" )
- .parse( "{ 2 :: r 1 :: center } sphere" )
- .parse( "difference" )
- .parse( "{ 1.3 :: r 1 :: center } sphere" )
- .parse( "{ 2.1 :: size 1 :: center } cube" )
- .parse( "intersection" )
- .parse( "union" )
- .parse( "[ 0 0 1.5 ] translate" )
- .parse( "10 scale" )
- .pop( );
- }
Add Comment
Please, Sign In to add comment