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

📄 compiler.cpp

📁 c-smile 一个语法类似与JS 又有点像C++的 编译器
💻 CPP
📖 第 1 页 / 共 4 页
字号:
      frequire ( T_IDENTIFIER );
      package_name = class_name;
      class_name = scan.t_token;

      PACKAGE *pkg = get_package ( package_name, true );
      klass = get_class ( class_name, pkg, true );
    }
    else
    {
      scan.stoken ( tkn );
      klass = get_class ( class_name, 0, true );
    }

    code_literal ( this, package->add_literal ( VALUE ( klass ) ) );
    pv->fcn = NULL;

    int n = 1;

    // generate code to push the selector
    putcbyte ( OP_PUSH );
    code_literal ( this,
                   package->add_literal (
                                VM::voc [ (const char *) class_name ] ) );

    if ( ( tkn = scan.token () ) == '(' )
    {
      // compile the argument arglist
      if ( ( tkn = scan.token () ) != ')' )
      {
        scan.stoken ( tkn );
        do
        {
          putcbyte ( OP_PUSH );
          do_expr2 ( pv );
          rvalue   ( pv );
          ++n;
        }
        while ( ( tkn = scan.token () ) == ',' );
      }
      require ( tkn, ')' );
    }
    else
      scan.stoken ( tkn );

    // send the message
    putcbyte ( OP_NEW );
    putcbyte ( n );

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

  }

  // do_expr15 - handle function calls
  void
    compiler::do_expr15 ( compiler::PVAL *pv )
  {
    string selector;
    int tkn;
    do_primary ( pv );
    while ( ( tkn = scan.token () ) == '('  ||
              tkn == '[' || tkn == T_MEMREF ||
              tkn == T_INC || tkn == T_DEC )
      switch ( tkn  )
      {
      case '(':
        do_call ( pv );
        break;
      case '[':
        do_index ( pv );
        break;
      case T_MEMREF:
        frequire ( T_IDENTIFIER );
        selector = scan.t_token;
        do_memref ( selector, pv );
        break;
      case T_INC:
        do_postincrement ( pv, OP_INC );
        break;
      case T_DEC:
        do_postincrement ( pv, OP_DEC );
        break;
      }
    scan.stoken ( tkn );
  }

  // do_primary - parse a primary expression and unary operators
  void
    compiler::do_primary ( compiler::PVAL *pv )
  {
    CLASS *klass;
    int tkn;
    switch ( scan.token () )
    {
    case '(':
      do_expr1 ( pv  );
      frequire ( ')' );
      break;
    case T_NUMBER:
      do_lit_number ( scan.t_value );
      pv->fcn = NULL;
      break;
    case T_STRING:
      do_lit_string ( scan.t_token );
      pv->fcn = NULL;
      break;
    case T_NULL:
      putcbyte ( OP_NULL );
      pv->fcn = NULL;
      break;
    case T_UNDEFINED:
      putcbyte ( OP_UNDEFINED );
      pv->fcn = NULL;
      break;
    case T_ARGUMENTS:
      putcbyte ( OP_ARGUMENTS );
      pv->fcn = NULL;
      break;
    case T_ARGUMENT:
      do_expr2 ( pv );
      rvalue ( pv );
      putcbyte ( OP_ARGUMENT );
      pv->fcn = NULL;
      break;
    case '[':
      do_lit_array ( pv );
      break;
    case '{':
      do_lit_map ( pv );
      break;
    case T_IDENTIFIER:
      {
        string member_id = scan.t_token;
        if ( ( tkn = scan.token () ) == T_CC )
        {
          frequire ( T_IDENTIFIER );

          string package_id;
          string class_id = member_id;
          member_id = scan.t_token;

          if ( ( tkn = scan.token  () ) == T_CC )
          {
            frequire ( T_IDENTIFIER );
            package_id = class_id;
            class_id = member_id;
            member_id = scan.t_token;
          }
          else
          {
            scan.stoken ( tkn );
          }

          klass = get_class_or_package ( class_id, package_id );
          assert ( klass );

          if ( ! findclassvariable ( klass, (const char *) member_id, pv ) )
            throw parse_error ( this, "'%s' is not a member of class '%s'",
                                (const char *) member_id,
                                (const char *) klass->full_name () );
        }
        else
        {
          scan.stoken ( tkn );
          findvariable ( (const char *) member_id, pv );
        }
      }
      break;
    default:
      throw parse_error ( this, "Expecting a primary expression" );
      break;
    }
  }


  // do_call - compile a function call
  void
    compiler::do_call ( compiler::PVAL *pv )
  {
    int tkn, n = 1;

    // get the value of the function
    rvalue ( pv );

    // put <undefined> as this
    putcbyte ( OP_PUSH );

    // compile each argument expression
    if ( ( tkn = scan.token () ) != ')' )
    {
      scan.stoken ( tkn );
      do
      {
        putcbyte ( OP_PUSH );
        do_expr2 ( pv );
        rvalue   ( pv );
        if ( ++n >= 10000 )
          throw parse_error ( this, "Too many parameters" );
      }
      while ( ( tkn = scan.token () ) == ',' );
    }
    require  ( tkn, ')' );
    putcbyte ( OP_CALL );
    putcword ( n );

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

  // do_send - compile a message sending expression
  void
    compiler::do_memref ( const char *selector, compiler::PVAL *pv )
  {
    // get the receiver value
    rvalue ( pv );
    // generate code to push the selector
    putcbyte ( OP_PUSH );
    code_literal ( this, package->add_literal ( VM::voc [ selector ] ) );
    pv->fcn = code_prop_member;
  }


  // do_index - compile an indexing operation
  void
    compiler::do_index ( compiler::PVAL *pv )
  {
    rvalue   ( pv );
    putcbyte ( OP_PUSH );
    do_expr  ();
    frequire ( ']' );
    pv->fcn = code_index;
  }


  // get_id_list - get a comma separated arglist of identifiers
  int
    compiler::get_id_list ( sym_table& st, const char *term )
  {
    int tkn, cnt = 0; symbol_t t;
    tkn = scan.token ();
    if ( ! strchr ( term, tkn ) )
    {
      scan.stoken ( tkn );
      do
      {
        frequire ( T_IDENTIFIER );
        if ( st.find ( scan.t_token, t ) )
        {
          char buf [ 100 ];
          sprintf ( buf, "'%s' already defined.",
                    (const char *) scan.t_token );
          throw parse_error ( this, buf );
        }
        else
          (void) st [ scan.t_token ];

      }
      while ( ( tkn = scan.token () ) == ',' );
    }
    scan.stoken ( tkn );
    return st.size ();
  }


  // findarg - find an argument offset
  int
    compiler::findarg ( const char *name )
  {
    symbol_t t;
    return arguments.find ( name, t ) ? (int) t : -1;
  }

  // findtmp - find a temporary variable offset
  int
    compiler::findtmp ( const char *name )
  {
    if ( temporaries == 0 )
      return -1;
    return (int) temporaries->find ( name );
  }

  // finddatamember - find a klass data member
  ENTRY
    compiler::finddatamember ( const char *name )
  {
    CLASS *klass = methodclass;
    if ( klass )
    {
      do
      {
        ENTRY e = klass->find ( name );
        if ( e.is_valid () )
          return e;
        klass = klass->base;
      }
      while ( klass );
    }
    return ENTRY::undefined ();
  }

  // frequire - fetch a token and check it
  void
    compiler::frequire ( int rtkn )
  {
    require ( scan.token (), rtkn );
  }

  // require - check for a required token
  void
    compiler::require ( int tkn, int rtkn )
  {
    char msg [ 100 ], tknbuf [ 100 ];
    if ( tkn != rtkn  )
    {
      strncpy ( tknbuf, scan.tkn_name ( rtkn ), 100 );
      snprintf ( msg, 100, "Expecting '%s', found '%s'", tknbuf, scan.tkn_name ( tkn ) );
      throw parse_error ( this, msg );
    }
  }

  // do_lit_integer - compile a literal number
  void
    compiler::do_lit_number ( VALUE v )
  {
    code_literal ( this, package->add_literal ( v ) );
  }

  // do_lit_string - compile a literal string
  void
    compiler::do_lit_string ( const char *str )
  {
    code_literal ( this, package->add_literal ( str ) );
  }

  // make_lit_symbol - make a literal string

  int
    compiler::make_lit_symbol ( const char *str )
  {
    return package->add_literal ( VM::voc [ str ] );
  }

  // make_lit_string - make a literal string
  int
    compiler::make_lit_string ( const char *str )
  {
    return package->add_literal ( str );
  }

  // make_lit_variable - make a literal reference to a variable
  int
    compiler::make_lit_variable ( ENTRY e )
  {
    return package->add_literal ( VALUE ( e ) );
  }

  // findvariable - find a variable
  void
    compiler::findvariable ( const char *id, compiler::PVAL *pv )
  {
    int n;
    if ( ( n = findarg ( id ) ) >= 0 )
    {
      pv->fcn = code_argument;
      pv->val = n;
    }
    else if ( ( n = findtmp ( id ) ) >= 0 )
    {
      pv->fcn = code_temporary;
      pv->val = n;
    }
    else if ( methodclass && findclassvariable ( methodclass, id, pv ) )
    {
      ;
    }
    else if ( findclassvariable ( package, id, pv ) )
    {
      ;
    }
    else if ( findclassvariable ( VM::std, id, pv ) )
    {
      ;
    }
    else
      throw parse_error ( this, "Variable or method '%s' not found", id );
  }

  // findclassvariable - find a klass member variable
  int
    compiler::findclassvariable ( CLASS *klass, const char *name,
                                  compiler::PVAL *pv )
  {
    ENTRY e = rfindmember ( klass, name );
    if ( !e.is_valid () )
      return false;
    switch ( e.type () )
    {
    case ST_DATA:
      pv->fcn = code_member;
      pv->val = e.value()->v.v_integer;
      break;
    case ST_SDATA:
      pv->fcn = code_variable;
      pv->val = make_lit_variable ( e );
      break;
    case ST_CONST:
      pv->fcn = code_const;
      pv->val = make_lit_variable ( e );
      break;
    case ST_FUNCTION:
      if ( findarg ( "this" ) >= 0 )
      {
        findvariable ( "this", pv );
        do_memref ( name, pv );
        break;
      }

    case ST_SFUNCTION:
      code_variable ( this, LOAD, make_lit_variable ( e ) );
      pv->fcn = NULL;
      break;
    }
    return true;
  }

  // code_argument - compile an argument reference
  void
    compiler::code_argument ( compiler *c, int fcn, int n )
  {
    switch ( fcn )
    {
    case LOAD:  c->putcbyte ( OP_AREF ); c->putcbyte ( n ); break;
    case STORE: c->putcbyte ( OP_ASET ); c->putcbyte ( n ); break;
    }
  }

  // code_temporary - compile a temporary variable reference
  void
    compiler::code_temporary ( compiler *c, int fcn, int n )
  {
    switch ( fcn )
    {
    case LOAD:  c->putcbyte ( OP_TREF ); c->putcbyte ( n ); break;
    case STORE: c->putcbyte ( OP_TSET ); c->putcbyte ( n ); break;
    }
  }

  // code_member - compile a data member reference
  void
    compiler::code_member ( compiler *c, int fcn, int n )
  {
    switch ( fcn  )
    {
    case LOAD:  c->putcbyte ( OP_MREF ); c->putcbyte ( n ); break;
    case STORE: c->putcbyte ( OP_MSET ); c->putcbyte ( n ); break;
    }
  }

  // code_variable - compile a variable reference
  void
    compiler::code_variable ( compiler *c, int fcn, int n )
  {
    switch ( fcn )
    {
    case LOAD:  c->putcbyte ( OP_REF ); c->putcword ( n ); break;
    case STORE: c->putcbyte ( OP_SET ); c->putcword ( n ); break;
    }
  }

  // code_variable - compile a variable reference
  void
    compiler::code_const ( compiler *c, int fcn, int n )
  {
    switch ( fcn  )
    {
    case LOAD:	c->putcbyte ( OP_REF ); c->putcword ( n ); break;
    case STORE:	throw parse_error ( c, "attempt to change constant" );
    }
  }

  // code_index - compile an indexed reference
  void
    compiler::code_index ( compiler *c, int fcn, int n )
  {
    switch ( fcn )
    {
    case LOAD:  c->putcbyte ( OP_VREF ); break;
    case STORE: c->putcbyte ( OP_VSET ); break;
    case PUSH:  c->putcbyte ( OP_PUSH ); break;
    case DUP:   c->putcbyte ( OP_DUP2 ); break;
    }
  }

  // code_prop_member - compile an object property reference
  void
    compiler::code_prop_member ( compiler *c, int fcn, int n )
  {
    switch ( fcn )
    {
    case LOAD:  c->putcbyte ( OP_PMREF ); break;
    case STORE: c->putcbyte ( OP_PMSET ); break;
    case PUSH:  c->putcbyte ( OP_PUSH );  break;
    case DUP:   c->putcbyte ( OP_DUP2 );  break;
    }
  }

  // code_literal - compile a literal reference
  void
    compiler::code_literal ( compiler *c, int n )
  {
    c->putcbyte ( OP_LIT );
    c->putcword ( n );
  }

  // putcbyte - put a code byte into data space
  int
    compiler::putcbyte ( int b )
  {
    if ( file_line != scan.lnum )
    {
      file_line = scan.lnum;
      _putcbyte ( OP_LINE );
      putcword ( file_line );
    }
    return _putcbyte ( b );
  }


  // putcbyte - put a code byte into data space
  int
    compiler::_putcbyte ( int b )
  {
    if ( cptr >= CMAX )
      throw parse_error ( this, "Insufficient code space" );
    cbuff [ cptr ] = b;
    return ( cptr++ );
  }


  // putcword - put a code word into data space
  int
    compiler::putcword ( int w )
  {
    _putcbyte ( w );
    _putcbyte ( w >> 8 );
    return ( cptr - 2 );
  }

  // fixup - fixup a reference chain
  void
    compiler::fixup ( int chn, int val )
  {
    int hval, nxt;
    for ( hval = val >> 8; chn != 0; chn = nxt )
    {
      nxt = ( cbuff [ chn ] & 0xFF ) | ( cbuff [ chn + 1 ] << 8 );
      cbuff [ chn     ] = val;
      cbuff [ chn + 1 ] = hval;
    }
  }
#endif //COMPILER

};

⌨️ 快捷键说明

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