0

I have some header files which host functions and in other enums.

So in file Lexer.h, I have a function called getNextToken() which returns a token and in this function I need to call a function called reservedLookup(string tokenString) found in token.h

reservedWords is another header file called reservedWords.h which has enum declarations of the reserved Words

This function is found in token.h

reservedWords reservedLookup (string tokenString)
{
        for(rIt = reservedMap.begin(); rIt!= reservedMap.end(); rIt++)
        {
            if(tokenString == (rIt->first))
            {
                return rIt->second;
            }

        }
}

in lexer.h I tried using this in private (and even in public:) :

reservedWords reservedLookup(string tokenString);

it compiles, but when in function Token* getNextToken() I use

int tokenType = reservedLookup(strBuffer);

it gives me an error stating:

obj\Release\main.o:main.cpp:(.text$_ZN5Lexer12getNextTokenEv[__ZN5Lexer12getNextTokenEv]+0x371)||undefined reference to `Lexer::reservedLookup(std::string)'|

I don't want my compiler to read reservedLookup as part of Lexer::reservedLookup(string str) but as Token::reservedLookup(string str)

Is there any way I can do it?


EDIT:

Token.h

class Token
{
       .....
       .....
public:

    void reservedDeclare ()
    {
         // iterator used for looping through reservedWords

        //Taking care of the Reserved Words first

        reservedMap["function"] =  reservedWords::tkfunction;

        //if - then - else - while - halt
        reservedMap["if"] = reservedWords::tkif;
        reservedMap["else"] = reservedWords::tkelse;
        reservedMap["while"] = reservedWords::tkwhile;
        reservedMap["halt"] = reservedWords::tkhalt;

        //and, or, not, true, else
        reservedMap["and"] = reservedWords::tkand;
        reservedMap["or"] = reservedWords::tkor;
        reservedMap["not"] = reservedWords::tknot;
        reservedMap["true"] = reservedWords::tktrue;
        reservedMap["false"] = reservedWords::tkfalse;

        //sets and read/write
        reservedMap["set"] = reservedWords::tkset;
        reservedMap["let"] = reservedWords::tklet;
        reservedMap["read"] = reservedWords::tkread;
        reservedMap["write"] = reservedWords::tkwrite;

        //variable type
        reservedMap["int"] = reservedWords::tkint;
        reservedMap["char"] = reservedWords::tkchar;
        reservedMap["bool"] = reservedWords::tkbool;
        reservedMap["real"] = reservedWords::tkreal;
        reservedMap["string"] = reservedWords::tkstring;
        reservedMap["unit"] = reservedWords::tkunit;


    }

reservedWords reservedLookup (string tokenString)
{
        for(rIt = reservedMap.begin(); rIt!= reservedMap.end(); rIt++)
        {
            if(tokenString == (rIt->first))
            {
                return rIt->second;
            }

        }
}

reservedWords.h

#ifndef RESERVEDWORDS_H_INCLUDED
#define RESERVEDWORDS_H_INCLUDED

#include <string>
#include <vector> //std::vector
#include <algorithm>    // std::find

using namespace std;

/**
        All the reserved words used by the compiler

*/


    /**
        This file contains all the keywords or reserved words or reserved Symbols used by the compiler
        In the lexer, we will check whether the string we are passing is either a Reserved word
        or it is actually and identifier
    */

    enum reservedWords
    {
        tkfunction,
        tkif,
        tkelse,
        tkwhile,
        tkhalt,

        tkand,
        tkor,
        tknot,
        tktrue,
        tkfalse,

        tkset,
        tklet,
        tkread,
        tkwrite,

        tkint,
        tkchar,
        tkbool,
        tkreal,
        tkstring,
        tkunit,

        tkreservedWord,
        tkidentifier


    };

    #endif // RESERVEDWORDS_H_INCLUDED

PARTIAL Code of Lexer.h

class Lexer
{
   private:
   string strBuffer ="";//holds the current characters that have been read and waiting to be matched
   int tokenType = 0;
   reservedWords reservedLookup(string tokenString); // THIS DOES NOT WORK. SEES IT AS Lexer::reservedLookup
  ....
  ....
  ...
  ...

  tokenType = reservedLookup(strBuffer); // GIVES ME ERROR BECAUSE OF ABOVE
DodoSombrero
  • 767
  • 3
  • 15
  • 29
  • Please make it clear when your code samples are inside a class definition or other context. – aschepler May 16 '14 at 00:06
  • @aschepler Check the edit, see if it helps... LEXER.H and TOKEN.H are both in a class. ReservedWords no, just enum – DodoSombrero May 16 '14 at 00:11
  • In the partial code of Lexer.h, where you have "THIS DOES NOT WORK" commented... Is that a class member function declaration within class Lexer? If it is _not_, why is it there? If it _is_, why doesn't it have a return value? – jeffrey_t_b May 16 '14 at 00:18
  • @jeffrey_t_b sorry that should be read as `reservedWords reservedlookup (string tokenString)` , I tried to make another header function to call the one in token.h (as I've seen on other tutorials) but it didn't help. all the other tutorials consisted of having .cpp with it – DodoSombrero May 16 '14 at 00:21
  • Is `tokenType = reservedLookup(strBuffer);` inside a function definition? If you want it to call `Token::reservedLookup`, what `Token` object to you want it to use? – aschepler May 16 '14 at 00:33
  • `tokenType = reservedLookup(strBuffer)` is found inside function called `Token* getNextToken()` which returns an enum. Token is an enum, which can return reservedWords and so. I want to call reservedLookup which is found in Token – DodoSombrero May 16 '14 at 00:36

1 Answers1

3

Let's look at this part of your code first:

class Token
{
  ...
public:
  ...
  reservedWords reservedLookup (string tokenString)
  {       // start of function body
    for(rIt = reservedMap.begin(); rIt!= reservedMap.end(); rIt++)
    {
        if(tokenString == (rIt->first))
        {
            return rIt->second;
        }

    }
  }       // end of function body
  ...
};

In this file you have declared a function whose fully-scoped name is Token::reservedLookup. (If you're unfamiliar with the term "fully scoped", OK; for our purposes here, the important thing is that this is a specific way of naming this function.) We can write Token:: at the front of this name because this function is a member of the class Token. You have also defined the function by providing a function body (the code enclosed in braces { and }). I have added comments on the lines where the function body begins and ends.

So far, so good. Now, this function is an ordinary member of the class Token, not a "static" function, so in order to call it, you must first have an object of type Token, and then you can call this function on that object, for example by writing code like this inside some other function:

Token token;
token.reservedDeclare();
reservedWords word = token.reservedLookup("read");

Now comes the part where things get confused. You wrote this code:

class Lexer
{
private:
  ...
  reservedWords reservedLookup(string tokenString);
  ...
};

What this does is to declare a different function from the first one. This function's fully-scoped name is Lexer::reservedLookup. You have not provided any definition of the function, however (neither here, nor apparently anywhere else). So when you are within the code of the Lexer class and you write a line such as this,

tokenType = reservedLookup(strBuffer);

the compiler interprets this in the way the C++ language specification says it should, which is that this should be a call to the function reservedLookup that belongs to the class of the same function where this call appeared. In short, it is a call to Lexer::reservedLookup. Since you never defined that function, it is impossible to produce the code that calls the function correctly, and therefore you have an error.

So you probably do not want to define Lexer::reservedLookup at all. If you are not calling Token::reservedLookup from within one of the functions of the class Token itself, you may provide an object of type Token so that you may call the function, as I did in my example. Alternatively, you might want to make your definition of the function static so that you can call it this way, without requiring an object of type Token:

reservedWords word = Token::reservedLookup("read");

In order to make this work as desired, however, you would also have to make reservedDeclare a static function and make reservedMap a static variable of Token, or make some other changes so that the data used by Token::reservedLookup exists independently of a specific object of type Token.

You may also want to look at the answers to this question: The Definitive C++ Book Guide and List and read a recommended book to help understand the terminology of the language better so that you can get better advice about your programs.

Community
  • 1
  • 1
David K
  • 3,147
  • 2
  • 13
  • 19
  • Thanks mate! really good explanation helped me with a lot of stuff. Will try some things out – DodoSombrero May 16 '14 at 05:10
  • so when functions are `ClassName::Function` they are Fully scoped right? sry if asking again – DodoSombrero May 16 '14 at 05:17
  • @DodoSerebro: Technically, no. For instance, there's `std::string::size` where `std` is a namespace, and `string` the class, and `size` the function. A name is fully qualified if it includes all surrounding classes and namespaces. – MSalters May 16 '14 at 13:43
  • As pointed out by @MSalters, it is not always the case that a fully-scoped name has only one `::`. In the code in the question. I merely assumed there was no additional scoping defined in the parts of the source files we didn't see. For example, I assumed you didn't write anything like `namespace parsing {` as the last thing before your definition of `class Token`, because that would have made the fully-scoped function name `parsing::Token::reservedLookup`. – David K May 16 '14 at 14:08