Advertisement
snake5

A simple script interpreter, named "DumbScript"

Mar 18th, 2012
225
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 6.09 KB | None | 0 0
  1.  
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <ctype.h>
  6. #include <assert.h>
  7.  
  8.  
  9. /*  the interpreter state   */
  10.  
  11. #define VARS_MAX    32
  12. #define NAME_MAX    32
  13. #define OPBUF_MAX   1024
  14.  
  15. typedef struct state_s
  16. {
  17.     int     varcount;
  18.     char    varkeys[ VARS_MAX * NAME_MAX ];
  19.     int     varvals[ VARS_MAX ];
  20.     char    opbuf[ OPBUF_MAX ];
  21. }
  22. state_t;
  23.  
  24.  
  25. /*  variables   */
  26. int state_var_find( state_t* S, const char* name )
  27. {
  28.     char* at = S->varkeys;
  29.     int i = 0;
  30.  
  31.     while( *at )
  32.     {
  33.         char* atend = at;
  34.         while( *atend && *atend != '=' )
  35.             atend++;
  36.  
  37.         if( strncmp( at, name, atend - at ) == 0 )
  38.             return i;
  39.  
  40.         if( !*atend )   break;
  41.         else            at = atend + 1;
  42.         i++;
  43.     }
  44.  
  45.     return -1;
  46. }
  47.  
  48. int state_var_add( state_t* S, const char* name )
  49. {
  50.     assert( S->varcount < VARS_MAX );
  51.     assert( strlen( name ) < NAME_MAX );
  52.  
  53.     S->varcount++;
  54.     strcat( S->varkeys, name );
  55.     strcat( S->varkeys, "=" );
  56.     return S->varcount - 1;
  57. }
  58.  
  59. void state_var_set( state_t* S, const char* name, int val )
  60. {
  61.     int at = state_var_find( S, name );
  62.  
  63.     if( at < 0 )    S->varvals[ state_var_add( S, name ) ] = val;
  64.     else            S->varvals[ at ] = val;
  65. }
  66.  
  67. int state_var_get( state_t* S, const char* name )
  68. {
  69.     int at = state_var_find( S, name );
  70.  
  71.     if( at < 0 )    return 0;
  72.     else            return S->varvals[ at ];
  73. }
  74.  
  75.  
  76. /*  operation buffer    */
  77. void state_opbuf_remove( state_t* S, int from, int to )
  78. {
  79.     int len = strlen( S->opbuf );
  80.  
  81.     memmove(
  82.         S->opbuf + from,
  83.         S->opbuf + to + 1,
  84.         len - to );
  85. }
  86.  
  87. void state_opbuf_replace( state_t* S, int from, int to, const char* str )
  88. {
  89.     int len     = strlen( S->opbuf );
  90.     int slen    = strlen( str );
  91.  
  92.     memmove(
  93.         S->opbuf + from + slen,
  94.         S->opbuf + to + 1,
  95.         len - to );
  96.  
  97.     memcpy( S->opbuf + from, str, slen );
  98. }
  99.  
  100. int state_opbuf_findbest( state_t* S )
  101. {
  102.     int op = -1;
  103.     int weight = -1;
  104.     int level = 0;
  105.  
  106.     char* ptr = S->opbuf;
  107.     while( *ptr )
  108.     {
  109.         if( *ptr == '(' )       level++;
  110.         else if( *ptr == ')' )  level--;
  111.         else if( *ptr == '=' ||
  112.             *ptr == '+' || *ptr == '-' ||
  113.             *ptr == '*' || *ptr == '/' )
  114.         {
  115.             int wt;
  116.             if( *ptr == '=' )   wt = 0;
  117.             else if( *ptr == '+' || *ptr == '-' )   wt = 1;
  118.             else if( *ptr == '*' || *ptr == '/' )   wt = 2;
  119.             wt += level * 3;
  120.             if( wt >= weight )
  121.             {
  122.                 op = ptr - S->opbuf;
  123.                 weight = wt;
  124.             }
  125.         }
  126.  
  127.         ptr++;
  128.     }
  129.  
  130.     return op;
  131. }
  132.  
  133. void state_opbuf_cleanparens( state_t* S )
  134. {
  135.     int clean = 1;
  136.  
  137.     while( clean )
  138.     {
  139.         char* ptr = S->opbuf;
  140.         int begin = -1;
  141.         int ops = 0;
  142.         clean = 0;
  143.  
  144.         while( *ptr )
  145.         {
  146.             if( *ptr == '(' )
  147.             {
  148.                 begin = ptr - S->opbuf;
  149.                 ops = 0;
  150.             }
  151.             else if( *ptr == ')' )
  152.             {
  153.                 if( !ops && begin >= 0 )
  154.                 {
  155.                     state_opbuf_remove( S, ptr - S->opbuf, ptr - S->opbuf );
  156.                     state_opbuf_remove( S, begin, begin );
  157.                     ptr -= 2;
  158.                     clean++;
  159.                 }
  160.                 begin = -1;
  161.             }
  162.             else if( strchr( "=+-*/", *ptr ) )
  163.                 ops++;
  164.  
  165.             ptr++;
  166.         }
  167.     }
  168. }
  169.  
  170. void state_opbuf_getargs( state_t* S, int op, int* from, int* to )
  171. {
  172.     char* ptr = S->opbuf + op - 1;
  173.     while( ptr >= S->opbuf && isalnum( *ptr ) ) ptr--;
  174.     *from = ptr + 1 - S->opbuf;
  175.  
  176.     ptr = S->opbuf + op + 1;
  177.     while( isalnum( *ptr ) ) ptr++;
  178.     *to = ptr - 1 - S->opbuf;
  179. }
  180.  
  181. void state_opbuf_parse( state_t* S )
  182. {
  183.     int op;
  184.  
  185. printf( "[opbuf_parse] input: %s\n", S->opbuf );
  186.  
  187.     state_opbuf_cleanparens( S );
  188.     op = state_opbuf_findbest( S );
  189.  
  190.     while( op >= 0 )
  191.     {
  192.         char optype = S->opbuf[ op ];
  193.         char operand1[ NAME_MAX ];
  194.         char operand2[ NAME_MAX ];
  195.         char outbuf[ NAME_MAX ];
  196.         int from, to, opval1, opval2, value;
  197.  
  198.         state_opbuf_getargs( S, op, &from, &to );
  199.         assert( op != from && op != to );
  200.  
  201. printf( "[opbuf_parse] " );
  202. fwrite( S->opbuf + from, 1, to - from + 1, stdout );
  203.  
  204.         memcpy( operand1, S->opbuf + from, op - from );
  205.         operand1[ op - from ] = 0;
  206.         memcpy( operand2, S->opbuf + op + 1, to - op );
  207.         operand2[ to - op ] = 0;
  208.  
  209.         if( isdigit( *operand1 ) )
  210.         {
  211.             assert( optype != '=' );
  212.             opval1 = atoi( operand1 );
  213.         }
  214.         else if( optype != '=' )
  215.             opval1 = state_var_get( S, operand1 );
  216.  
  217.         if( isdigit( *operand2 ) )
  218.             opval2 = atoi( operand2 );
  219.         else
  220.             opval2 = state_var_get( S, operand2 );
  221.  
  222.         switch( optype )
  223.         {
  224.         case '=':
  225.             state_var_set( S, operand1, opval2 );
  226. printf( "\t=> set( %s, %d )", operand1, opval2 );
  227.             state_opbuf_remove( S, op, to );
  228.             break;
  229.         case '+': case '-': case '*': case '/':
  230.             if( optype == '+' )         value = opval1 + opval2;
  231.             else if( optype == '-' )    value = opval1 - opval2;
  232.             else if( optype == '*' )    value = opval1 * opval2;
  233.             else if( optype == '/' )    value = opval1 / opval2;
  234.  
  235. printf( "\t=> %d %c %d = %d", opval1, optype, opval2, value );
  236.             sprintf( outbuf, "%d", value );
  237.             state_opbuf_replace( S, from, to, outbuf );
  238.             break;
  239.         default:
  240.             state_opbuf_replace( S, from, to, "0" );
  241.         }
  242.  
  243. putchar( '\n' );
  244.  
  245.         state_opbuf_cleanparens( S );
  246.         op = state_opbuf_findbest( S );
  247.     }
  248.  
  249.     S->opbuf[ 0 ] = 0;
  250. }
  251.  
  252.  
  253. /*  high-level functions    */
  254. void state_init( state_t* S )
  255. {
  256.     S->varcount     = 0;
  257.     S->varkeys[ 0 ] = 0;
  258.     S->opbuf[ 0 ]   = 0;
  259. }
  260.  
  261. void state_dump( state_t* S )
  262. {
  263.     int i = 0;
  264.     char* ptr = S->varkeys;
  265.  
  266.     printf( "-- state dump --\n" );
  267.     printf( "number of variables: %d\n", S->varcount );
  268.  
  269.     while( *ptr )
  270.     {
  271.         char* pbeg = ptr;
  272.         while( *ptr && *ptr != '=' )
  273.             ptr++;
  274.  
  275.         fwrite( pbeg, 1, ptr - pbeg, stdout );
  276.         putchar( '=' );
  277.         printf( "%d\n", S->varvals[ i++ ] );
  278.  
  279.         if( *ptr == '=' ) ptr++;
  280.     }
  281. }
  282.  
  283. void state_interpret( state_t* S, const char* str )
  284. {
  285.     const char* ptr = str;
  286.  
  287.     S->opbuf[ 0 ] = 0;
  288.     while( *ptr )
  289.     {
  290.         if( *ptr == ';' )
  291.         {
  292.             state_opbuf_parse( S );
  293.         }
  294.         else if( isalnum( *ptr ) || strchr( "=+-*/()", *ptr ) )
  295.         {
  296.             strncat( S->opbuf, ptr, 1 );
  297.         }
  298.         ptr++;
  299.     }
  300. }
  301.  
  302.  
  303.  
  304. const char* sample_program =
  305. "a = 5;\t"
  306. "b = 3;\t"
  307. "c = a;\n"
  308. "d = b + c * a + b;\n"
  309. "e = a + b * ( c + d );\n"
  310. "g = f = d;";
  311.  
  312. int main()
  313. {
  314.     printf( "DumbScript 3: a primitive interpreter\n-----\nCode:\n" );
  315.     printf( sample_program );
  316.     printf( "\n-----\nOutput:\n" );
  317.  
  318.     state_t state;
  319.     state_init( &state );
  320.     state_interpret( &state, sample_program );
  321.     state_dump( &state );
  322.  
  323.     printf( "\n-----\n" );
  324.     return 0;
  325. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement