I can't figure out what is going on in my program, I'm having a hard time wrapping my mind around what steps its taking to get to the wrong result.
I have this function which should make my parser ignore C-style comments, ie /* */. When I type /* * */ or any number of * in the comment my program is detecting the * characters inside the comment itself, and when it detects a * it also detects the last /:
// Handle C-style comments
private void HandleComment() {
// Consume until closing characters, multi-line comments are supported
while (Peek() != '*' && PeekAhead() != '/' && !IsAtEnd()) {
if (Peek() == '\n') line++;
Advance();
}
Advance();
Advance();
}
I figured I would need to Advance() twice in order to consume both the characters that denote the end of the comment.
Peek(), PeekAhead(), Advance() and IsAtEnd() are functions from the book, Crafting Interpreters, here they are:
// Peek at the next char
private char Peek() {
if (IsAtEnd()) return '\0';
return source[current];
}
// Peek after next char
private char PeekAhead() {
if (current + 1 >= source.Length) return '\0';
return source[current+1];
}
private char Advance() {
return source[current++];
}
private bool IsAtEnd() {
return current >= source.Length;
}
The source variable is just a string that contains the text contents of a file or the input from Console.ReadLine().
I based the comment logic on the string logic here:
// Handle string lexemes
private void HandleString() {
// Consume until closing quote, multi-line strings are supported
while (Peek() != '"' && !IsAtEnd()) {
if (Peek() == '\n') line++;
Advance();
}
// Handle unterminated strings
if (IsAtEnd()) {
DotLox.Error(line, "Unterminated string.");
return;
}
// Consume
Advance();
// Tokenize string and store value without quotes
string value = source[(start+1)..(current-1)];
AddToken(TokenType.STRING, value);
}
I almost forgot to share this crucial bit of logic here:
private void ScanToken() {
char c = Advance();
// Match characters to tokens
switch(c) {
// Division and comments
case '/':
if (Match('/')) {
// Consume comment but don't turn it into a token
while (Peek() != '\n' && !IsAtEnd()) Advance();
} else if (Match('*')) {
// Handle C-style comments
HandleComment();
} else {
// Turn lone slash into a token
AddToken(TokenType.SLASH);
}
break;
}
}