interpreter working nicely

This commit is contained in:
Shautvast 2024-12-11 21:36:36 +01:00
parent 5df54044f8
commit 1c092acd40
11 changed files with 448 additions and 76 deletions

View file

@ -1,13 +1,13 @@
TARGET := ./target TARGET := ./target
SRC := ./src SRC := ./src
CC := clang -c -std=c17 CC := clang -c -std=c17
#-Wall -Wextra -pedantic -Werror # -Wall -Wextra -pedantic -Werror
SRCS := $(shell find $(SRC) -name '*.c') SRCS := $(shell find $(SRC) -name '*.c')
OBJS := $(SRCS:%=$(TARGET)/%.o) OBJS := $(SRCS:%=$(TARGET)/%.o)
$(TARGET)/lox: $(TARGET)/lox.c.o $(TARGET)/parser.c.o $(TARGET)/scanner.c.o $(TARGET)/tokens.c.o $(TARGET)/utils.c.o $(TARGET)/lox: $(TARGET)/lox.c.o $(TARGET)/interpreter.c.o $(TARGET)/parser.c.o $(TARGET)/scanner.c.o $(TARGET)/tokens.c.o $(TARGET)/utils.c.o
clang $(TARGET)/lox.c.o -L$(TARGET) -lparser.c.o -ltokens.c.o -lscanner.c.o -lutils.c.o -o $(TARGET)/lox clang $(TARGET)/lox.c.o -L$(TARGET) -linterpreter.c.o -lparser.c.o -ltokens.c.o -lscanner.c.o -lutils.c.o -o $(TARGET)/lox
$(TARGET)/utils.c.o: $(SRC)/utils.c $(TARGET)/utils.c.o: $(SRC)/utils.c
$(CC) $< -o $@ $(CC) $< -o $@
@ -21,6 +21,9 @@ $(TARGET)/scanner.c.o: $(SRC)/scanner.c
$(TARGET)/parser.c.o: $(SRC)/parser.c $(TARGET)/parser.c.o: $(SRC)/parser.c
$(CC) $< -o $@ $(CC) $< -o $@
$(TARGET)/interpreter.c.o: $(SRC)/interpreter.c
$(CC) $< -o $@
$(TARGET)/lox.c.o: $(SRC)/lox.c $(TARGET) $(TARGET)/lox.c.o: $(SRC)/lox.c $(TARGET)
$(CC) $< -o $@ $(CC) $< -o $@

248
src/interpreter.c Normal file
View file

@ -0,0 +1,248 @@
#include "interpreter.h"
#include <string.h>
Value *accept(Expression *expr);
void checkNumeric(Value *left, Value *right);
Value *isEqual(Value *left, Value *right);
bool streq(char *left, char *right);
Value *visitBinary(Expression *expr);
Value *visitUnary(Expression *unary);
Value *visitLiteral(Expression *literal);
Value *visitGroup(Expression *literal);
Value *visitVariable(Expression *var);
Value *visitVariableStmt(Expression *varStmt);
Value *visitAssignStmt(Expression *varStmt);
Value *visitPrintStmt(Expression *printStatement);
Value *visitBlock(Expression *block);
static VarMap *current;
Value *accept(Expression *expr) {
// printf("accept %s\n", expr->type);
char *type = expr->type;
if (streq(type, "BinaryExpr")) {
return visitBinary(expr);
}
if (streq(type, "UnaryExpr")) {
return visitUnary(expr);
}
if (streq(type, "Literal")) {
return visitLiteral(expr);
}
if (streq(type, "Group")) {
return visitGroup(expr);
}
if (streq(type, "PrintStmt")) {
return visitPrintStmt(expr);
}
if (streq(type, "VariableStmt")) {
return visitVariableStmt(expr);
}
if (streq(type, "AssignStmt")) {
return visitAssignStmt(expr);
}
if (streq(type, "Variable")) {
return visitVariable(expr);
}
if (streq(type, "ExprStmt")) {
return accept(expr->left);
}
if (streq(type, "Block")) {
return visitBlock(expr);
}
return NULL;
}
void execute(Expression *statement) { accept(statement); }
void interpret(VarMap *environment, ExpressionList *statements) {
current = environment;
for (int i = 0; i < statements->size; i++) {
execute(exprlist_get(statements, i));
}
}
Value *visitVariable(Expression *var) { return var_get(current, var->name); }
Value *visitVariableStmt(Expression *var) {
Value *value = accept(var->left);
if (var_isdefined(current, var->name)) {
printf("%s is already defined\n", var->name);
return NULL;
}
var_add(current, var->name, value);
return NULL;
}
Value *visitBlock(Expression *blockStmt) {
VarMap *previous = current;
current = newVarMap(previous);
for (int i = 0; i < blockStmt->block->size; i++) {
Expression *e = exprlist_get(blockStmt->block, i);
execute(e);
}
current = previous;
return NULL;
}
Value *visitGroup(Expression *group) { return accept(group->left); }
Value *visitPrintStmt(Expression *printStatement) {
Value *value = accept(printStatement->left);
if (value == NULL) {
return NULL;
}
printf("%s\n", value_string(value));
return NULL;
}
Value *visitAssignStmt(Expression *var) {
Value *value = accept(var->left);
bool result = var_set(current, var->name, value);
if (!result) {
printf("%s is not defined", var->name);
}
return NULL;
}
Value *visitUnary(Expression *unary) {
Value *right = accept(unary->right);
switch (unary->operator->type) {
case MINUS:
return newNumber(-right->value.number);
case BANG:
return newBoolean(!right->value.boolean);
default:
return NULL;
};
}
Value *visitLiteral(Expression *literal) { return literal->value; }
Value *visitBinary(Expression *expr) {
Value *left = accept(expr->left);
Value *right = accept(expr->right);
switch (expr->operator->type) {
case MINUS:
checkNumeric(left, right);
return newNumber(left->value.number - right->value.number);
case PLUS:
checkNumeric(left, right);
return newNumber(left->value.number + right->value.number);
case SLASH:
checkNumeric(left, right);
return newNumber(left->value.number / right->value.number);
case STAR:
checkNumeric(left, right);
return newNumber(left->value.number * right->value.number);
case GREATER:
checkNumeric(left, right);
return newBoolean(left->value.number > right->value.number);
case GREATER_EQUAL:
checkNumeric(left, right);
return newBoolean(left->value.number >= right->value.number);
case LESS:
checkNumeric(left, right);
return newBoolean(left->value.number < right->value.number);
case LESS_EQUAL:
checkNumeric(left, right);
return newBoolean(left->value.number <= right->value.number);
case BANG_EQUAL:
return isEqual(left, right);
case EQUAL_EQUAL:
return isEqual(left, right);
default:
return NULL;
}
}
void checkNumeric(Value *left, Value *right) {
if (left->type != NUMBERTYPE || right->type != NUMBERTYPE) {
printf("operands should be numeric");
exit(-1);
}
}
VarMap *newVarMap(VarMap *enclosing) {
VarMap *map = malloc(sizeof(VarMap));
if (map == NULL) {
printf("Can not allocate memory for VarMap");
exit(1);
}
map->size = 0;
map->enclosing = enclosing;
return map;
}
bool var_isdefined(VarMap *map, const char *key) {
for (int i = 0; i < map->size; i++) {
if (strcmp(map->entries[i].key, key) == 0) {
return true;
}
}
if (map->enclosing != NULL) {
return var_isdefined(map->enclosing, key);
}
return false;
}
void var_add(VarMap *map, const char *key, Value *value) {
if (map->size == MAX_MAP_SIZE) {
printf("Map is full!\n");
return;
}
strcpy(map->entries[map->size].key, key);
map->entries[map->size].value = value;
map->size += 1;
}
bool var_set(VarMap *map, char *key, Value *value) {
for (int i = 0; i < map->size; i++) {
if (strcmp(map->entries[i].key, key) == 0) {
map->entries[i].value = value; // Return the value
return true;
}
}
return false;
}
Value *var_get(VarMap *map, const char *key) {
for (int i = 0; i < map->size; i++) {
if (strcmp(map->entries[i].key, key) == 0) {
return map->entries[i].value; // Return the value
}
}
if (map->enclosing != NULL) {
return var_get(map->enclosing, key);
}
printf("%s is not defined\n", key);
return NULL; // Key not found
}
Value *isEqual(Value *left, Value *right) {
if (left->type != right->type) {
return newBoolean(false);
}
switch (left->type) {
case STRINGTYPE:
return newBoolean(strcmp(left->value.string, right->value.string) == 0);
case NUMBERTYPE:
return newBoolean(left->value.number == right->value.number);
case BOOLEANTYPE:
return newBoolean(left->value.boolean == right->value.boolean);
case EXPR: // MUST NOT HAPPEN :(=)
return NULL;
}
}
bool streq(char *left, char *right) { return strcmp(left, right) == 0; }

28
src/interpreter.h Normal file
View file

@ -0,0 +1,28 @@
#ifndef INTERPRETER_H
#define INTERPRETER_H
#include "parser.h"
#define MAX_MAP_SIZE 1000
typedef struct VarMap VarMap;
VarMap *newVarMap(VarMap *enclosing);
void interpret(VarMap *environment, ExpressionList *statements);
typedef struct {
char key[50]; // Array of strings for keys
Value *value; // Integer values associated with keys
} MapEntry;
struct VarMap {
VarMap *enclosing;
MapEntry entries[MAX_MAP_SIZE]; // Array of key-value pairs
int size; // Current size of the map
};
bool var_isdefined(VarMap *map, const char *key);
void var_add(VarMap *map, const char *key, Value *value);
Value *var_get(VarMap *map, const char *key);
bool var_set(VarMap *map, char *key, Value *value);
#endif

View file

@ -1,3 +1,4 @@
#include "interpreter.h"
#include "parser.h" #include "parser.h"
#include "scanner.h" #include "scanner.h"
#include "utils.h" #include "utils.h"
@ -9,8 +10,11 @@
int run_file(char *file); int run_file(char *file);
void run_prompt(void); void run_prompt(void);
void run(char *source); void run(char *source);
static VarMap *environment;
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
environment = newVarMap(NULL);
setvbuf(stdout, NULL, _IONBF, 0); setvbuf(stdout, NULL, _IONBF, 0);
if (argc > 2) { if (argc > 2) {
puts("Usage: lox [script]"); puts("Usage: lox [script]");
@ -80,6 +84,7 @@ void run_prompt(void) {
void run(char *source) { void run(char *source) {
ScanResult scan_result = scan_tokens(source); ScanResult scan_result = scan_tokens(source);
// tokenlist_print(&scan_result.token_list); // tokenlist_print(&scan_result.token_list);
ExpressionList list = parse(&scan_result.token_list); ExpressionList *list = parse(&scan_result.token_list);
exprlist_print(&list); // exprlist_print(list);
interpret(environment, list);
} }

View file

@ -1,5 +1,4 @@
#include "parser.h" #include "parser.h"
#include "tokens.h"
#include <stdbool.h> #include <stdbool.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@ -7,8 +6,6 @@
bool is_at_end(void); bool is_at_end(void);
Token *peek(void); Token *peek(void);
size_t expr_toString(const Expression *expr, char *output, size_t outputSize,
size_t offset);
void expr_print(const Expression *expr); void expr_print(const Expression *expr);
Expression *declaration(void); Expression *declaration(void);
bool match1(TokenType t); bool match1(TokenType t);
@ -22,7 +19,7 @@ Expression *var_declaration(void);
Expression *expression(void); Expression *expression(void);
Expression *statement(void); Expression *statement(void);
Expression *printStatement(void); Expression *printStatement(void);
ExpressionList block(void); ExpressionList *parse_block(void);
Expression *expressionStatement(void); Expression *expressionStatement(void);
Expression *assignment(void); Expression *assignment(void);
Expression *equality(void); Expression *equality(void);
@ -37,15 +34,14 @@ Token *consume(TokenType type, char *message);
static TokenList *tokens; static TokenList *tokens;
static int current; static int current;
ExpressionList parse(TokenList *tokens_to_parse) { ExpressionList *parse(TokenList *tokens_to_parse) {
ExpressionList statements; ExpressionList *statements = newExpressionList();
exprlist_init(&statements);
tokens = tokens_to_parse; tokens = tokens_to_parse;
current = 0; current = 0;
while (!is_at_end()) { while (!is_at_end()) {
exprlist_add(&statements, declaration()); exprlist_add(statements, declaration());
} }
return statements; return statements;
} }
@ -60,12 +56,12 @@ Expression *declaration(void) {
Expression *var_declaration(void) { Expression *var_declaration(void) {
Token *name = consume(IDENTIFIER, "Expected a variable name"); Token *name = consume(IDENTIFIER, "Expected a variable name");
Expression *initializer; Expression *initializer = NULL;
if (match1(EQUAL)) { if (match1(EQUAL)) {
initializer = expression(); initializer = expression();
} }
consume(SEMICOLON, "Expected semicolon"); consume(SEMICOLON, "Expected semicolon");
Expression *variableStatement = newExpression("VariableStatement"); Expression *variableStatement = newExpression("VariableStmt");
variableStatement->name = name->lexeme; variableStatement->name = name->lexeme;
variableStatement->left = initializer; variableStatement->left = initializer;
return variableStatement; return variableStatement;
@ -76,24 +72,22 @@ Expression *statement(void) {
return printStatement(); return printStatement();
} }
if (match1(LEFT_BRACE)) { if (match1(LEFT_BRACE)) {
ExpressionList block_contents = block();
Expression *block = newExpression("Block"); Expression *block = newExpression("Block");
block->value = &block_contents;
ExpressionList *block_statements = newExpressionList();
while (!check(RIGHT_BRACE) && !is_at_end()) {
exprlist_add(block_statements, declaration());
}
advance();
block->block = block_statements;
return block; return block;
} }
return expressionStatement(); return expressionStatement();
} }
ExpressionList block(void) {
ExpressionList statements;
exprlist_init(&statements);
while (!check(RIGHT_BRACE) && !is_at_end()) {
exprlist_add(&statements, declaration());
}
return statements;
}
Expression *printStatement(void) { Expression *printStatement(void) {
Expression *value = expression(); Expression *value = expression();
consume(SEMICOLON, "Expected semicolon"); consume(SEMICOLON, "Expected semicolon");
@ -106,7 +100,7 @@ Expression *expressionStatement(void) {
Expression *value = expression(); Expression *value = expression();
consume(SEMICOLON, "Expected semicolon"); consume(SEMICOLON, "Expected semicolon");
Expression *statement = newExpression("ExprStmt"); Expression *statement = newExpression("ExprStmt");
statement->value = &value; statement->left = value;
return statement; return statement;
} }
@ -120,7 +114,7 @@ Expression *assignment(void) {
if (strcmp(expr->type, "Variable") == 0) { if (strcmp(expr->type, "Variable") == 0) {
Expression *assign = newExpression("AssignStmt"); Expression *assign = newExpression("AssignStmt");
assign->name = expr->name; assign->name = expr->name;
assign->value = &value; assign->left = value;
return assign; return assign;
} }
Expression *error = newExpression("Error"); Expression *error = newExpression("Error");
@ -201,13 +195,11 @@ Expression *unary(void) {
Expression *primary(void) { Expression *primary(void) {
Expression *r = newExpression("Literal"); Expression *r = newExpression("Literal");
if (match1(FALSE)) { if (match1(FALSE)) {
r->name = "boolean"; r->value = newBoolean(false);
r->value = "false";
return r; return r;
} }
if (match1(TRUE)) { if (match1(TRUE)) {
r->name = "boolean"; r->value = newBoolean(true);
r->value = "true";
return r; return r;
} }
@ -219,25 +211,24 @@ Expression *primary(void) {
if (check(NUMBER)) { if (check(NUMBER)) {
advance(); advance();
r->name = "number"; r->value = newNumber(strtod(previous()->literal, NULL));
r->value = previous()->literal;
return r; return r;
} }
if (check(STRING)) { if (check(STRING)) {
advance(); advance();
r->name = "string"; r->value = newString(previous()->literal);
r->value = previous()->literal;
return r; return r;
} }
if (match1(IDENTIFIER)) { if (match1(IDENTIFIER)) {
Expression *var = newExpression("Variable"); Expression *var = newExpression("Variable");
r->name = previous()->lexeme; var->name = previous()->lexeme;
return var; return var;
} }
if (match1(LEFT_PAREN)) { if (match1(LEFT_PAREN)) {
Expression *expr = expression();
Expression *group = newExpression("Group"); Expression *group = newExpression("Group");
consume(RIGHT_PAREN, "Expect ')' after expression."); consume(RIGHT_PAREN, "Expect ')' after expression.");
r->left = group; group->left = expr;
return group; return group;
} }
@ -246,10 +237,11 @@ Expression *primary(void) {
} }
Token *consume(TokenType type, char *message) { Token *consume(TokenType type, char *message) {
// printf("%s==%s\n", token_name(type), token_name(peek()->type));
if (check(type)) { if (check(type)) {
return advance(); return advance();
} }
printf("error\n");
Token *t = newToken(); Token *t = newToken();
t->type = ERROR; t->type = ERROR;
t->lexeme = message; t->lexeme = message;
@ -310,10 +302,21 @@ bool is_at_end(void) { return peek()->type == END_OF_FILE; }
Token *peek(void) { return tokenlist_get(tokens, current); } Token *peek(void) { return tokenlist_get(tokens, current); }
void exprlist_init(ExpressionList *list) { ExpressionList *newExpressionList() {
ExpressionList *list = malloc(sizeof(ExpressionList));
if (list == NULL) {
printf("Cannot allocate memory for ExpressionList");
exit(1);
}
list->expressions = malloc(sizeof(Expression) * 32); list->expressions = malloc(sizeof(Expression) * 32);
if (list->expressions == NULL) {
printf("Cannot allocate memory for ExpressionList");
exit(1);
}
list->size = 0; list->size = 0;
list->capacity = 32; list->capacity = 32;
return list;
} }
void exprlist_add(ExpressionList *list, Expression *value) { void exprlist_add(ExpressionList *list, Expression *value) {
@ -322,8 +325,7 @@ void exprlist_add(ExpressionList *list, Expression *value) {
list->expressions = list->expressions =
realloc(list->expressions, sizeof(Expression) * list->capacity); realloc(list->expressions, sizeof(Expression) * list->capacity);
} }
list->expressions[list->size] = value; list->expressions[list->size++] = value;
list->size += 1;
} }
Expression *exprlist_get(ExpressionList *list, int index) { Expression *exprlist_get(ExpressionList *list, int index) {
@ -359,15 +361,13 @@ void expr_print(const Expression *expr) {
} }
if (expr->name != NULL) { if (expr->name != NULL) {
printf(", name: %s", expr->name); printf(", name: %s", expr->name);
if (strcmp(expr->name, "string") == 0 ||
strcmp(expr->name, "number") == 0 ||
strcmp(expr->name, "boolean") == 0) {
printf(", value: %s", (char *)expr->value);
}
if (strcmp(expr->name, "nil") == 0 && expr->value == NULL) { if (strcmp(expr->name, "nil") == 0 && expr->value == NULL) {
printf(", value: NULL"); printf(", value: NULL");
} }
} }
if (expr->value != NULL) {
printf(", value: %s", value_string(expr->value));
}
printf("]"); printf("]");
} }
@ -379,5 +379,59 @@ Expression *newExpression(char *type) {
e->name = NULL; e->name = NULL;
e->operator= NULL; e->operator= NULL;
e->value = NULL; e->value = NULL;
e->block = NULL;
return e; return e;
} }
Value *newString(char *string) {
Value *value = newValue();
value->type = STRINGTYPE;
value->value.string = string;
return value;
}
Value *newBoolean(bool boolean) {
Value *value = newValue();
value->type = BOOLEANTYPE;
value->value.boolean = boolean;
return value;
}
Value *newNumber(double number) {
Value *value = newValue();
value->type = NUMBERTYPE;
value->value.number = number;
return value;
}
Value *newValue(void) {
Value *value = malloc(sizeof(Value));
if (value == NULL) {
printf("can't allocate memory for Value");
exit(1);
}
return value;
}
char *d_to_s(double d) {
char *str = (char *)malloc(50);
if (str == NULL) {
puts("cannot allocate memory for string");
exit(1);
}
snprintf(str, sizeof(str), "%lf", d); //
return str;
}
const char *value_string(Value *v) {
switch (v->type) {
case STRINGTYPE:
return v->value.string;
case BOOLEANTYPE:
return v->value.boolean ? "true" : "false";
case NUMBERTYPE:
return d_to_s(v->value.number);
case EXPR:
return v->value.expr->type;
}
}

View file

@ -1,6 +1,24 @@
#ifndef PARSER_H
#define PARSER_H
#include "tokens.h" #include "tokens.h"
typedef struct Expression Expression; typedef struct Expression Expression;
typedef struct ExpressionList ExpressionList;
typedef union ValueHolder {
double number;
char *string;
bool boolean;
Expression *expr;
} ValueHolder;
typedef enum { NUMBERTYPE, STRINGTYPE, BOOLEANTYPE, EXPR } Type;
typedef struct Value {
Type type;
ValueHolder value;
} Value;
struct Expression { struct Expression {
char *type; char *type;
@ -8,7 +26,8 @@ struct Expression {
Expression *right; Expression *right;
Token *operator; Token *operator;
char *name; char *name;
void *value; Value *value;
ExpressionList *block;
}; };
typedef struct ExpressionList { typedef struct ExpressionList {
@ -17,9 +36,15 @@ typedef struct ExpressionList {
int capacity; int capacity;
} ExpressionList; } ExpressionList;
ExpressionList parse(TokenList *tokens); const char *value_string(Value *v);
Value *newValue(void);
Value *newString(char *string);
Value *newNumber(double number);
Value *newBoolean(bool boolean);
void exprlist_init(ExpressionList *list); ExpressionList *parse(TokenList *tokens);
ExpressionList *newExpressionList();
// void exprlist_init(ExpressionList *list);
void exprlist_add(ExpressionList *list, Expression *value); void exprlist_add(ExpressionList *list, Expression *value);
@ -28,3 +53,4 @@ Expression *exprlist_get(ExpressionList *list, int index);
void exprlist_print(ExpressionList *list); void exprlist_print(ExpressionList *list);
void exprlist_free(ExpressionList *list); void exprlist_free(ExpressionList *list);
#endif

View file

@ -109,6 +109,9 @@ static void scan_token(void) {
case '-': case '-':
add_token(MINUS); add_token(MINUS);
break; break;
case '*':
add_token(STAR);
break;
case '!': case '!':
add_token(match('=') ? BANG_EQUAL : BANG); add_token(match('=') ? BANG_EQUAL : BANG);
break; break;

View file

@ -1,11 +1,12 @@
#include "tokens.h" #include "tokens.h"
#include <stdbool.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
Token *newToken() { Token *newToken(void) {
Token *token = malloc(sizeof(Token)); Token *token = malloc(sizeof(Token));
if (token == NULL) { if (token == NULL) {
printf("can't allocate memory"); printf("can't allocate memory for Token");
exit(1); exit(1);
} }
return token; return token;
@ -13,6 +14,10 @@ Token *newToken() {
void tokenlist_init(TokenList *list) { void tokenlist_init(TokenList *list) {
list->tokens = malloc(sizeof(Token) * 32); list->tokens = malloc(sizeof(Token) * 32);
if (list->tokens == NULL) {
printf("Cannot allocate memory for TokenList");
exit(1);
}
list->size = 0; list->size = 0;
list->capacity = 32; list->capacity = 32;
} }
@ -39,12 +44,7 @@ Token *tokenlist_last(TokenList *list) { return list->tokens[list->size - 1]; }
void tokenlist_print(TokenList *tokenlist) { void tokenlist_print(TokenList *tokenlist) {
for (int i = 0; i < tokenlist->size; i++) { for (int i = 0; i < tokenlist->size; i++) {
Token *token = tokenlist_get(tokenlist, i); Token *token = tokenlist_get(tokenlist, i);
if (token->literal != NULL) { printf("%s(%s)", token_name(token->type), token->lexeme);
printf("%s(x:%s,l:%s), ", token_name(token->type), token->lexeme,
(char *)token->literal);
} else {
printf("%s(l:%s)", token_name(token->type), token->lexeme);
}
} }
printf("\n"); printf("\n");
} }

View file

@ -1,5 +1,8 @@
#ifndef TOKENS_H #ifndef TOKENS_H
#define TOKENS_H #define TOKENS_H
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
typedef enum { typedef enum {
LEFT_PAREN, LEFT_PAREN,
@ -58,10 +61,10 @@ static inline const char *token_name(TokenType type) {
return tokens[type]; return tokens[type];
} }
typedef struct { typedef struct Token {
TokenType type; TokenType type;
char *lexeme; char *lexeme;
void *literal; char *literal;
int line; int line;
} Token; } Token;
@ -71,7 +74,7 @@ typedef struct TokenList {
int capacity; int capacity;
} TokenList; } TokenList;
Token *newToken(); Token *newToken(void);
void tokenlist_init(TokenList *list); void tokenlist_init(TokenList *list);

View file

@ -1,19 +1,21 @@
#include <stdlib.h> #include "utils.h"
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* substring(char* string, int position, int length){ char *substring(char *string, int position, int length) {
char* ptr = malloc(length+1); char *ptr = malloc(length + 1);
if (ptr == NULL) { if (ptr == NULL) {
printf("out of memory"); printf("out of memory");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
int c; int c;
for (c=0; c < length; c+=1){ for (c = 0; c < length; c += 1) {
*(ptr+c) = *(string+position-1); *(ptr + c) = *(string + position - 1);
string += sizeof(char); string += sizeof(char);
} }
*(ptr+c) = '\0'; *(ptr + c) = '\0';
return ptr; return ptr;
} }

View file

@ -1,6 +1,6 @@
#ifndef UTILS_H #ifndef UTILS_H
#define UTILS_H #define UTILS_H
char* substring(char* string, int position, int length); char *substring(char *string, int position, int length);
#endif #endif