lilo_booter

OpenJScad RPN Hacking v2

May 7th, 2016
103
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. function stack( )
  2. {
  3.     this.inner = [ ];
  4.     this.rstack = [ ];
  5.  
  6.     this.states = {
  7.         running: 0,
  8.         defining: 1,
  9.     };
  10.  
  11.     this.words = { };
  12.     this.parsers = { };
  13.  
  14.     this.state = [ this.states.running ];
  15.  
  16.     this.word_name = "";
  17.     this.word_current = [ ];
  18.  
  19.     this.parsing = "";
  20.  
  21.     this.state_push = function( state )
  22.     {
  23.         this.state.push( state );
  24.     }
  25.  
  26.     this.state_current = function( )
  27.     {
  28.         return this.state[ this.state.length - 1 ];
  29.     }
  30.  
  31.     this.state_done = function( )
  32.     {
  33.         this.state.pop( );
  34.     }
  35.  
  36.     this.define = function( name, func, parsing )
  37.     {
  38.         this.parsers[ name ] = parsing != null && parsing;
  39.         if ( typeof( func ) == "function" )
  40.             this.words[ name ] = func;
  41.         else if ( typeof( func ) == "string" )
  42.             this.words[ name ] = func.split( " " );
  43.         else
  44.             this.words[ name ] = func;
  45.         return this;
  46.     }
  47.  
  48.     this.parse = function( input )
  49.     {
  50.         var tokens = input.split( " " );
  51.         for ( var index in tokens )
  52.         {
  53.             var token = tokens[ index ];
  54.             if ( this.state_current( ) == this.states.running )
  55.             {
  56.                 if ( token == ":" )
  57.                     this.state_push( this.states.defining );
  58.                 else
  59.                     this.push( token );
  60.             }
  61.             else if ( this.state_current( ) == this.states.defining )
  62.             {
  63.                 if ( this.word_name == "" )
  64.                     this.word_name = token;
  65.                 else if ( token == ":" )
  66.                     this.state_push( this.states.defining );
  67.                 else if ( token != ";" )
  68.                     this.word_current.push( token );
  69.                 else
  70.                     this.state_done( );
  71.  
  72.                 if ( this.state_current( ) == this.states.running )
  73.                 {
  74.                     this.words[ this.word_name ] = this.word_current;
  75.                     this.word_current = [ ];
  76.                     this.word_name = "";
  77.                 }
  78.             }
  79.         }
  80.         return this;
  81.     }
  82.  
  83.     this.push = function( object )
  84.     {
  85.         if ( this.parsing == "" && typeof( object ) == "string" && object in this.parsers && this.parsers[ object ] )
  86.         {
  87.             this.inner.push( object );
  88.             this.parsing = object;
  89.         }
  90.         else if ( this.parsing != "" )
  91.         {
  92.             this.inner.push( object );
  93.             object = this.parsing;
  94.         }
  95.  
  96.         if ( typeof( object ) == "string" && object in this.words && typeof( this.words[ object ] ) == "function" )
  97.             this.words[ object ]( this.inner, this.rstack );
  98.         else if ( typeof( object ) == "string" && object in this.words )
  99.             this.execute( object );
  100.         else
  101.             this.inner.push( object );
  102.  
  103.         if ( this.parsing != "" )
  104.         {
  105.             var ret = parseInt( this.inner.pop( ) );
  106.             if ( ret == 0 )
  107.                 this.parsing = "";
  108.         }
  109.  
  110.         return this;
  111.     }
  112.  
  113.     this.execute = function( name )
  114.     {
  115.         var word = this.words[ name ];
  116.         for ( var index in word )
  117.             this.parse( word[ index ] );
  118.     }
  119.  
  120.     this.pop = function( )
  121.     {
  122.         return this.inner.pop( );
  123.     }
  124. }
  125.  
  126. function grammar( )
  127. {
  128.     var result = new stack( );
  129.  
  130.     // Basic maths
  131.     return result
  132.     .define( "*", function( s ) { s.push( parseFloat( s.pop( ) ) * parseFloat( s.pop( ) ) ); } )
  133.     .define( "+", function( s ) { s.push( parseFloat( s.pop( ) ) + parseFloat( s.pop( ) ) ); } )
  134.     .define( "-", function( s ) { var a = parseFloat( s.pop( ) ); s.push( parseFloat( s.pop( ) ) - a ); } )
  135.     .define( "/", function( s ) { var a = parseFloat( s.pop( ) ); s.push( parseFloat( s.pop( ) ) / a ); } )
  136.  
  137.     // Basic stack manipulations
  138.     .define( "pick", function( s ) { var index = parseInt( s.pop( ) ); s.push( s[ s.length - index - 1 ] ); } )
  139.     .define( "roll", function( s ) { var index = parseInt( s.pop( ) ); var a = s.splice( s.length - index - 1, 1 ); s.push( a[ 0 ] ); } )
  140.     .define( "pack", function( s ) { var length = parseInt( s.pop( ) ); var pack = s.splice( s.length - length, length ); echo( "pack: " + pack ); s[ s.length ] = pack; } )
  141.     .define( "drop", function( s ) { s.pop( ); } )
  142.  
  143.     // Standard FORTH words
  144.     .define( "dup", "0 pick" )
  145.     .define( "over", "1 pick" )
  146.     .define( "swap", "1 roll" )
  147.  
  148.     // Vector/array words
  149.     .define( "[", function( s, r ) { r.push( s.length ); } )
  150.     .define( "]", function( s, r ) { var start = r.pop( ); result.push( s.length - start ); result.push( "pack" ); } )
  151.  
  152.     // Map words
  153.     .define( "{", function( s, r ) { r.push( { } ); } )
  154.     .define( "}", function( s, r ) { s.push( r.pop( ) ); } )
  155.     .define( "::", function( s, r ) { var n = s.pop( ); if ( n != "::" ) r[ r.length - 1 ][ n ] = parseFloat( s.pop( ) ); s.push( n == "::" ? 1 : 0 ); }, true )
  156.  
  157.     // OpenJSCad words
  158.     .define( "cube", function( s ) { s.push( cube( s.pop( ) ) ); } )
  159.     .define( "sphere", function( s ) { s.push( sphere( s.pop( ) ) ); } )
  160.     .define( "union", function( s ) { var a = s.pop( ); s.push( union( s.pop( ), a ) ); } )
  161.     .define( "difference", function( s ) { var a = s.pop( ); s.push( difference( s.pop( ), a ) ); } )
  162.     .define( "intersection", function( s ) { var a = s.pop( ); s.push( intersection( s.pop( ), a ) ); } )
  163.     .define( "translate", function( s ) { var a = s.pop( ); s.push( s.pop( ).translate( a ) ); } )
  164.     .define( "scale", function( s ) { var a = s.pop( ); s.push( s.pop( ).scale( a ) ); } )
  165.  
  166.     // Debug
  167.     .define( "dump", function( s ) { echo( "dump: " + s ); } )
  168.     ;
  169. }
  170.  
  171. function main( )
  172. {
  173.     return grammar( )
  174.     .parse( "{ 3 :: size 1 :: center } cube" )
  175.     .parse( "{ 2 :: r 1 :: center } sphere" )
  176.     .parse( "difference" )
  177.     .parse( "{ 1.3 :: r 1 :: center } sphere" )
  178.     .parse( "{ 2.1 :: size 1 :: center } cube" )
  179.     .parse( "intersection" )
  180.     .parse( "union" )
  181.     .parse( "[ 0 0 1.5 ] translate" )
  182.     .parse( "10 scale" )
  183.     .pop( );
  184. }
Add Comment
Please, Sign In to add comment