Skip to content

Commit

Permalink
feat: operators implemented!
Browse files Browse the repository at this point in the history
  • Loading branch information
orzklv committed Nov 27, 2024
1 parent bf57f00 commit 1b5522a
Show file tree
Hide file tree
Showing 6 changed files with 151 additions and 1 deletion.
22 changes: 22 additions & 0 deletions include/lexer.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
#include "process.h"
#include "sabine/vector.h"
#include "token.h"
#include <string.h>

#define S_EQ(str1, str2) (str1 && str2 && (strcmp(str1, str2) == 0))

#define NUMERIC_CASE \
case '0': \
Expand All @@ -21,6 +24,25 @@
case '8': \
case '9'

#define OPERATOR_CASE_EXCLUDING_DIVISION \
case '+': \
case '-': \
case '*': \
case '>': \
case '<': \
case '^': \
case '%': \
case '!': \
case '=': \
case '~': \
case '|': \
case '&': \
case '(': \
case '[': \
case ',': \
case '.': \
case '?'

enum {
LEXICAL_ANALYSIS_ALL_OK,
LEXICAL_ANALYSIS_INPUT_ERROR,
Expand Down
2 changes: 2 additions & 0 deletions include/token.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,6 @@ struct token {
const char *between_brackets;
};

bool token_is_keyword(struct token *token, const char *value);

#endif // SABINE_TOKEN_H
118 changes: 118 additions & 0 deletions src/lexer.c
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,120 @@ static struct token *token_make_string(char start_delim, char end_delim)
&(struct token){.type = TOKEN_TYPE_STRING, .sval = buffer_ptr(buf)});
}

static bool op_treated_as_one(char op)
{
return op == '(' || op == '[' || op == ',' || op == '.' || op == '*' ||
op == '?';
}

/**
* Check for single operator whether is it acutally an operator
*/
static bool is_single_operator(char op)
{
return op == '+' || op == '-' || op == '/' || op == '*' || op == '=' ||
op == '>' || op == '<' || op == '|' || op == '&' || op == '^' ||
op == '%' || op == '!' || op == '(' || op == '[' || op == ',' ||
op == '.' || op == '~' || op == '?';
}

bool op_valid(const char *op)
{
return S_EQ(op, "+") || S_EQ(op, "-") || S_EQ(op, "*") || S_EQ(op, "/") ||
S_EQ(op, "!") || S_EQ(op, "^") || S_EQ(op, "+=") || S_EQ(op, "-=") ||
S_EQ(op, "*=") || S_EQ(op, "/=") || S_EQ(op, ">>") || S_EQ(op, "<<") ||
S_EQ(op, ">=") || S_EQ(op, "<=") || S_EQ(op, ">") || S_EQ(op, "<") ||
S_EQ(op, "||") || S_EQ(op, "&&") || S_EQ(op, "|") || S_EQ(op, "&") ||
S_EQ(op, "++") || S_EQ(op, "--") || S_EQ(op, "=") || S_EQ(op, "!=") ||
S_EQ(op, "==") || S_EQ(op, "->") || S_EQ(op, "(") || S_EQ(op, "[") ||
S_EQ(op, ",") || S_EQ(op, ".") || S_EQ(op, "...") || S_EQ(op, "~") ||
S_EQ(op, "?") || S_EQ(op, "%");
}

void read_op_flush_back_keep_first(struct buffer *buffer)
{
const char *data = buffer_ptr(buffer);

int len = buffer->len;
for (int i = len - 1; i >= 1; i--) {
if (data[i] == 0x00) {
continue;
}

pushc(data[i]);
}
}

const char *read_op()
{
bool single_operator = true;

char op = nextc();
struct buffer *buffer = buffer_create();
buffer_write(buffer, op);

if (!op_treated_as_one(op)) {
op = peekc();
if (is_single_operator(op)) {
buffer_write(buffer, op);
nextc();

single_operator = false;
}
}

// null terminator
buffer_write(buffer, 0x00);
char *ptr = buffer_ptr(buffer);

if (!single_operator) {
if (!op_valid(ptr)) {
read_op_flush_back_keep_first(buffer);
ptr[1] = 0x00;
}
}
else if (!op_valid(ptr)) {
compiler_error(lex_process->compiler, "The operator %s is not valid\n",
ptr);
}

return ptr;
}

static void lex_new_expression()
{
lex_process->current_expression_count++;
if (lex_process->current_expression_count == 1) {
lex_process->parentheses_buffer = buffer_create();
}
}

bool lex_is_in_expression()
{
return lex_process->current_expression_count > 0;
}

static struct token *token_make_operator_or_string()
{
// dedicated to every key newline include psychos
char op = peekc();
if (op == '<') {
struct token *last_token = lexer_last_token();
if (token_is_keyword(last_token, "include")) {
return token_make_string('<', '>');
}
}

struct token *token = token_create(
&(struct token){.type = TOKEN_TYPE_OPERATOR, .sval = read_op()});

if (op == '(') {
lex_new_expression();
}

return token;
}

struct token *read_next_token()
{
struct token *token = NULL;
Expand All @@ -147,6 +261,10 @@ struct token *read_next_token()
token = token_make_number();
break;

OPERATOR_CASE_EXCLUDING_DIVISION:
token = token_make_operator_or_string();
break;

case '"':
token = token_make_string('"', '"');
break;
Expand Down
2 changes: 1 addition & 1 deletion src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

int main()
{
int res = compile_file("./tests/string.c", "./tests/string", 0);
int res = compile_file("./tests/operator.c", "./tests/output", 0);

if (res == COMPILER_FILE_COMPILED_OK) {
printf("trace: compiled successfully\n");
Expand Down
7 changes: 7 additions & 0 deletions src/token.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#include "token.h"
#include "lexer.h"

bool token_is_keyword(struct token *token, const char *value)
{
return token->type == TOKEN_TYPE_KEYWORD && S_EQ(token->sval, value);
}
1 change: 1 addition & 0 deletions tests/operator.c
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
50 - 20 "something" 2342

0 comments on commit 1b5522a

Please sign in to comment.