Printing string creates stackdump

Moving on from https://www.cplusplus.com/forum/general/279314/ , I put that aside temporarily and decided to just move on for now. New issue: The code thinks the 4th token (type TOKEN_RPAREN) has the type TOKEN_IDENTIFIER and it won't let me print the content of the token. Source code is on https://github.com/Axocudo/Axocudo .
What output did you get?
What output did you expect?
I didn't get any output, nor did I really expect anything.
Parser::Parser contains the statement
this->lexer = &lexer;
where lexer is a formal parameter of type Lexer.

The formal parameter's lifetime ends when the constructor returns. Again Parser::lexer is left a dangling pointer.
Last edited on
Now it seems to work.
That's the following output I get in VS 2019
Type: TOKEN_IDENTIFIER
Content: print

Type: TOKEN_LPAREN
Content: (

Type: TOKEN_STRING
Content: Hello World!

Type: TOKEN_RPAREN
Content: )

Type: TOKEN_SEMI
Content: ;

Type: TOKEN_IDENTIFIER
Content: print

Type: TOKEN_LPAREN
Content: (

Type: TOKEN_STRING
Content: Second test

Type: TOKEN_RPAREN
Content: )

Type: TOKEN_SEMI
Content: ;

Type: 10
Content:

parse_statements();
parse_statement();
parse_identifier();
parse_variable();
Ate token of type 0.
New token's type 0.
New token's content print
HEY
Start!
3
Variable
Finish!


CORRECTION:
When I run it in Release mode I got the following exception:
Exception thrown at 0x010B21E5 in Axocudo-main.exe: 0xC0000005: Access violation reading location 0x00000003.
1
2
3
Token* Lexer::getToken(int index) {
    return this->tokenVector.at(index);
}
Last edited on
When I run it in Release mode I got the following exception: Exception thrown at 0x010B21E5 in Axocudo-main.exe: 0xC0000005: Access violation reading location 0x00000003.

That sounds like the problem.
Parser::Parser contains the statement
this->lexer = &lexer;
where lexer is a formal parameter of type Lexer.

Got it fixed by removing the &.
Another problem is leaking memory.
You have 29 new all over the place but not a single delete.
I would suggest getting rid of all this pointers and use value semantics.
Consider moving the Lexer object.
Parser::Parser( Lexer lexer ) : lexer( std::move(lexer) ) { /* ... */ }
A couple of comments.

1) Why are you using this-> everywhere? Within the body of a class function, you don't need to use this-> to refer to a class variable.

2) I'd advise against using the same name for a function parameter and a member variable.

3) Initialise member variables when they are defined. You don't then need to initialise these in the constructor(s) unless to a different value.

4) Pass containers/class etc (eg std::string) by ref/const ref and not by value to avoid a copy (unless a copy is required)

5) Use member initialization lists to initialise member variables.

Eg. For lexer.h (partial)

1
2
3
4
5
 private:
        std::string code;

        char c {};
        size_t i {};


lexer.cpp (partial)

 
Lexer::Lexer(const std::string& code_) : code(code_), c(code[i]), tokenVector(tokenize()) {}


There's also much scope for code simplification. Eg

1
2
3
std::string Lexer::getCurrentCharAsString() {
    return std::string(1, c);
}


1
2
3
4
5
6
7
std::vector<Token*> Lexer::tokenize() {
    std::vector<Token*> tokvector;
    
    for (Token* token {};  (token = getNextToken())->getType() != TOKEN_EOF; tokvector.push_back(token));

    return tokvector;
}


1
2
3
4
5
6
7
8
Token* Lexer::collectIdentifier() {
    std::string value;

   for (; isalnum(c); advance())
        value += c;

    return new Token(TOKEN_IDENTIFIER, value);
}


There's also isspace() to test if a char is a white-space char (space, tab, newline).

For AST.

You're got an enum for AST_TYPE. You're then got different member variables for each type.

Consider having a separate class/struct for each ast type. Then use a std::variant of these types which is accessed via the std::visit pattern. You then have a tree (or vector or however you're holding these) of these variants. Then use std::visit to process each of these types.
Last edited on
Why are you using this-> everywhere?
The local name clashed with parameter name, and he's used the pattern everywhere to avoid the problem.

He's also passing by value everywhere, using raw pointers. The only thing that's saved him so far is he's just let them leak, and not tried to handle them cleanly.

However, I thought it best to let him make some progress on the project, and fix this stuff and improve on language issues later on. Being able to use the language to do stuff is really important.
You should put this badly-written program aside (or trash it) and actually learn C++ first.
Here you go, OP.
https://github.com/Axocudo/Axocudo/pull/2
I removed all error-prone constructs and replaced them with safe modern C++ equivalents. The most serious one was a few dynamic arrays you were managing manually with malloc() and realloc(). There's still more to fix. The OOP design is bad, the Visitor pattern is incorrectly implemented, and the parser doesn't properly parse your language. You still have a ways to go.
Topic archived. No new replies allowed.