Compare commits
3 Commits
2e773218be
...
ab690f4bb5
Author | SHA1 | Date |
---|---|---|
|
ab690f4bb5 | |
|
be648a6485 | |
|
4cd5115d4b |
|
@ -16,6 +16,8 @@ typedef enum {
|
|||
TOKEN_RBRACE,
|
||||
TOKEN_LBRACKET,
|
||||
TOKEN_RBRACKET,
|
||||
TOKEN_CHARACTER,
|
||||
TOKEN_STRING,
|
||||
} TokenType;
|
||||
|
||||
typedef struct {
|
||||
|
|
52
src/lexer.c
52
src/lexer.c
|
@ -25,18 +25,18 @@ static char peek(Lexer *lexer) {
|
|||
return lexer->source[lexer->pos];
|
||||
}
|
||||
|
||||
static char double_peek(Lexer *lexer) {
|
||||
return lexer->source[lexer->pos+1];
|
||||
static char far_peek(Lexer *lexer, size_t index) {
|
||||
return lexer->source[lexer->pos + index];
|
||||
}
|
||||
|
||||
static char advance(Lexer *lexer) {
|
||||
static void advance(Lexer *lexer) {
|
||||
if (lexer->source[lexer->pos] == '\n') {
|
||||
lexer->line++;
|
||||
lexer->column = 1;
|
||||
} else {
|
||||
lexer->column++;
|
||||
}
|
||||
return lexer->source[lexer->pos++];
|
||||
lexer->source[lexer->pos++];
|
||||
}
|
||||
|
||||
typedef enum {
|
||||
|
@ -56,6 +56,20 @@ static char is_digit_char(char c, DigitFlags flags) {
|
|||
return isdigit(c) || c == '_';
|
||||
}
|
||||
|
||||
static char is_digit_after(char c) {
|
||||
return
|
||||
isspace(c) ||
|
||||
c == '\0' ||
|
||||
c == ',' ||
|
||||
c == ')' ||
|
||||
c == '(' ||
|
||||
c == '}' ||
|
||||
c == '{' ||
|
||||
c == ']' ||
|
||||
c == '[' ||
|
||||
c == ';';
|
||||
}
|
||||
|
||||
static char is_identifier_start(char c) {
|
||||
return isalpha(c) || c == '_';
|
||||
}
|
||||
|
@ -77,7 +91,7 @@ TokenResult lexer_next(Lexer *lexer) {
|
|||
|
||||
while (isspace(peek(lexer)) || peek(lexer) == '/') {
|
||||
// Skip Comments
|
||||
if (peek(lexer) == '/' && double_peek(lexer) == '/')
|
||||
if (peek(lexer) == '/' && far_peek(lexer, 1) == '/')
|
||||
while (peek(lexer) != '\n') advance(lexer);
|
||||
// Skip whitespace
|
||||
while (isspace(peek(lexer))) advance(lexer);
|
||||
|
@ -108,13 +122,39 @@ TokenResult lexer_next(Lexer *lexer) {
|
|||
}
|
||||
}
|
||||
while (is_digit_char(peek(lexer), flags)) advance(lexer);
|
||||
if (isspace(peek(lexer)) || peek(lexer) == ';' || peek(lexer) == '\0' || peek(lexer) == ')' || peek(lexer) == '(' || peek(lexer) == ',') {
|
||||
if (is_digit_after(peek(lexer))) {
|
||||
return lexer_result(lexer, TOKEN_NUMBER, start, start_line);
|
||||
} else {
|
||||
return lexer_error(lexer, "Invalid number format", start, start_line);
|
||||
}
|
||||
}
|
||||
|
||||
// Characters
|
||||
if (c == '\'') {
|
||||
advance(lexer); // Opening `'`
|
||||
if (peek(lexer) == '\\') advance(lexer); // Slash
|
||||
advance(lexer); // Char
|
||||
if (peek(lexer) == '\'') {
|
||||
advance(lexer); // Closing `'`
|
||||
return lexer_result(lexer, TOKEN_CHARACTER, start, start_line);
|
||||
} else return lexer_error(lexer, "Invalid character format", start, start_line);
|
||||
}
|
||||
|
||||
// Strings
|
||||
if (c == '"') {
|
||||
advance(lexer);
|
||||
while (peek(lexer) != '"') {
|
||||
if (peek(lexer) == '\\') {
|
||||
advance(lexer);
|
||||
} else if (peek(lexer) == '\n') {
|
||||
return lexer_error(lexer, "Invalid string format", start, start_line);
|
||||
}
|
||||
advance(lexer);
|
||||
}
|
||||
advance(lexer);
|
||||
return lexer_result(lexer, TOKEN_STRING, start, start_line);
|
||||
}
|
||||
|
||||
// Identifiers
|
||||
if (is_identifier_start(c)) {
|
||||
while (is_identifier_char(peek(lexer))) advance(lexer);
|
||||
|
|
|
@ -4,11 +4,12 @@
|
|||
#include "sync/lexer.h"
|
||||
|
||||
static void print_token(Token token) {
|
||||
printf("Token: %-15s | Text: '%.*s'\n",
|
||||
printf("Token: %-15s | Text: %.*s\n",
|
||||
(const char *[]){
|
||||
"EOF", "IDENTIFIER", "NUMBER", "OPERATOR",
|
||||
"LPAREN", "RPAREN", "SEMICOLON", "LBRACE",
|
||||
"RBRACE", "LBRACKET", "RBRACKET"
|
||||
"RBRACE", "LBRACKET", "RBRACKET", "CHARACTER",
|
||||
"STRING"
|
||||
}[token.type],
|
||||
(int)token.length, token.start
|
||||
);
|
||||
|
@ -46,6 +47,9 @@ int main(void) {
|
|||
fprintf(stderr, "Error: %s\n", result.error.message);
|
||||
fprintf(stderr, "\tFilename: %s\n", result.error.file_info.filename);
|
||||
fprintf(stderr, "\tLine: %zi\n", result.error.file_info.line);
|
||||
fprintf(stderr, "\tColumn: %zi\n", result.error.file_info.column);
|
||||
free(source);
|
||||
return 1;
|
||||
}
|
||||
} while (result.type != SYNC_ERROR && result.result.type != TOKEN_EOF);
|
||||
|
||||
|
|
Loading…
Reference in New Issue