⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 compiler.cpp

📁 c-smile 一个语法类似与JS 又有点像C++的 编译器
💻 CPP
📖 第 1 页 / 共 4 页
字号:
    {
      delete temporaries;
      temporaries = save_temp;
    }

    return last_stat;
  }

  // do_return - handle the RETURN expression
  void
    compiler::do_return ()
  {
    if ( inConstructor )
    {
      compiler::PVAL pv;
      findvariable ( "this", &pv );
      rvalue ( &pv );
    }
    else
    {
      int tkn = scan.token ();
      scan.stoken ( tkn );
      if ( tkn == ';')
        putcbyte ( OP_UNDEFINED );
      else do_expr ();
    }
    frequire ( ';' );
    putcbyte ( OP_RETURN );
  }

  // do_test - compile a test expression
  void
    compiler::do_test ()
  {
    frequire ( '(' );
    do_expr  ();
    frequire ( ')' );
  }

  // do_expr - parse an expression
  void
    compiler::do_expr ()
  {
    compiler::PVAL pv;
    do_expr1 ( &pv );
    rvalue   ( &pv );
  }

  // rvalue - get the rvalue of a partial expression
  void
    compiler::rvalue ( compiler::PVAL *pv )
  {
    if ( pv->fcn )
    {
      ( *pv->fcn ) ( this, LOAD, pv->val );
      pv->fcn = NULL;
    }
  }

  // chklvalue - make sure we've got an lvalue
  void
    compiler::chklvalue ( compiler::PVAL *pv )
  {
    if ( !pv->fcn )
      throw parse_error ( this, "Expecting an lvalue" );
  }

  // do_expr1 - handle the ',' operator
  void
    compiler::do_expr1 ( compiler::PVAL *pv )
  {
    int tkn;
    do_expr2 ( pv );
    while ( ( tkn = scan.token () ) == ',' )
    {
      rvalue   ( pv );
      do_expr1 ( pv );
      rvalue   ( pv );
    }
    scan.stoken ( tkn );
  }

  // do_vardecl - var declaration
  void
    compiler::do_vardecl ( void )
  {
    int tkn;
    string id;
    compiler::PVAL rhs;
    for ( ; ; )
    {
      tkn = scan.token ();
      if ( tkn != T_IDENTIFIER )
        throw parse_error ( this, "Expecting an identifier" );
      id = scan.t_token;
      int temp_var_num = temporaries->add ( id );

      if ( temp_var_num < 0  )
      {
        char msg [ 100 ];
        sprintf ( msg, "Variable '%s' already defined", (const char *) id );
        throw parse_error ( this, msg );
      }

      tkn = scan.token ();
      if ( tkn == '=' )
      {
        code_temporary ( this, PUSH, 0 );
        do_expr2 ( &rhs );
        rvalue   ( &rhs );
        code_temporary ( this, STORE, temp_var_num );
        tkn = scan.token ();
      }
      else
      {
        putcbyte ( OP_UNDEFINED );
        code_temporary ( this, STORE, temp_var_num );
      }

      if ( tkn == ',' )
        continue;
      else if ( tkn == ';' )
      {
        scan.stoken ( tkn );
        break;
      }
      else
        throw parse_error ( this, "Expecting ',' | ';'" );
    }
  }

  // do_expr2 - handle the assignment operators
  void
    compiler::do_expr2 ( compiler::PVAL *pv )
  {
    int tkn;
    compiler::PVAL rhs;
    do_expr3 ( pv );
    while ( (tkn = scan.token () ) == '='     ||
             tkn == T_ADDEQ || tkn == T_SUBEQ ||
             tkn == T_MULEQ || tkn == T_DIVEQ ||
             tkn == T_REMEQ || tkn == T_ANDEQ ||
             tkn == T_OREQ  || tkn == T_XOREQ ||
             tkn == T_SHLEQ || tkn == T_SHLEQ  )
    {
      chklvalue ( pv );
      switch ( tkn )
      {
      case '=':
        ( *pv->fcn ) ( this, PUSH, 0 );
        do_expr1 ( &rhs );
        rvalue   ( &rhs );
        ( *pv->fcn ) ( this, STORE, pv->val );
        break;
      case T_ADDEQ:	    do_assignment ( pv, OP_ADD );	    break;
      case T_SUBEQ:	    do_assignment ( pv, OP_SUB );	    break;
      case T_MULEQ:	    do_assignment ( pv, OP_MUL );	    break;
      case T_DIVEQ:	    do_assignment ( pv, OP_DIV );	    break;
      case T_REMEQ:	    do_assignment ( pv, OP_REM );	    break;
      case T_ANDEQ:	    do_assignment ( pv, OP_BAND );	  break;
      case T_OREQ:	    do_assignment ( pv, OP_BOR );	    break;
      case T_XOREQ:	    do_assignment ( pv, OP_XOR );	    break;
      case T_SHLEQ:	    do_assignment ( pv, OP_SHL );	    break;
      case T_SHREQ:	    do_assignment ( pv, OP_SHR );	    break;
      }
      pv->fcn = NULL;
    }
    scan.stoken ( tkn );
  }

  // do_assignment - handle assignment operations
  void
    compiler::do_assignment ( compiler::PVAL *pv, int op )
  {
    compiler::PVAL rhs;
    ( *pv->fcn ) ( this, DUP, 0 );
    ( *pv->fcn ) ( this, LOAD, pv->val );
    putcbyte ( OP_PUSH );
    do_expr1 ( &rhs );
    rvalue   ( &rhs );
    putcbyte ( op );
    ( *pv->fcn ) ( this, STORE, pv->val );
  }

  // do_expr3 - handle the '?:' operator
  void
    compiler::do_expr3 ( compiler::PVAL *pv )
  {
    int tkn, nxt, end;
    do_expr4 ( pv );
    while ( (tkn = scan.token  () ) == '?' )
    {
      rvalue ( pv );
      putcbyte ( OP_BRF );
      nxt = putcword ( 0 );
      do_expr1 ( pv );
      rvalue ( pv );
      frequire ( ':' );
      putcbyte ( OP_BR );
      end = putcword ( 0 );
      fixup ( nxt, cptr );
      do_expr1 ( pv );
      rvalue ( pv );
      fixup ( end, cptr );
    }
    scan.stoken ( tkn );
  }

  // do_expr4 - handle the '||' operator
  void
    compiler::do_expr4 ( compiler::PVAL *pv )
  {
    int tkn, end = 0;
    do_expr5 ( pv );
    while ( ( tkn = scan.token () ) == T_OR )
    {
      rvalue ( pv );
      putcbyte ( OP_BRT );
      end = putcword ( end );
      do_expr5 ( pv );
      rvalue ( pv );
    }
    fixup ( end, cptr );
    scan.stoken ( tkn );
  }

  // do_expr5 - handle the '&&' operator
  void
    compiler::do_expr5 ( compiler::PVAL *pv )
  {
    int tkn, end = 0;
    do_expr6 ( pv );
    while ( ( tkn = scan.token () ) == T_AND )
    {
      rvalue ( pv );
      putcbyte ( OP_BRF );
      end = putcword ( end );
      do_expr6 ( pv );
      rvalue ( pv );
    }
    fixup ( end, cptr );
    scan.stoken ( tkn );
  }

  // do_expr6 - handle the '|' operator
  void
    compiler::do_expr6 ( compiler::PVAL *pv )
  {
    int tkn;
    do_expr7 ( pv );
    while ( ( tkn = scan.token () ) == '|' )
    {
      rvalue ( pv );
      putcbyte ( OP_PUSH );
      do_expr7 ( pv );
      rvalue   ( pv );
      putcbyte ( OP_BOR );
    }
    scan.stoken ( tkn );
  }

  // do_expr7 - handle the '^' operator
  void
    compiler::do_expr7 ( compiler::PVAL *pv )
  {
    int tkn;
    do_expr8 ( pv );
    while ( ( tkn = scan.token () ) == '^' )
    {
      rvalue ( pv );
      putcbyte ( OP_PUSH );
      do_expr8 ( pv );
      rvalue   ( pv );
      putcbyte ( OP_XOR );
    }
    scan.stoken ( tkn );
  }

  // do_expr8 - handle the '&' operator
  void
    compiler::do_expr8 ( compiler::PVAL *pv )
  {
    int tkn;
    do_expr9 ( pv );
    while ( ( tkn = scan.token () ) == '&' )
    {
      rvalue ( pv );
      putcbyte ( OP_PUSH );
      do_expr9 ( pv );
      rvalue   ( pv );
      putcbyte ( OP_BAND );
    }
    scan.stoken ( tkn );
  }

  // do_expr9 - handle the '==' and '!=' operators
  void
    compiler::do_expr9 ( compiler::PVAL *pv )
  {
    int tkn, op;
    do_expr10 ( pv );
    while ( ( tkn = scan.token () ) == T_EQ || tkn == T_NE )
    {
      switch ( tkn )
      {
      case T_EQ: op = OP_EQ; break;
      case T_NE: op = OP_NE; break;
      }
      rvalue ( pv );
      putcbyte ( OP_PUSH );
      do_expr10 ( pv );
      rvalue ( pv );
      putcbyte ( op );
    }
    scan.stoken ( tkn );
  }

  // do_expr10 - handle the '<', '<=', '>=' and '>' operators
  void
    compiler::do_expr10 ( compiler::PVAL *pv )
  {
    int tkn, op;
    do_expr11 ( pv );
    while ( ( tkn = scan.token () ) == '<' ||
              tkn == T_LE || tkn == T_GE || tkn == '>' )
    {
      switch ( tkn )
      {
      case '<':  op = OP_LT; break;
      case T_LE: op = OP_LE; break;
      case T_GE: op = OP_GE; break;
      case '>':  op = OP_GT; break;
      }
      rvalue ( pv );
      putcbyte ( OP_PUSH );
      do_expr11 ( pv );
      rvalue    ( pv );
      putcbyte  ( op );
    }
    scan.stoken ( tkn );
  }

  // do_expr11 - handle the '<<' and '>>' operators
  void
    compiler::do_expr11 ( compiler::PVAL *pv )
  {
    int tkn, op;
    do_expr12 ( pv );
    while ( ( tkn = scan.token () ) == T_SHL || tkn == T_SHR )
    {
      switch ( tkn  )
      {
      case T_SHL: op = OP_SHL; break;
      case T_SHR: op = OP_SHR; break;
      }
      rvalue ( pv );
      putcbyte ( OP_PUSH );
      do_expr12 ( pv );
      rvalue ( pv );
      putcbyte ( op );
    }
    scan.stoken ( tkn );
  }

  // do_expr12 - handle the '+' and '-' operators
  void
    compiler::do_expr12 ( compiler::PVAL *pv )
  {
    int tkn, op;
    do_expr13 ( pv );
    while ( ( tkn = scan.token () ) == '+' || tkn == '-' )
    {
      switch ( tkn )
      {
      case '+': op = OP_ADD; break;
      case '-': op = OP_SUB; break;
      }
      rvalue ( pv );
      putcbyte ( OP_PUSH );
      do_expr13 ( pv );
      rvalue    ( pv );
      putcbyte  ( op );
    }
    scan.stoken ( tkn );
  }

  // do_expr13 - handle the '*' and '/' operators
  void
    compiler::do_expr13 ( compiler::PVAL *pv )
  {
    int tkn, op;
    do_expr14 ( pv );
    while ( ( tkn = scan.token () ) == '*' || tkn == '/' ||
              tkn == '%' || tkn == T_MAKEREF || tkn == T_INSTANCEOF )
    {
      switch ( tkn )
      {
      case '*':           op = OP_MUL;        break;
      case '/':           op = OP_DIV;        break;
      case '%':           op = OP_REM;        break;
      case T_MAKEREF:     op = OP_MAKEREF;    break;
      case T_INSTANCEOF:  op = OP_INSTANCEOF; break;
      }
      rvalue ( pv );
      putcbyte ( OP_PUSH );
      do_expr14 ( pv );
      rvalue    ( pv );
      putcbyte  ( op );
    }
    scan.stoken ( tkn );
  }

  // do_expr14 - handle unary operators
  void
    compiler::do_expr14 ( compiler::PVAL *pv )
  {
    int tkn;
    switch ( tkn = scan.token () )
    {
    case '-':
      do_expr15 ( pv );
      rvalue    ( pv );
      putcbyte  ( OP_NEG );
      break;
    case '!':
      do_expr15 ( pv );
      rvalue    ( pv );
      putcbyte  ( OP_NOT );
      break;
    case '~':
      do_expr15 ( pv );
      rvalue    ( pv );
      putcbyte  ( OP_BNOT );
      break;
    case T_INC:
      do_preincrement ( pv, OP_INC );
      break;
    case T_DEC:
      do_preincrement ( pv, OP_DEC );
      break;
    case T_NEW:
      do_new ( pv );
      break;
    default:
      scan.stoken ( tkn );
      do_expr15   ( pv );
      return;
    }
  }

  void
    compiler::do_lit_array ( compiler::PVAL *pv )
  {
    compiler::PVAL pc;
    CLASS *klass = get_class ( "array", VM::std );
    findclassvariable ( klass, "[", &pc );
    rvalue ( &pc );
    // put <undefined> as this
    putcbyte ( OP_PUSH );
    int tkn, n = 1;
    // compile each argument expression
    if ( ( tkn = scan.token () ) != ']' )
    {
      scan.stoken ( tkn );
      do
      {
        putcbyte ( OP_PUSH );
        compiler::PVAL ai;
        do_expr2 ( &ai );
        rvalue ( &ai );
        ++n;
        if ( n >= 10000 ) throw parse_error ( this, "Too many literal items" );
      }
      while ( ( tkn = scan.token () ) == ',' );
    }
    require ( tkn, ']' );
    putcbyte ( OP_CALL );
    putcword ( n );

    // we've got an rvalue now
    pv->fcn = NULL;
  }

  void
    compiler::do_lit_map ( compiler::PVAL *pv )
  {
    compiler::PVAL pc;
    CLASS *klass = get_class ( "map", VM::std );
    findclassvariable ( klass, "{", &pc );
    rvalue ( &pc );
    // put <undefined> as this
    putcbyte ( OP_PUSH );
    int tkn, n = 1;
    // compile each argument expression
    if ( ( tkn = scan.token () ) != '}' )
    {
      scan.stoken ( tkn );
      do
      {
        compiler::PVAL l, r;
        putcbyte ( OP_PUSH );
        do_expr2 ( &l );
        rvalue ( &l );
        tkn = scan.token ();
        require ( tkn, ':' );
        putcbyte ( OP_PUSH );
        do_expr2 ( &r );
        rvalue ( &r );
        n += 2;
        if ( n >= 10000 )
          throw parse_error ( this, "Too many literal items" );
      }
      while ( ( tkn = scan.token () ) == ',' );
    }
    require  ( tkn, '}' );
    putcbyte ( OP_CALL );
    putcword ( n );

    // we've got an rvalue now
    pv->fcn = NULL;
  }

  // do_preincrement - handle prefix '++' and '--'
  void
    compiler::do_preincrement ( compiler::PVAL *pv, int op )
  {
    do_expr15 ( pv );
    chklvalue ( pv );
    ( *pv->fcn ) ( this, DUP, 0 );
    ( *pv->fcn ) ( this, LOAD, pv->val );
    putcbyte ( op );
    ( *pv->fcn ) ( this, STORE, pv->val );
    pv->fcn = NULL;
  }

  // do_postincrement - handle postfix '++' and '--'
  void
    compiler::do_postincrement ( compiler::PVAL *pv, int op )
  {
    chklvalue    ( pv );
    ( *pv->fcn ) ( this, DUP, 0 );
    ( *pv->fcn ) ( this, LOAD, pv->val );
    putcbyte     ( OP_TSTORE );
    putcbyte     ( op );

    ( *pv->fcn ) ( this, STORE, pv->val );
    putcbyte ( OP_TRESTORE );

    pv->fcn = NULL;
  }

  // do_new - handle the 'new' operator
  void
    compiler::do_new ( compiler::PVAL *pv )
  {
    string  package_name, class_name;
    int     tkn;
    CLASS * klass = 0;

    frequire ( T_IDENTIFIER );
    class_name = scan.t_token;

    if ( ( tkn = scan.token () ) == T_CC )
    {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -