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