Question

so I'm trying to build a vector recursively, as I look at this I begin to think I'm doing it quite wrong. Will the following code return a vector with each iterations results, or am I just creating new vectors on each iteration that actually wont build on each recursive call. If I'm wrong, how do I go about building a vector recursively... Thanks in advance for your constructive help!

std::vector<ParameterClass> recursiveParser :: parseParamList()
{
  std::vector<ParameterClass> paramVector;

  if (lexicator->getCurrentToken()->getTokenType() == STRING) {

    paramVector.push_back(ParameterClass(*lexicator->getCurrentToken()));
    lexicator->advance();
    parseParamList();

  } else if (lexicator->getCurrentToken()->getTokenType() == ID) {

    paramVector.push_back(ParameterClass(*lexicator->getCurrentToken()));
    lexicator->advance();
    parseParamList();

  } else {

  // so as to not fail in Expression, i need to check to see that there is a
  // left paren indicating that there should be an expression

    if (lexicator->getCurrentToken()->getTokenType() == LEFT_PAREN) {
      paramVector.push_back(ParameterClass(parseExpression()));
      lexicator->advance();
      parseParamList();
    }
  }
  return paramVector;
}
Was it helpful?

Solution

If you want build a list (vector etc) recursively, use the following pattern:

private:
    void InternalBuild(std::vector<OutputData> & vec)
    {
        // Add data to vec
        // Possibly call recursively InternalBuild(vec);
    }

public:
    std::vector<OutputData> RecursiveBuild()
    {
        std::vector<OutputData> vec;
        InternalBuild(vec);
        return vec;
    }

It is worth noting, that you seem to misuse recursion here. The recursion is meant to be used on data structures, which are recursive by their nature (trees, graphs etc.). In this case you process linear data recursively - why not simply write something like:

while (!lexer.endOfExpression())
{
    // Process token

    lexer.Advance();
}

In your case, if you get expression long enough, you'll end up with a stack overflow exception, because your program will run out of stack memory. That won't happen if you implement this algorithm linearly.

OTHER TIPS

try this, which append the result from recursive call

    std::vector<ParameterClass> recursiveParser :: parseParamList()
 {
std::vector<ParameterClass> paramVector;
if(lexicator->getCurrentToken()->getTokenType() == STRING)
{
    paramVector.push_back(ParameterClass(*lexicator->getCurrentToken()));
    lexicator->advance();
    std::vector<ParameterClass> result = parseParamList();
    std::copy(result.begin(), result.end(), std::back_inserter(paramVector));
}
else
    if(lexicator->getCurrentToken()->getTokenType() == ID)
    {
        paramVector.push_back(ParameterClass(*lexicator->getCurrentToken()));
        lexicator->advance();
        std::vector<ParameterClass> result = parseParamList();
        std::copy(result.begin(), result.end(), std::back_inserter(paramVector));
    }else
    {
        // so as to not fail in Expression, i need to check to see that there is a left paren indicating that there should be an expression
        if(lexicator->getCurrentToken()->getTokenType() == LEFT_PAREN)
        {
            paramVector.push_back(ParameterClass(parseExpression()));
            lexicator->advance();
            std::vector<ParameterClass> result = parseParamList();
            std::copy(result.begin(), result.end(), std::back_inserter(paramVector));
        }
    }
return paramVector;
 }

also please use switch instead of if-elseif-elseif and avoid repeated code

std::vector<ParameterClass> recursiveParser :: parseParamList()
{
    std::vector<ParameterClass> paramVector;

    switch(lexicator->getCurrentToken()->getTokenType())
    {
    case STRING:
        paramVector.push_back(ParameterClass(*lexicator->getCurrentToken()));
        break;
    case ID:
        paramVector.push_back(ParameterClass(*lexicator->getCurrentToken()));
        break;
    case LEFT_PAREN: // so as to not fail in Expression, i need to check to see that there is a left paren indicating that there should be an expression
        paramVector.push_back(ParameterClass(parseExpression()));
        break;
    }
    lexicator->advance();
    std::vector<ParameterClass> result = parseParamList();
    std::copy(result.begin(), result.end(), std::back_inserter(paramVector));
    return paramVector;
}

but use @Spook's pattern, because it allows tail call optimization

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top