Exemple #1
0
const CType* CAstBinaryOp::GetType(void) const
{
  CTypeManager *tm = CTypeManager::Get();
  EOperation oper = GetOperation();

  // If lhs or rhs is null, then null.
  if(_left->GetType() == NULL || _right->GetType() == NULL)
    return NULL;

  // case '+', '-', '*', '/'
  if(oper == opAdd || oper == opSub || oper == opMul || oper == opDiv) {
    if(_left->GetType()->IsInt() && _right->GetType()->IsInt())
      return tm->GetInt();

    else return NULL;
  }
  // case '&&' , '||'
  else if(oper == opAnd || oper == opOr) {
    if(_left->GetType()->IsBoolean() && _right->GetType()->IsBoolean())
      return tm->GetBool();

    else return NULL;
  }
  // case '=', '#'
  else if(oper == opEqual || oper == opNotEqual) {
    if(_left->GetType()->IsBoolean() && _right->GetType()->IsBoolean() ||
       _left->GetType()->IsChar() && _right->GetType()->IsChar() ||
       _left->GetType()->IsInt() && _right->GetType()->IsInt())
      return tm->GetBool();

    else return NULL;
  }
  // case '>', '>=', '<', '<='
  else {
    if(_left->GetType()->IsInt() && _right->GetType()->IsInt() ||
       _left->GetType()->IsChar() && _right->GetType()->IsChar())
      return tm->GetBool();

    else return NULL;
  }
}
Exemple #2
0
const CType* CAstUnaryOp::GetType(void) const
{
  CTypeManager *tm = CTypeManager::Get();
  EOperation oper = GetOperation();
  CAstExpression *e = GetOperand();

  if(e->GetType() == NULL)
    return NULL;

  if(oper == opNeg || oper == opPos) { //case '+' || '-'
    if(e->GetType()->IsInt())
      return tm->GetInt();
    else return NULL;
  }
  else { // case '!'
    if(e->GetType()->IsBoolean())
      return tm->GetBool();
  
    else return NULL;
  }
}
Exemple #3
0
const CType* CParser::type(bool isParam, bool isFunction) {
  //
  // type ::= basetype | type "[" [ number ] "]".
  // basetype ::= "boolean" | "char" | "integer".
  //
  
  CToken t;
  CToken tk;
  EToken tt = _scanner->Peek().GetType();
  CTypeManager *tm = CTypeManager::Get();
  const CType *type;
  vector<int> nelems;

  // basetype cases.
  switch(tt) {
    case tBoolean:
      Consume(tBoolean, &t);
      tk = t;
      type = dynamic_cast<const CType *>(tm->GetBool());
      break;
    case tChar:
      Consume(tChar, &t);
      tk = t;
      type = dynamic_cast<const CType *>(tm->GetChar());
      break;
    case tInteger:
      Consume(tInteger, &t);
      tk = t;
      type = dynamic_cast<const CType *>(tm->GetInt());
      break;

    default:
      SetError(_scanner->Peek(), "basetype expected.");
      break;
  }

  assert(type != NULL);

  // array case.
  while(_scanner->Peek().GetType() == tLSBrak) {
    Consume(tLSBrak);
    CToken nelem;

    if(_scanner->Peek().GetType() == tNumber) {
      Consume(tNumber, &nelem);
      nelems.push_back(atoi(nelem.GetValue().c_str()));
    }
    else {
      // open arrays are allowed only in parameter.
      if(isParam)
        nelems.push_back(-1);
      else
        SetError(_scanner->Peek(), "expected 'tNumber', got '" + _scanner->Peek().GetName() + "'");
    }
    Consume(tRSBrak);
  }

  for(int i = nelems.size()-1; i >= 0; i--) {
    type = dynamic_cast<const CType *>(tm->GetArray(nelems[i], type));
    assert(type != NULL);
    nelems.pop_back();

    // Arrays are addressed in parameter.
    if(i == 0 && isParam)
      type = dynamic_cast<const CType *>(tm->GetPointer(type));
  }

  if(isFunction && !type->IsScalar()) {
    SetError(tk, "invalid composite type for function.");
  }

  return type;
}
Exemple #4
0
CAstExpression* CParser::factor(CAstScope *s) {
  //
  // factor ::= qualident | number | boolean | char | string | "(" expression ")" | subroutineCall | "!" factor.
  // FIRST(factor) = { tIdent, tNumber, tTrue, tFalse, tCharacter, tString, tLBrak, tEMark }.
  //
  
  CToken t;
  EToken tt = _scanner->Peek().GetType();
  CTypeManager *tm = CTypeManager::Get();
  CAstExpression *n = NULL;
  CSymtab *symtab = s->GetSymbolTable();

  switch(tt) {
    case tTrue:
      Consume(tTrue, &t);
      n = new CAstConstant(t, tm->GetBool(), 1);
      break;

    case tFalse:
      Consume(tFalse, &t);
      n = new CAstConstant(t, tm->GetBool(), 0);
      break;

    case tNumber:
    {
      Consume(tNumber, &t);
      errno = 0;
      long long v = strtoll(t.GetValue().c_str(), NULL, 10);
      if (errno != 0) SetError(t, "invalid number.");

      // integer range validation check.
      if(v > 2147483648)
        SetError(t, "integer constant outside valid range.");

      n = new CAstConstant(t, tm->GetInt(), v);
      break;
    }

    case tIdent:
    {
      Consume(tIdent, &t);

      if(_scanner->Peek().GetType() == tLBrak) { // subroutineCall
        Consume(tLBrak);
        CAstFunctionCall *f;

        // If subroutineCall calls undefined procedure/function, then set error.
        if(symtab->FindSymbol(t.GetValue(),sLocal) == NULL && symtab->FindSymbol(t.GetValue(), sGlobal) != NULL) {
          // Check if symbol is procedure.
          if(dynamic_cast<const CSymProc *>(symtab->FindSymbol(t.GetValue(), sGlobal)) == NULL)
            SetError(t, "invalid procedure/function identifier.");

          f = new CAstFunctionCall(t, dynamic_cast<const CSymProc *>(symtab->FindSymbol(t.GetValue(), sGlobal)));
        }
        else if(symtab->FindSymbol(t.GetValue(), sLocal) != NULL) {
          // Check if symbol is procedure.
          if(dynamic_cast<const CSymProc *>(symtab->FindSymbol(t.GetValue(), sLocal)) == NULL)
            SetError(t, "invalid procedure/function identifier.");

          f = new CAstFunctionCall(t, dynamic_cast<const CSymProc *>(symtab->FindSymbol(t.GetValue(), sLocal)));
        }
        else
          SetError(t, "undefined identifier.");

        assert(f != NULL);

        if(isExpr(_scanner->Peek())) {
          CAstExpression *expr = expression(s);
          assert(expr != NULL);
 
          // If array, then addressed.
          if(expr->GetType()->IsArray())
            expr = new CAstSpecialOp(expr->GetToken(), opAddress, expr, NULL);

          f->AddArg(expr);

          while(_scanner->Peek().GetType() == tComma) {
            Consume(tComma);
            expr = expression(s);
            assert(expr != NULL);
 
            // If array, then addressed.
            if(expr->GetType()->IsArray())
              expr = new CAstSpecialOp(expr->GetToken(), opAddress, expr, NULL);

            f->AddArg(expr);
          }
        }
        Consume(tRBrak);

        n = f;
      }
      else { // qualident
        if(_scanner->Peek().GetType() == tLSBrak) { // It means array
          CAstArrayDesignator *f;

          if(symtab->FindSymbol(t.GetValue(), sLocal) == NULL && symtab->FindSymbol(t.GetValue(), sGlobal) != NULL) {
            // Check if symbol is procedure.
            if(dynamic_cast<const CSymProc *>(symtab->FindSymbol(t.GetValue(), sGlobal)) != NULL)
              SetError(t, "designator expected.");

            f = new CAstArrayDesignator(t, symtab->FindSymbol(t.GetValue(), sGlobal));
          }
          else if(symtab->FindSymbol(t.GetValue(), sLocal) != NULL) {
            // Check if symbol is procedure.
            if(dynamic_cast<const CSymProc *>(symtab->FindSymbol(t.GetValue(), sLocal)) != NULL)
              SetError(t, "designator expected");

            f = new CAstArrayDesignator(t, symtab->FindSymbol(t.GetValue(), sLocal));
          }
          else {
            SetError(t, "undefined identifier.");
          }
          
          while(_scanner->Peek().GetType() == tLSBrak) {
            Consume(tLSBrak);

            CAstExpression *expr = expression(s);
            assert(expr != NULL);
            f->AddIndex(expr);

            Consume(tRSBrak);
          }

          f->IndicesComplete();

          n = f;
        } // non-array case.
        else {
          if(symtab->FindSymbol(t.GetValue(), sLocal) == NULL && symtab->FindSymbol(t.GetValue(), sGlobal) != NULL) {
            // Check if symbol is procedure.
            if(dynamic_cast<const CSymProc *>(symtab->FindSymbol(t.GetValue(), sGlobal)) != NULL) {
              SetError(t, "designator expected.");
            }
            n = new CAstDesignator(t, symtab->FindSymbol(t.GetValue(), sGlobal));
          }
          else if(symtab->FindSymbol(t.GetValue(), sLocal) != NULL) {
            // Check if symbol is procedure.
            if(dynamic_cast<const CSymProc *>(symtab->FindSymbol(t.GetValue(), sLocal)) != NULL) {
              SetError(t, "designator expected.");
            }
            n = new CAstDesignator(t, symtab->FindSymbol(t.GetValue(), sLocal));
          }
          else
            SetError(t, "undefined identifier.");
        }
      }
      break;
    }

    case tString:
      Consume(tString, &t);
      n = new CAstStringConstant(t, t.GetValue(), s);
      break;

    case tCharacter:
    {
      Consume(tCharacter, &t);
      char res;

      // If character length is 0, it means character is '\0' because invalid character cases are handled in scanner.
      if(t.GetValue().length() == 0)
        res = '\0';
      else if(t.GetValue().length() == 1) {
        if(t.GetValue().at(0) != '\\')
          res = t.GetValue().at(0);
        else SetError(t, "wrong character");
      }
      // unescape.
      else if(t.GetValue().length() == 2) {
        if(t.GetValue().at(0) == '\\') {
          if(t.GetValue().at(1) == 'n') {
            res = '\n';
          }
          else if(t.GetValue().at(1) == 't') {
            res = '\t';
          }
          else if(t.GetValue().at(1) == '"') {
            res = '"';
          }
          else if(t.GetValue().at(1) == '\'') {
            res = '\'';
          }
          else if(t.GetValue().at(1) == '\\') {
            res = '\\';
          }
          else if(t.GetValue().at(1) == '0') {
            res = '\0';
          }
          else
            SetError(t, "wrong character");
        }
      }
      else SetError(t, "wrong character");

      n = new CAstConstant(t, tm->GetChar(), (long long)res);
      break;
    }

    case tLBrak:
      Consume(tLBrak);
      n = expression(s);
      Consume(tRBrak);
      break;

    case tEMark:
      Consume(tEMark, &t);
      n = new CAstUnaryOp(t, opNot, factor(s));
      break;

    default:
//      cout << "got " << _scanner->Peek() << endl;
      SetError(_scanner->Peek(), "factor expected.");
      break;
  }

  return n;
}