Rewriting C++ – Parser to Rust: Problem with understanding traits

  c++, rust, traits

To learn Rust I want to rewrite an old Project. A very simple arithmetic C++-Parser (only mult and plus). It works as intended in C++. It’s not meant to evaluate the arithmetic expression just recognize when parenthesis are mandatory or not (mult and plus).
Example: (5+1) * 2 = (5+1) * 2 but (5 * 1) * 1 = 5 * 1 * 1

I started off trying to implement the equivalent of header files to rust. (I don’t want to use bindgen).

There’s also ast.h/cpp, parser.h/cpp, but I wanted to start with the tokenizer.

That’s the old C++- Tokenizer header:

 // Tokenizer for exp


#ifndef __TOKENIZER__
#define __TOKENIZER__

#include <iostream>
#include <string>
#include <vector>

using namespace std;

typedef enum {
    EOS,           // End of string
    ZERO,
    ONE,
    TWO,
    OPEN,
    CLOSE,
    PLUS,
    MULT
} Token_t;

string showTok(Token_t t);

// Elementary tokenize(r) class
class Tokenize {
    string s;
    int pos;
public:
    Tokenize(string s) {
        this->s = s;
        pos = 0;
    }

    // Scan throuh string, letter (symbol) by letter.
    Token_t next();
    vector<Token_t> scan();
    string show();

};


// Wrapper class, provide the (current) token.
class Tokenizer : Tokenize {
public:
    Token_t token;
    Tokenizer(string s) : Tokenize(s) { token = next(); }
    void nextToken() {
        token = next();
    }
};

#endif // __TOKENIZER__

and it’s cpp file only as context :

#include <iostream>
#include <string>
#include <vector>

using namespace std;

#include "tokenizer.h"


string showTok(Token_t t) {
    switch(t) {
        case EOS:   return "EOS";
        case ZERO:  return "ZERO";
        case ONE:   return "ONE";
        case TWO:   return "TWO";
        case OPEN:  return "OPEN";
        case CLOSE: return "CLOSE";
        case PLUS:  return "PLUS";
        case MULT:  return "MULT";
    }
    
}

Token_t Tokenize::next() {
    if(s.length() <= pos)
        return EOS;

    while(1) {

        if(s.length() <= pos)
            return EOS;

        switch(s[pos]) {
            case '0': pos++;
                return ZERO;
            case '1': pos++;
                return ONE;
            case '2': pos++;
                return TWO;
            case '(': pos++;
                return OPEN;
            case ')': pos++;
                return CLOSE;
            case '+': pos++;
                return PLUS;
            case '*': pos++;
                return MULT;
            default:  
                pos++;
                break;
        }
    }
} // next


vector<Token_t> Tokenize::scan() {
    vector<Token_t> v;
    Token_t t;

    do {
        t = next();
        v.push_back(t);
    }
    while(t != EOS);

    return v;
} // scan


string Tokenize::show() {
    vector<Token_t> v = this->scan();
    string s;

    for(int i=0; i < v.size(); i++) {
        s += showTok(v[i]);
        if(i+1 < v.size())
            s += ";" ;         //delimiter
    }
    return s;
} // show

And here’s my attempt to rewrite the header in Rust:

enum Token_t {
    EndOfString,
    Zero,
    OneExp,
    TwoExp,
    OpenParan,
    CloseParan,
    Plus,
    Mult,
}

//fn showTok(Token_t: Token)-> string;

struct Tokenize{
    str: string,
    pos: int
}

trait Tokenize{
    fn tokenize(&self)->f64{
        self.str = str;
        self.pos = pos;
    }

    fn next()->Tokenize;
    fn scan()->vector<Tokenize>;
    fn show()-> string;
}


//Wrapper class, provide current Token

trait Tokenizer : Tokenize{
    

}

My understanding is that Rust equivalent of inheritance works with traits. Is that even the correct start to use them? And "self" should reference the struct field using the point operator . am I using it correctly?

Source: Windows Questions C++

LEAVE A COMMENT