asCScriptNode *asCParser::ParseFunction(bool isMethod)
{
	asCScriptNode *node = new asCScriptNode(snFunction);

	// If this is a class constructor then no return type will be declared
	sToken t1,t2;
	GetToken(&t1);
	GetToken(&t2);
	RewindTo(&t1);
	if( !isMethod || t2.type != ttOpenParanthesis )
	{
		node->AddChildLast(ParseType(false));
		if( isSyntaxError ) return node;

		node->AddChildLast(ParseTypeMod(false));
		if( isSyntaxError ) return node;
	}

	node->AddChildLast(ParseIdentifier());
	if( isSyntaxError ) return node;

	node->AddChildLast(ParseParameterList());
	if( isSyntaxError ) return node;

	node->AddChildLast(ParseStatementBlock());

	return node;
}
asCScriptNode *asCParser::ParseInterfaceMethod()
{
	asCScriptNode *node = new asCScriptNode(snFunction);

	node->AddChildLast(ParseType(true));
	if( isSyntaxError ) return node;

	node->AddChildLast(ParseTypeMod(false));
	if( isSyntaxError ) return node;

	node->AddChildLast(ParseIdentifier());
	if( isSyntaxError ) return node;

	node->AddChildLast(ParseParameterList());
	if( isSyntaxError ) return node;

	// Parse an optional const after the method definition
	sToken t1;
	GetToken(&t1);
	RewindTo(&t1);
	if( t1.type == ttConst )
		node->AddChildLast(ParseToken(ttConst));

	GetToken(&t1);
	if( t1.type != ttEndStatement )
	{
		Error(ExpectedToken(";").AddressOf(), &t1);
		return node;
	}

	node->UpdateSourcePos(t1.pos, t1.length);

	return node;
}
list<Parametro*> Sintactico::ParseFunctionParam()
{
	list<Parametro*> lista_params;
	if ( proximo_token.GetTipo() == punt_colon )
	{
		proximo_token = analizador_lexico->ObtenerSiguienteToken();
		return lista_params; //Lista de parametros vacia

	}
	else if ( proximo_token.GetTipo() == punt_parentizq )
	{
		proximo_token = analizador_lexico->ObtenerSiguienteToken();

		lista_params = ParseParameterList();

		if (proximo_token.GetTipo() == punt_parentder)
		{
			proximo_token = analizador_lexico->ObtenerSiguienteToken();

			if ( proximo_token.GetTipo() == punt_colon )
			{
				proximo_token = analizador_lexico->ObtenerSiguienteToken();
				return lista_params;
			}
			else
				throw SyntaxException("Falta un token de colon" ,analizador_lexico->GetLineaActual());
		}
		else
			throw SyntaxException("Falta un parentesis derecho",analizador_lexico->GetLineaActual());
	}
	else 
		throw SyntaxException("Token invalido",analizador_lexico->GetLineaActual());
}
asCScriptNode *asCParser::ParseFunctionDefinition()
{
	asCScriptNode *node = new asCScriptNode(snFunction);

	node->AddChildLast(ParseType(true));
	if( isSyntaxError ) return node;

	node->AddChildLast(ParseTypeMod(false));
	if( isSyntaxError ) return node;

	node->AddChildLast(ParseIdentifier());
	if( isSyntaxError ) return node;

	node->AddChildLast(ParseParameterList());
	if( isSyntaxError ) return node;

	// Parse an optional const after the function definition (used for object methods)
	sToken t1;
	GetToken(&t1);
	RewindTo(&t1);
	if( t1.type == ttConst )
		node->AddChildLast(ParseToken(ttConst));

	return node;
}
list<Parametro*> Sintactico::ParseProcedureParam()
{
	list<Parametro*> lista_params;
	if ( proximo_token.GetTipo() == punt_puntocoma )
	{
		proximo_token = analizador_lexico->ObtenerSiguienteToken();
		return lista_params;
	}
	else if ( proximo_token.GetTipo() == punt_parentizq )
	{
		proximo_token = analizador_lexico->ObtenerSiguienteToken();

		lista_params = ParseParameterList();
		if ( proximo_token.GetTipo() == punt_parentder )
		{
			proximo_token = analizador_lexico->ObtenerSiguienteToken();

			if ( proximo_token.GetTipo() == punt_puntocoma )
			{
				proximo_token = analizador_lexico->ObtenerSiguienteToken();
				return lista_params;
			}
			else
				throw SyntaxException("Falta un punto y coma",analizador_lexico->GetLineaActual());
		}
		else{

			throw SyntaxException("Falta un parentesis derecho",analizador_lexico->GetLineaActual());
		}
	}else 
		throw SyntaxException("Parametro de procedimiento incorrecto",analizador_lexico->GetLineaActual());
}
void
nsSVGAnimatedTransformList::SMILAnimatedTransformList::ParseValue(
  const nsAString& aSpec,
  const nsIAtom* aTransformType,
  nsSMILValue& aResult)
{
  MOZ_ASSERT(aResult.IsNull(), "Unexpected type for SMIL value");

  static_assert(SVGTransformSMILData::NUM_SIMPLE_PARAMS == 3,
                "nsSVGSMILTransform constructor should be expecting array "
                "with 3 params");

  float params[3] = { 0.f };
  int32_t numParsed = ParseParameterList(aSpec, params, 3);
  uint16_t transformType;

  if (aTransformType == nsGkAtoms::translate) {
    // tx [ty=0]
    if (numParsed != 1 && numParsed != 2)
      return;
    transformType = SVG_TRANSFORM_TRANSLATE;
  } else if (aTransformType == nsGkAtoms::scale) {
    // sx [sy=sx]
    if (numParsed != 1 && numParsed != 2)
      return;
    if (numParsed == 1) {
      params[1] = params[0];
    }
    transformType = SVG_TRANSFORM_SCALE;
  } else if (aTransformType == nsGkAtoms::rotate) {
    // r [cx=0 cy=0]
    if (numParsed != 1 && numParsed != 3)
      return;
    transformType = SVG_TRANSFORM_ROTATE;
  } else if (aTransformType == nsGkAtoms::skewX) {
    // x-angle
    if (numParsed != 1)
      return;
    transformType = SVG_TRANSFORM_SKEWX;
  } else if (aTransformType == nsGkAtoms::skewY) {
    // y-angle
    if (numParsed != 1)
      return;
    transformType = SVG_TRANSFORM_SKEWY;
  } else {
    return;
  }

  nsSMILValue val(SVGTransformListSMILType::Singleton());
  SVGTransformSMILData transform(transformType, params);
  if (NS_FAILED(SVGTransformListSMILType::AppendTransform(transform, val))) {
    return; // OOM
  }

  // Success! Populate our outparam with parsed value.
  aResult.Swap(val);
}
void
nsSVGTransformSMILAttr::ParseValue(const nsAString& aSpec,
                                   const nsIAtom* aTransformType,
                                   nsSMILValue& aResult)
{
  NS_ASSERTION(aResult.IsNull(), "Unexpected type for SMIL value");

  // nsSVGSMILTransform constructor should be expecting array with 3 params
  PR_STATIC_ASSERT(nsSVGSMILTransform::NUM_SIMPLE_PARAMS == 3);

  float params[3] = { 0.f };
  PRInt32 numParsed = ParseParameterList(aSpec, params, 3);
  nsSVGSMILTransform::TransformType transformType;

  if (aTransformType == nsGkAtoms::translate) {
    // tx [ty=0]
    if (numParsed != 1 && numParsed != 2)
      return;
    transformType = nsSVGSMILTransform::TRANSFORM_TRANSLATE;
  } else if (aTransformType == nsGkAtoms::scale) {
    // sx [sy=sx]
    if (numParsed != 1 && numParsed != 2)
      return;
    if (numParsed == 1) {
      params[1] = params[0];
    }
    transformType = nsSVGSMILTransform::TRANSFORM_SCALE;
  } else if (aTransformType == nsGkAtoms::rotate) {
    // r [cx=0 cy=0]
    if (numParsed != 1 && numParsed != 3)
      return;
    transformType = nsSVGSMILTransform::TRANSFORM_ROTATE;
  } else if (aTransformType == nsGkAtoms::skewX) {
    // x-angle
    if (numParsed != 1)
      return;
    transformType = nsSVGSMILTransform::TRANSFORM_SKEWX;
  } else if (aTransformType == nsGkAtoms::skewY) {
    // y-angle
    if (numParsed != 1)
      return;
    transformType = nsSVGSMILTransform::TRANSFORM_SKEWY;
  } else {
    return;
  }

  nsSMILValue val(&nsSVGTransformSMILType::sSingleton);
  nsSVGSMILTransform transform(transformType, params);
  if (NS_FAILED(nsSVGTransformSMILType::AppendTransform(transform, val))) {
    return;
  }

  // Success! Initialize our outparam with parsed value.
  aResult = val;
}
asCScriptNode *asCParser::ParseFunction()
{
	asCScriptNode *node = new asCScriptNode(snFunction);

	node->AddChildLast(ParseType(false));
	if( isSyntaxError ) return node;

	node->AddChildLast(ParseTypeMod(false));
	if( isSyntaxError ) return node;

	node->AddChildLast(ParseIdentifier());
	if( isSyntaxError ) return node;

	node->AddChildLast(ParseParameterList());
	if( isSyntaxError ) return node;

	node->AddChildLast(ParseStatementBlock());

	return node;
}
SymVar* Parser::ParseDeclarator(SymType* type, bool parseParams)
{
    SymVar* result = NULL;

    //pointer
    while (*lexer.Peek() == MULTIPLICATION)
    {
        type = new SymTypePointer(type);
        lexer.Get();
    }

    //direct-declarator
    if (*lexer.Peek() == ROUND_LEFT_BRACKET)
    {
        lexer.Get();
        result =  ParseDeclarator(type);
        Expected(lexer.Get()->GetSubType(), ROUND_RIGHT_BRACKET);
        return result;
    }

    Expected(parseParams || *lexer.Peek() == IDENTIFIER, "exepcted an identifier");

    if (parseParams && *lexer.Peek() != IDENTIFIER)
    {
        string n = to_string((long double)counter++);
        BaseToken* dummy = new BaseToken("abstract-"+n, 0, 0, IDENTIFIER, IDENTIFIER);
        result = new SymVar(dummy, type);
    }
    else
    {
        string msg = "redefinition: " + lexer.Peek()->GetText();
        Expected(!symStack.Top()->Find(lexer.Peek()->GetText()), &msg[0]);
        result = new SymVar(lexer.Get(), type);
    }

    BaseToken* token = lexer.Peek();
    if (*token == SQUARE_LEFT_BRACKET)
    {
        lexer.Get();
        Expected(*lexer.Peek() != SQUARE_RIGHT_BRACKET, "unknown size");

        SyntaxNode* index = ParseExpression();
        Expected(*index->token != IDENTIFIER, "expression must have a constant value");

        SymType* indexType = index->GetType();
        Expected(indexType == intType && indexType->CanConvertTo(intType),
                 "expression must be an integral constant expression");

        Expected(lexer.Get()->GetSubType(), SQUARE_RIGHT_BRACKET);

        int size = dynamic_cast<TokenVal <int> *>(index->token)->GetValue();
        result->SetType(new SymTypeArray(size, type));
    }
    else if (*token == ROUND_LEFT_BRACKET)
    {
        lexer.Get();
        SymTypeFunc* t = new SymTypeFunc(type);
        t->params->offset = 4;

        symStack.Push(t->params);
        ParseParameterList();
        symStack.Pop();

        if (*lexer.Peek() == FIGURE_LEFT_BRACKET)
        {
            parseFunc.push_back(t);
            t->body = ParseBlock();
            parseFunc.pop_back();
        }
        result->SetType(t);
    }

    return result;
}