void SemanticEval::evaluateNumericExpr(ExpressionValue& ev, int line) {
  if(!ev.isPrimitive() || !ev.isNumeric()) {
    stringstream err;
    err << "Esperando uma expressão numérica. Encontrado expressão \"" << ev.toString() << "\"";
    ErrorHandler::self()->add(err.str(), line);
  }
}
Beispiel #2
0
void CDirectiveData::encodeCustom(EncodingTable& table)
{
	customData.clear();
	for (size_t i = 0; i < entries.size(); i++)
	{
		ExpressionValue value = entries[i].evaluate();
		if (!value.isValid())
		{
			Logger::queueError(Logger::Error,L"Invalid expression");
			continue;
		}
		
		if (value.isInt())
		{
			customData.appendByte((u8)value.intValue);
		} else if (value.isString())
		{
			ByteArray encoded = table.encodeString(value.strValue,false);
			if (encoded.size() == 0 && value.strValue.size() > 0)
			{
				Logger::queueError(Logger::Error,L"Failed to encode \"%s\"",value.strValue);
			}
			customData.append(encoded);
		} else {
			Logger::queueError(Logger::Error,L"Invalid expression type");
		}
	}

	if (writeTermination)
	{
		ByteArray encoded = table.encodeTermination();
		customData.append(encoded);
	}
}
ExpressionValue SemanticEval::evaluateExpr(ExpressionValue& ev, RefPortugolAST unary_op) {
  ExpressionValue nulo;

  //não permitir TIPO_ALL em expressões binarias
  if(ev.primitiveType() == TIPO_ALL) {
    stringstream msg;
    msg << "Função interna não pode participar de expressão";
    ErrorHandler::self()->add(msg.str(), unary_op->getLine());
    return nulo;
  }

  switch(unary_op->getType()) {

    //operadores unarios para expressões numéricas (retorna o tipo da expressão 'expr')
    case SemanticWalkerTokenTypes::TI_UN_POS://+
    case SemanticWalkerTokenTypes::TI_UN_NEG://-    
      if(!ev.isNumeric()) {
        stringstream msg;
        msg <<  "Operador unário \"" << unary_op->getText()
            << "\" deve ser usado em termos numéricos";
        ErrorHandler::self()->add(msg.str(), unary_op->getLine());
        return nulo;
      } else {      
        return ev;
      }  
      break;
    case SemanticWalkerTokenTypes::TI_UN_BNOT://~
      if(!ev.isNumeric(true)) {
        stringstream msg;
        msg <<  "Operador unário \"" << unary_op->getText()
            << "\" deve ser usado em termos numéricos inteiros e compatíveis";
        ErrorHandler::self()->add(msg.str(), unary_op->getLine());
        return nulo;
      } else {      
        return ev;
      }  
      break;
      
    //operador "not", para todos os tipos. Retorna TIPO_LOGICO
    case SemanticWalkerTokenTypes::TI_UN_NOT:
      ev.setPrimitiveType(TIPO_LOGICO);
      return ev;
      break;
  }

  stringstream msg;
  msg << "Erro interno: operador não suportado: " << unary_op->getText() << "";
  ErrorHandler::self()->add(msg.str(), unary_op->getLine());
  return nulo;
}
void SemanticEval::evaluateAttribution(ExpressionValue&  lv, ExpressionValue& rv, int line) {
//lvalue e rvalue devem ter tipos compativeis
//  -numericos (inteiro, logico, real, caractere) sao compativeis entre si.

  stringstream msg;

  if(!lv.isPrimitive()) {
    msg << "Apenas variáveis de tipos primitivos podem receber valores";
    ErrorHandler::self()->add(msg.str(), line);
    return;
  }

  if(rv.primitiveType() == TIPO_NULO) {
    msg << "Expressão não retorna resultado para variável";  
    ErrorHandler::self()->add(msg.str(), line);
  } else  if(!lv.isCompatibleWidth(rv)) {
    msg << "Variável não pode receber valores do tipo '"
        << rv.toString() << "'";      
    ErrorHandler::self()->add(msg.str(), line);
  }
}
void SemanticEval::evaluateReturnCmd(ExpressionValue& ev, int line) {
  if(currentScope == SymbolTable::GlobalScope) {
    //tentando retornar no bloco principal
    ErrorHandler::self()->add("Bloco principal não deve ter retorno", line);
  } else {
    //currentScope eh o nome da funcao atual
    try {
      SymbolType sctype = stable.getSymbol(SymbolTable::GlobalScope, currentScope).type;
      
      if(!ev.isCompatibleWidth(sctype)) {
          stringstream msg;
          msg << "Expressão de retorno deve ser compatível com o tipo \"" 
            << sctype.toString() <<  "\"";
          ErrorHandler::self()->add(msg.str(), line);
      } //else ok!
    } catch(SymbolTableException& e) {
      cerr << "Erro interno: SemanticEval::evaluateReturnCmd exception\n";
    }
  } 
}
Beispiel #6
0
CAssemblerCommand* parseDirectiveConditional(Parser& parser, int flags)
{
    ConditionType type;
    std::wstring name;
    Expression exp;

    const Token& start = parser.peekToken();
    ConditionalResult condResult = ConditionalResult::Unknown;
    switch (flags)
    {
    case DIRECTIVE_COND_IF:
        type = ConditionType::IF;
        exp = parser.parseExpression();
        if (exp.isLoaded() == false)
        {
            parser.printError(start,L"Invalid condition");
            return new DummyCommand();
        }

        if (exp.isConstExpression())
        {
            ExpressionValue result = exp.evaluate();
            if (result.isInt())
                condResult = result.intValue != 0 ? ConditionalResult::True : ConditionalResult::False;
        }
        break;
    case DIRECTIVE_COND_IFDEF:
        type = ConditionType::IFDEF;
        if (parser.parseIdentifier(name) == false)
            return nullptr;
        break;
    case DIRECTIVE_COND_IFNDEF:
        type = ConditionType::IFNDEF;
        if (parser.parseIdentifier(name) == false)
            return nullptr;
        break;
    }

    parser.pushConditionalResult(condResult);
    CAssemblerCommand* ifBlock = parser.parseCommandSequence(L'.', {L".else", L".elseif", L".elseifdef", L".elseifndef", L".endif"});
    parser.popConditionalResult();

    // update the file info so that else commands get the right line number
    parser.updateFileInfo();

    CAssemblerCommand* elseBlock = nullptr;
    const Token &next = parser.nextToken();
    const std::wstring stringValue = next.getStringValue();

    if (stringValue == L".else")
    {
        ConditionalResult elseResult = condResult;
        switch (condResult)
        {
        case ConditionalResult::True:
            elseResult = ConditionalResult::False;
            break;
        case ConditionalResult::False:
            elseResult = ConditionalResult::True;
            break;
        }

        parser.pushConditionalResult(elseResult);
        elseBlock = parser.parseCommandSequence(L'.', {L".endif"});
        parser.popConditionalResult();

        parser.eatToken();	// eat .endif
    } else if (stringValue == L".elseif")
    {
        elseBlock = parseDirectiveConditional(parser,DIRECTIVE_COND_IF);
    } else if (stringValue == L".elseifdef")
    {
        elseBlock = parseDirectiveConditional(parser,DIRECTIVE_COND_IFDEF);
    } else if (stringValue == L".elseifndef")
    {
        elseBlock = parseDirectiveConditional(parser,DIRECTIVE_COND_IFNDEF);
    } else if (stringValue != L".endif")
    {
        return nullptr;
    }

    // for true or false blocks, there's no need to create a conditional command
    if (condResult == ConditionalResult::True)
    {
        delete elseBlock;
        return ifBlock;
    }

    if (condResult == ConditionalResult::False)
    {
        delete ifBlock;
        if (elseBlock != nullptr)
            return elseBlock;
        else
            return new DummyCommand();
    }

    CDirectiveConditional* cond;
    if (exp.isLoaded())
        cond = new CDirectiveConditional(type,exp);
    else if (name.size() != 0)
        cond = new CDirectiveConditional(type,name);
    else
        cond = new CDirectiveConditional(type);

    cond->setContent(ifBlock,elseBlock);
    return cond;
}
ExpressionValue SemanticEval::evaluateNumTypes(ExpressionValue& left, ExpressionValue& right) {
  ExpressionValue ret;

  if(!left.isNumeric() || !right.isNumeric()) return ret;

  //a ordem eh importante. Primeiro o tipo mais forte.

  if((left.primitiveType() == TIPO_REAL) || (right.primitiveType() == TIPO_REAL)) {
    ret.setPrimitiveType(TIPO_REAL); //promoted to real

  } else if((left.primitiveType() == TIPO_INTEIRO) || (right.primitiveType() == TIPO_INTEIRO)) {
    ret.setPrimitiveType(TIPO_INTEIRO); //promoted to int

  } else  if((left.primitiveType() == TIPO_CARACTERE) || (right.primitiveType() == TIPO_CARACTERE)) {
    ret.setPrimitiveType(TIPO_CARACTERE); //promoted to char

  } else if((left.primitiveType() == TIPO_LOGICO) || (right.primitiveType() == TIPO_LOGICO)) {
    ret.setPrimitiveType(TIPO_LOGICO); //promoted to bool
  }    

  return ret; //no number here...
}
ExpressionValue SemanticEval::evaluateFCall(RefPortugolAST f, list<ExpressionValue>& args) {
  ExpressionValue v;
  Symbol s;
  try {
    s = stable.getSymbol(SymbolTable::GlobalScope, f->getText());
    v.set(s.type);
  } catch(SymbolTableException& e) {
    stringstream msg;
    msg << "Função \"" << f->getText() << "\" não foi declarada";
    ErrorHandler::self()->add(msg.str(), f->getLine());      
    return v;
  }

  ParameterSig params = s.param;

  if(params.isVariable()) {
    //nao permitir 0 argumentos
    if(args.size() == 0) {
      stringstream msg;
      msg << "Pelo menos um argumento deve ser passado para a função \"" << f->getText() << "\"";
      ErrorHandler::self()->add(msg.str(), f->getLine());      
      return v;
    }
    //nao permitir matrizes como argumentos de funcoes com parametros variaveis
    int count = 1;
    for(list<ExpressionValue>::iterator it = args.begin();
        it != args.end(); ++it) {
      if(!(*it).isPrimitive()) {
        stringstream msg;
        msg << "Argumento " << count;
        msg << " da função \"" << f->getText() << "\" não pode ser matriz/conjunto";
        ErrorHandler::self()->add(msg.str(), f->getLine());      
        return v;
      }
      count++;
    }
    return v;
  }
  
  if(params.symbolList().size() != args.size()) {
    stringstream msg;
    msg << "Número de argumentos diferem do número de parâmetros da função \""
      << f->getText() << "\"";
    ErrorHandler::self()->add(msg.str(), f->getLine());      
    return v;
  }

  list< pair<string,SymbolType> >::iterator pit = params.symbolList().begin();
  list< pair<string,SymbolType> >::iterator pend = params.symbolList().end();

  list<ExpressionValue>::iterator ait = args.begin();
  list<ExpressionValue>::iterator aend = args.end();

  int count = 1;
  while((pit != pend) && (ait != aend)) {
    if(!(*ait).isCompatibleWidth((*pit).second)) {
      stringstream msg;
      msg << "Argumento " << count << " da função \"" << f->getText() << "\" deve ser do tipo \""
        << (*pit).second.toString() << "\"";
      ErrorHandler::self()->add(msg.str(), f->getLine());              
      return v;
    }    
    ++count;
    ++pit;
    ++ait;
  }
  return v;
}
ExpressionValue SemanticEval::evaluateExpr(ExpressionValue& left, ExpressionValue& right, RefPortugolAST op) {
  //analisa expressoes binarias

  ExpressionValue ret, nulo;

  //operadores suportam apenas primitivos
//   if(!left.isPrimitive() || !right.isPrimitive()) {
//     return ret;
//   }

  //não permitir TIPO_ALL em expressões binarias
  if((left.primitiveType() == TIPO_ALL) || (right.primitiveType() == TIPO_ALL)) {
    stringstream msg;
    msg << "Função interna não pode participar de expressão";
    ErrorHandler::self()->add(msg.str(), op->getLine());
    return nulo;
  }

  switch(op->getType()) {
    //qualquer tipo, contanto que left e right sejam compativeis
    case SemanticWalkerTokenTypes::T_IGUAL:
    case SemanticWalkerTokenTypes::T_DIFERENTE:

    //nota sobre literais:
    // operacoes aplicadas sobre o length() do literal
    case SemanticWalkerTokenTypes::T_MAIOR:
    case SemanticWalkerTokenTypes::T_MENOR:
    case SemanticWalkerTokenTypes::T_MAIOR_EQ:
    case SemanticWalkerTokenTypes::T_MENOR_EQ:

    case SemanticWalkerTokenTypes::T_KW_OU:
    case SemanticWalkerTokenTypes::T_KW_E:
      if(left.isCompatibleWidth(right)) {
        ret.setPrimitiveType(TIPO_LOGICO);
        return ret;
      } else {
        stringstream msg;
        msg << "Operador \"" << op->getText() << "\" não pode ser usado em expressões no formato " 
            << "'" << left.toString() 
            << " " << op->getText() 
            << " " << right.toString() << "'";
            ErrorHandler::self()->add(msg.str(), op->getLine());
            return nulo;
      }   
      break;

    //qualquer numerico não-real (inteiro, caractere, lógico)
    case SemanticWalkerTokenTypes::T_BIT_OU:
    case SemanticWalkerTokenTypes::T_BIT_XOU:
    case SemanticWalkerTokenTypes::T_BIT_E:
      ret = evaluateNumTypes(left, right);
      if((ret.primitiveType() == TIPO_REAL) || (ret.primitiveType() == TIPO_NULO)) {
        stringstream msg;
        msg << "Operador \"" << op->getText() << "\" só pode ser usado com termos númericos não-reais";
            ErrorHandler::self()->add(msg.str(), op->getLine());
         return nulo;
      } else {
        return ret;
      }
      break;

    //qualquer numérico
    case SemanticWalkerTokenTypes::T_MAIS:
    case SemanticWalkerTokenTypes::T_MENOS:
    case SemanticWalkerTokenTypes::T_DIV:
    case SemanticWalkerTokenTypes::T_MULTIP:    
      ret = evaluateNumTypes(left, right);
      if(!ret.isNumeric()) {
        stringstream msg;
        msg << "Operador \"" << op->getText() << "\" só pode ser usado com termos numéricos";
            ErrorHandler::self()->add(msg.str(), op->getLine());          
            return nulo;
      } else {
        return ret;
      }      
      break;
    case SemanticWalkerTokenTypes::T_MOD:
      ret = evaluateNumTypes(left, right);
      if(!ret.isNumeric(true)) {
        stringstream msg;
        msg << "Operador \"" << op->getText() << "\" não pode ser usado com termos "
            << "numéricos inteiros e compatíveis";
            ErrorHandler::self()->add(msg.str(), op->getLine());          
            return nulo;
      } else {
        return ret;
      }      
      break;
  }

  stringstream msg;
  msg << "Erro interno: operador não suportado: " << op->getText();
  ErrorHandler::self()->add(msg.str(), op->getLine());
  return nulo;
}
ExpressionValue SemanticEval::evaluateLValue(RefPortugolAST id, list<ExpressionValue>& dim) {
/*
  1: lvalue (id) deve ter sido declarado no escopo global ou local
  2: o tipo do lvalue (id) deve ser o mesmo da declaracao (primitivo/dimensoes)
  3: as expressoes das dimensoes devem ser numericas inteiras. [1.2] ou ["aa"] ->erro
*/

  bool islocal;
  Symbol lvalue;
  ExpressionValue ret;

  try {
    lvalue = stable.getSymbol(currentScope, id->getText(), true);
    if(lvalue.scope == SymbolTable::GlobalScope) {
      islocal = false;
    } else {
      islocal = true;
    }
  } catch(SymbolTableException& e) {
    stringstream msg;    
    msg << "Variável \"" << id->getText() << "\" não foi declarada";
    ErrorHandler::self()->add(msg.str(), id->getLine());
    return ret;
  }

  ret.setPrimitiveType(lvalue.type.primitiveType());

  if(lvalue.isFunction) {
    stringstream msg;
    msg << "Função \"" << id->getText() << "\" não pode ser usada como variável";
    ErrorHandler::self()->add(msg.str(), id->getLine());
    return ret;    
  }

  if(lvalue.type.isPrimitive()) {
    ret.set(lvalue.type);
    if(dim.size() > 0) {
      stringstream msg;
      msg << "Variável \"" << id->getText() << "\" não é uma matriz/conjunto";
      ErrorHandler::self()->add(msg.str(), id->getLine());
      return ret;
    } else {
      return ret;
    }
  } else {//matriz/conjunto    

//     ret.setPrimitive(true);
//     ret.setPrimitiveType(lvalue.type.primitiveType());

    //checar expressoes dos subscritos
    list<ExpressionValue>::iterator it;
    for(it = dim.begin(); it != dim.end();++it) {
      if(!(*it).isNumeric(true)) {
        ErrorHandler::self()->add("Subscritos de conjuntos/matrizes devem ser valores numéricos inteiros ou equivalente", id->getLine());
      }
    }

    /* Nota: checar pelas dimensoes impede que 
       se passe matriz como parametros. Checar subscritos apenas 
       em atribuicoes.
    */

    //checar numero de dimensoes usado
    // - So eh permitido matrizes como lvalue sem subscritos, ou com todos os seus subscritos

    if(dim.size() > 0) {
      //matriz com seus subscritos, retorna apenas o tipo primitivo
      ret.setPrimitive(true);

      if(lvalue.type.dimensions().size() != dim.size()) {
        stringstream msg;
        msg << "Matriz/conjunto \"" << id->getText() << "\" possui " << lvalue.type.dimensions().size();
  
        if(dim.size() == 1) {
          msg << " dimensão";
        } else {
          msg << " dimensões";
        }
        msg << " Use " << lvalue.type.dimensions().size() << " subscrito(s)";
        ErrorHandler::self()->add(msg.str(), id->getLine());
      } 
    } else {
      //variavel matriz sem subscritos, retorna tipo matriz
      ret.setPrimitive(true);
      ret.setDimensions(lvalue.type.dimensions());
    }
    return ret;
  }
}
Beispiel #11
0
// =============================================================================
//
// Try to parse an expression symbol (i.e. an OPER_erator or OPER_erand or a colon)
// from the lexer.
//
ExpressionSymbol* Expression::parseSymbol()
{
	int pos = m_lexer->position();
	ExpressionValue* op = null;

	if (m_lexer->next (TK_Colon))
		return new ExpressionColon;

	// Check for OPER_erator
	for (const OperatorInfo& op : g_Operators)
		if (m_lexer->next (op.token))
			return new ExpressionOperator ((ExpressionOperatorType) (&op - &g_Operators[0]));

	// Check sub-expression
	if (m_lexer->next (TK_ParenStart))
	{
		Expression expr (m_parser, m_lexer, m_type);
		m_lexer->mustGetNext (TK_ParenEnd);
		return expr.getResult()->clone();
	}

	op = new ExpressionValue (m_type);

	// Check function
	if (CommandInfo* comm = findCommandByName (m_lexer->peekNextString()))
	{
		m_lexer->skip();

		if (m_type != TYPE_Unknown && comm->returnvalue != m_type)
			error ("%1 returns an incompatible data type", comm->name);

		op->setBuffer (m_parser->parseCommand (comm));
		return op;
	}

	// Check for variables
	if (m_lexer->next (TK_DollarSign))
	{
		m_lexer->mustGetNext (TK_Symbol);
		Variable* var = m_parser->findVariable (getTokenString());

		if (var == null)
			error ("unknown variable %1", getTokenString());

		if (var->type != m_type)
			error ("expression requires %1, variable $%2 is of type %3",
				dataTypeName (m_type), var->name, dataTypeName (var->type));

		if (var->isarray)
		{
			m_lexer->mustGetNext (TK_BracketStart);
			Expression expr (m_parser, m_lexer, TYPE_Int);
			expr.getResult()->convertToBuffer();
			DataBuffer* buf = expr.getResult()->buffer()->clone();
			buf->writeDWord (DH_PushGlobalArray);
			buf->writeDWord (var->index);
			op->setBuffer (buf);
			m_lexer->mustGetNext (TK_BracketEnd);
		}
		elif (var->writelevel == WRITE_Constexpr)
			op->setValue (var->value);
		else
		{