feature: added error diagnostics and the ability to parse multiple files
This commit is contained in:
parent
fc80e23917
commit
472a4a623c
|
@ -5,7 +5,7 @@
|
||||||
#include <sys/log.h>
|
#include <sys/log.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
struct AST_Node_t *AST_new_node(enum AST_SyntaxElement_t kind, const char* value) {
|
struct AST_Node_t *AST_new_node(TokenLocation location, enum AST_SyntaxElement_t kind, const char* value) {
|
||||||
DEBUG("creating new AST node: %d \"%s\"", kind, value);
|
DEBUG("creating new AST node: %d \"%s\"", kind, value);
|
||||||
assert(kind < AST_ELEMENT_COUNT);
|
assert(kind < AST_ELEMENT_COUNT);
|
||||||
|
|
||||||
|
@ -23,6 +23,7 @@ struct AST_Node_t *AST_new_node(enum AST_SyntaxElement_t kind, const char* value
|
||||||
node->child_count = 0;
|
node->child_count = 0;
|
||||||
node->kind = kind;
|
node->kind = kind;
|
||||||
node->value = value;
|
node->value = value;
|
||||||
|
node->location = location;
|
||||||
|
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
@ -114,6 +115,14 @@ const char* AST_node_to_string(const struct AST_Node_t* node) {
|
||||||
return string;
|
return string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline unsigned long int min(unsigned long int a, unsigned long int b) {
|
||||||
|
return a > b ? b : a;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline unsigned long int max(unsigned long int a, unsigned long int b) {
|
||||||
|
return a > b ? a : b;
|
||||||
|
}
|
||||||
|
|
||||||
void AST_push_node(struct AST_Node_t *owner, struct AST_Node_t *child) {
|
void AST_push_node(struct AST_Node_t *owner, struct AST_Node_t *child) {
|
||||||
DEBUG("Adding new node %p to %p", child, owner);
|
DEBUG("Adding new node %p to %p", child, owner);
|
||||||
assert(owner != NULL);
|
assert(owner != NULL);
|
||||||
|
@ -134,6 +143,12 @@ void AST_push_node(struct AST_Node_t *owner, struct AST_Node_t *child) {
|
||||||
PANIC("failed to allocate children array of AST node");
|
PANIC("failed to allocate children array of AST node");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
owner->location.col_end = max(owner->location.col_end, child->location.col_end);
|
||||||
|
owner->location.line_end = max(owner->location.line_end, child->location.line_end);
|
||||||
|
|
||||||
|
owner->location.col_start = min(owner->location.col_start, child->location.col_start);
|
||||||
|
owner->location.line_start = min(owner->location.line_start, child->location.line_start);
|
||||||
|
|
||||||
assert(owner->children != NULL);
|
assert(owner->children != NULL);
|
||||||
|
|
||||||
owner->children[owner->child_count++] = child;
|
owner->children[owner->child_count++] = child;
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#define _AST_H_
|
#define _AST_H_
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <io/files.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The type of a AST node
|
* @brief The type of a AST node
|
||||||
|
@ -94,6 +95,8 @@ struct AST_Node_t {
|
||||||
// optional value: integer literal, string literal, ...
|
// optional value: integer literal, string literal, ...
|
||||||
const char* value;
|
const char* value;
|
||||||
|
|
||||||
|
TokenLocation location;
|
||||||
|
|
||||||
// number of child nodes ownd by this node
|
// number of child nodes ownd by this node
|
||||||
// length of children array
|
// length of children array
|
||||||
size_t child_count;
|
size_t child_count;
|
||||||
|
@ -133,7 +136,7 @@ const char* AST_node_to_string(const struct AST_Node_t* node);
|
||||||
[[maybe_unused]]
|
[[maybe_unused]]
|
||||||
[[nodiscard("pointer must be freed")]]
|
[[nodiscard("pointer must be freed")]]
|
||||||
[[gnu::returns_nonnull]]
|
[[gnu::returns_nonnull]]
|
||||||
struct AST_Node_t *AST_new_node(enum AST_SyntaxElement_t kind, const char* value);
|
struct AST_Node_t *AST_new_node(TokenLocation location, enum AST_SyntaxElement_t kind, const char* value);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Deallocate this node and all of its children.
|
* @brief Deallocate this node and all of its children.
|
||||||
|
|
|
@ -0,0 +1,224 @@
|
||||||
|
//
|
||||||
|
// Created by servostar on 5/30/24.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <io/files.h>
|
||||||
|
#include <sys/log.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <sys/col.h>
|
||||||
|
|
||||||
|
ModuleFile *push_file(ModuleFileStack *stack, const char *path) {
|
||||||
|
assert(stack != NULL);
|
||||||
|
|
||||||
|
// lazy init of heap stack
|
||||||
|
if (stack->files == NULL) {
|
||||||
|
stack->files = g_array_new(FALSE, FALSE, sizeof(ModuleFile));
|
||||||
|
}
|
||||||
|
|
||||||
|
ModuleFile new_file = {
|
||||||
|
.path = path,
|
||||||
|
.handle = NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
g_array_append_val(stack->files, new_file);
|
||||||
|
|
||||||
|
return ((ModuleFile *) stack->files->data) + stack->files->len - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void delete_files(ModuleFileStack *stack) {
|
||||||
|
for (size_t i = 0; i < stack->files->len; i++) {
|
||||||
|
ModuleFile *file = ((ModuleFile *) stack->files->data) + i;
|
||||||
|
|
||||||
|
if (file->handle != NULL) {
|
||||||
|
DEBUG("closing file: %s", file->path);
|
||||||
|
fclose(file->handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
g_array_free(stack->files, TRUE);
|
||||||
|
DEBUG("deleted module file stack");
|
||||||
|
}
|
||||||
|
|
||||||
|
#define SEEK_BUF_BYTES 256
|
||||||
|
|
||||||
|
static inline unsigned long int min(unsigned long int a, unsigned long int b) {
|
||||||
|
return a > b ? b : a;
|
||||||
|
}
|
||||||
|
|
||||||
|
// behaves like fgets except that it has defined behavior when n == 1
|
||||||
|
static void custom_fgets(char *buffer, size_t n, FILE *stream) {
|
||||||
|
if (n == 1) {
|
||||||
|
buffer[0] = (char) fgetc(stream);
|
||||||
|
buffer[1] = 0;
|
||||||
|
} else {
|
||||||
|
fgets(buffer, (int) n, stream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_diagnostic(ModuleFile *file, TokenLocation *location, Message kind, const char *message) {
|
||||||
|
assert(file->handle != NULL);
|
||||||
|
assert(location != NULL);
|
||||||
|
assert(message != NULL);
|
||||||
|
|
||||||
|
// reset to start
|
||||||
|
rewind(file->handle);
|
||||||
|
|
||||||
|
char *buffer = alloca(SEEK_BUF_BYTES);
|
||||||
|
unsigned long int line_count = 1;
|
||||||
|
|
||||||
|
// seek to first line
|
||||||
|
while (line_count < location->line_start && fgets(buffer, SEEK_BUF_BYTES, file->handle) != NULL) {
|
||||||
|
line_count += strchr(buffer, '\n') != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *accent_color = RESET;
|
||||||
|
const char *kind_text = "unknown";
|
||||||
|
switch (kind) {
|
||||||
|
case Info:
|
||||||
|
kind_text = "info";
|
||||||
|
accent_color = CYAN;
|
||||||
|
file->statistics.info_count++;
|
||||||
|
break;
|
||||||
|
case Warning:
|
||||||
|
kind_text = "warning";
|
||||||
|
accent_color = YELLOW;
|
||||||
|
file->statistics.warning_count++;
|
||||||
|
break;
|
||||||
|
case Error:
|
||||||
|
kind_text = "error";
|
||||||
|
accent_color = RED;
|
||||||
|
file->statistics.error_count++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
char absolute_path[PATH_MAX];
|
||||||
|
realpath(file->path, absolute_path);
|
||||||
|
|
||||||
|
printf("%s%s:%ld:%s %s%s:%s %s\n", BOLD, absolute_path, location->line_start, RESET, accent_color, kind_text, RESET,
|
||||||
|
message);
|
||||||
|
|
||||||
|
size_t lines = location->line_end - location->line_start + 1;
|
||||||
|
|
||||||
|
for (size_t l = 0; l < lines; l++) {
|
||||||
|
printf(" %4ld | ", location->line_start + l);
|
||||||
|
|
||||||
|
size_t limit;
|
||||||
|
size_t chars = 0;
|
||||||
|
|
||||||
|
// print line before token group start
|
||||||
|
limit = min(location->col_start, SEEK_BUF_BYTES);
|
||||||
|
while (limit > 1) {
|
||||||
|
custom_fgets(buffer, (int) limit, file->handle);
|
||||||
|
chars += printf("%s", buffer);
|
||||||
|
limit = min(location->col_start - chars, SEEK_BUF_BYTES);
|
||||||
|
|
||||||
|
if (strchr(buffer, '\n') != NULL) {
|
||||||
|
goto cont;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("%s", accent_color);
|
||||||
|
|
||||||
|
chars = 0;
|
||||||
|
limit = min(location->col_end - location->col_start + 1, SEEK_BUF_BYTES);
|
||||||
|
while (limit > 0) {
|
||||||
|
custom_fgets(buffer, (int) limit, file->handle);
|
||||||
|
chars += printf("%s", buffer);
|
||||||
|
limit = min(location->col_end - location->col_start + 1 - chars, SEEK_BUF_BYTES);
|
||||||
|
|
||||||
|
if (strchr(buffer, '\n') != NULL) {
|
||||||
|
goto cont;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("%s", RESET);
|
||||||
|
|
||||||
|
// print rest of the line
|
||||||
|
do {
|
||||||
|
custom_fgets(buffer, SEEK_BUF_BYTES, file->handle);
|
||||||
|
printf("%s", buffer);
|
||||||
|
} while (strchr(buffer, '\n') == NULL);
|
||||||
|
|
||||||
|
cont:
|
||||||
|
printf("%s", RESET);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf(" | ");
|
||||||
|
for (size_t i = 1; i < location->col_start; i++) {
|
||||||
|
printf(" ");
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("%s", accent_color);
|
||||||
|
printf("^");
|
||||||
|
for (size_t i = 0; i < location->col_end - location->col_start; i++) {
|
||||||
|
printf("~");
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("%s\n\n", RESET);
|
||||||
|
}
|
||||||
|
|
||||||
|
TokenLocation new_location(unsigned long int line_start, unsigned long int col_start, unsigned long int line_end,
|
||||||
|
unsigned long int col_end) {
|
||||||
|
TokenLocation location;
|
||||||
|
|
||||||
|
location.line_start = line_start;
|
||||||
|
location.line_end = line_end;
|
||||||
|
location.col_start = col_start;
|
||||||
|
location.col_end = col_end;
|
||||||
|
|
||||||
|
return location;
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_file_statistics(ModuleFile *file) {
|
||||||
|
if (file->statistics.info_count + file->statistics.warning_count + file->statistics.error_count < 1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("File %s generated ", file->path);
|
||||||
|
|
||||||
|
if (file->statistics.info_count > 0) {
|
||||||
|
printf("%ld notice(s) ", file->statistics.info_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (file->statistics.warning_count > 0) {
|
||||||
|
printf("%ld warning(s) ", file->statistics.warning_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (file->statistics.error_count > 0) {
|
||||||
|
printf("%ld error(s) ", file->statistics.error_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\n\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_unit_statistics(ModuleFileStack *file_stack) {
|
||||||
|
FileDiagnosticStatistics stats;
|
||||||
|
stats.info_count = 0;
|
||||||
|
stats.warning_count = 0;
|
||||||
|
stats.error_count = 0;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < file_stack->files->len; i++) {
|
||||||
|
ModuleFile *file = (ModuleFile *) file_stack->files->data;
|
||||||
|
|
||||||
|
stats.info_count += file->statistics.warning_count;
|
||||||
|
stats.warning_count += file->statistics.warning_count;
|
||||||
|
stats.error_count += file->statistics.error_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("%d files generated ", file_stack->files->len);
|
||||||
|
|
||||||
|
if (stats.info_count > 0) {
|
||||||
|
printf("%ld notice(s) ", stats.info_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stats.warning_count > 0) {
|
||||||
|
printf("%ld warning(s) ", stats.warning_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stats.error_count > 0) {
|
||||||
|
printf("%ld error(s) ", stats.error_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\n\n");
|
||||||
|
}
|
|
@ -0,0 +1,77 @@
|
||||||
|
//
|
||||||
|
// Created by servostar on 5/30/24.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef GEMSTONE_FILES_H
|
||||||
|
#define GEMSTONE_FILES_H
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <glib.h>
|
||||||
|
|
||||||
|
typedef struct FileDiagnosticStatistics_t {
|
||||||
|
size_t error_count;
|
||||||
|
size_t warning_count;
|
||||||
|
size_t info_count;
|
||||||
|
} FileDiagnosticStatistics;
|
||||||
|
|
||||||
|
typedef struct ModuleFile_t {
|
||||||
|
const char *path;
|
||||||
|
FILE *handle;
|
||||||
|
FileDiagnosticStatistics statistics;
|
||||||
|
} ModuleFile;
|
||||||
|
|
||||||
|
typedef struct ModuleFileStack_t {
|
||||||
|
GArray *files;
|
||||||
|
} ModuleFileStack;
|
||||||
|
|
||||||
|
typedef enum Message_t {
|
||||||
|
Info,
|
||||||
|
Warning,
|
||||||
|
Error
|
||||||
|
} Message;
|
||||||
|
|
||||||
|
typedef struct TokenLocation_t {
|
||||||
|
unsigned long int line_start;
|
||||||
|
unsigned long int col_start;
|
||||||
|
unsigned long int line_end;
|
||||||
|
unsigned long int col_end;
|
||||||
|
} TokenLocation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Add a new file to the file stack.
|
||||||
|
* @attention The file handle returned will be invalid
|
||||||
|
* @param stack
|
||||||
|
* @param path
|
||||||
|
* @return A new file module
|
||||||
|
*/
|
||||||
|
[[gnu::nonnull(1), gnu::nonnull(2)]]
|
||||||
|
ModuleFile *push_file(ModuleFileStack *stack, const char *path);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Delete all files in the stack and the stack itself
|
||||||
|
* @param stack
|
||||||
|
*/
|
||||||
|
[[gnu::nonnull(1)]]
|
||||||
|
void delete_files(ModuleFileStack *stack);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new token location
|
||||||
|
* @param line_start
|
||||||
|
* @param col_start
|
||||||
|
* @param line_end
|
||||||
|
* @param col_end
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
TokenLocation new_location(unsigned long int line_start, unsigned long int col_start, unsigned long int line_end,
|
||||||
|
unsigned long int col_end);
|
||||||
|
|
||||||
|
[[gnu::nonnull(1), gnu::nonnull(2)]]
|
||||||
|
void print_diagnostic(ModuleFile *file, TokenLocation *location, Message kind, const char *message);
|
||||||
|
|
||||||
|
[[gnu::nonnull(1)]]
|
||||||
|
void print_file_statistics(ModuleFile *file);
|
||||||
|
|
||||||
|
[[gnu::nonnull(1)]]
|
||||||
|
void print_unit_statistics(ModuleFileStack *file_stack);
|
||||||
|
|
||||||
|
#endif //GEMSTONE_FILES_H
|
|
@ -25,6 +25,16 @@ void lex_init(void) {
|
||||||
atexit(lex_deinit);
|
atexit(lex_deinit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void lex_reset(void) {
|
||||||
|
eof = 0;
|
||||||
|
nRow = 0;
|
||||||
|
nBuffer = 0;
|
||||||
|
lBuffer = 0;
|
||||||
|
nTokenStart = 0;
|
||||||
|
nTokenLength = 0;
|
||||||
|
nTokenNextStart = 0;
|
||||||
|
}
|
||||||
|
|
||||||
void beginToken(char *t) {
|
void beginToken(char *t) {
|
||||||
nTokenStart = nTokenNextStart;
|
nTokenStart = nTokenNextStart;
|
||||||
nTokenLength = (int) strlen(t);
|
nTokenLength = (int) strlen(t);
|
||||||
|
|
|
@ -16,6 +16,8 @@ extern char* buffer;
|
||||||
*/
|
*/
|
||||||
void lex_init(void);
|
void lex_init(void);
|
||||||
|
|
||||||
|
void lex_reset(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Begin counting a new token. This will fill the global struct yylloc.
|
* @brief Begin counting a new token. This will fill the global struct yylloc.
|
||||||
* @param t the text of the token. Must be null terminated
|
* @param t the text of the token. Must be null terminated
|
||||||
|
|
116
src/main.c
116
src/main.c
|
@ -4,11 +4,52 @@
|
||||||
#include <yacc/parser.tab.h>
|
#include <yacc/parser.tab.h>
|
||||||
#include <sys/col.h>
|
#include <sys/col.h>
|
||||||
#include <lex/util.h>
|
#include <lex/util.h>
|
||||||
|
#include <io/files.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
#define LOG_LEVEL LOG_LEVEL_DEBUG
|
extern void yyrestart(FILE *);
|
||||||
|
|
||||||
extern FILE *yyin;
|
[[maybe_unused]]
|
||||||
AST_NODE_PTR root;
|
AST_NODE_PTR root;
|
||||||
|
[[maybe_unused]]
|
||||||
|
ModuleFile *current_file;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Compile the specified file into AST
|
||||||
|
* @param ast
|
||||||
|
* @param file
|
||||||
|
* @return EXIT_SUCCESS in case the parsing was success full anything lese if not
|
||||||
|
*/
|
||||||
|
[[nodiscard("AST may be in invalid state")]]
|
||||||
|
[[gnu::nonnull(1), gnu::nonnull(1)]]
|
||||||
|
static size_t compile_file_to_ast(AST_NODE_PTR ast, ModuleFile *file) {
|
||||||
|
assert(file->path != NULL);
|
||||||
|
assert(ast != NULL);
|
||||||
|
|
||||||
|
file->handle = fopen(file->path, "r");
|
||||||
|
|
||||||
|
if (file->handle == NULL) {
|
||||||
|
INFO("unable to open file: %s", file->path);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUG("parsing file: %s", file->path);
|
||||||
|
// setup global state
|
||||||
|
root = ast;
|
||||||
|
current_file = file;
|
||||||
|
yyin = file->handle;
|
||||||
|
yyrestart(yyin);
|
||||||
|
lex_reset();
|
||||||
|
|
||||||
|
yyparse();
|
||||||
|
|
||||||
|
// clean up global state
|
||||||
|
// current_file = NULL;
|
||||||
|
root = NULL;
|
||||||
|
yyin = NULL;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Log a debug message to inform about beginning exit procedures
|
* @brief Log a debug message to inform about beginning exit procedures
|
||||||
|
@ -22,9 +63,9 @@ void notify_exit(void) { DEBUG("Exiting gemstone..."); }
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void close_file(void) {
|
void close_file(void) {
|
||||||
if (NULL != yyin) {
|
if (NULL != yyin) {
|
||||||
fclose(yyin);
|
fclose(yyin);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -32,52 +73,57 @@ void close_file(void) {
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void setup(void) {
|
void setup(void) {
|
||||||
// setup preample
|
// setup preample
|
||||||
|
|
||||||
log_init();
|
log_init();
|
||||||
DEBUG("starting gemstone...");
|
DEBUG("starting gemstone...");
|
||||||
|
|
||||||
#if LOG_LEVEL <= LOG_LEVEL_DEBUG
|
#if LOG_LEVEL <= LOG_LEVEL_DEBUG
|
||||||
atexit(¬ify_exit);
|
atexit(¬ify_exit);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// actual setup
|
// actual setup
|
||||||
AST_init();
|
AST_init();
|
||||||
|
|
||||||
col_init();
|
col_init();
|
||||||
|
|
||||||
lex_init();
|
lex_init();
|
||||||
|
|
||||||
DEBUG("finished starting up gemstone...");
|
DEBUG("finished starting up gemstone...");
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
|
|
||||||
setup();
|
setup();
|
||||||
atexit(close_file);
|
atexit(close_file);
|
||||||
|
|
||||||
// Check for file input as argument
|
ModuleFileStack files;
|
||||||
if (2 != argc) {
|
files.files = NULL;
|
||||||
INFO("Usage: %s <filename>\n", argv[0]);
|
|
||||||
PANIC("No File could be found");
|
|
||||||
}
|
|
||||||
|
|
||||||
// filename as first argument
|
for (int i = 1; i < argc; i++) {
|
||||||
char *filename = argv[1];
|
printf("Compiling file: %s\n\n", argv[i]);
|
||||||
|
|
||||||
FILE *file = fopen(filename, "r");
|
TokenLocation location = {
|
||||||
|
.line_start = 0,
|
||||||
|
.line_end = 0,
|
||||||
|
.col_start = 0,
|
||||||
|
.col_end = 0
|
||||||
|
};
|
||||||
|
AST_NODE_PTR ast = AST_new_node(location, AST_Module, NULL);
|
||||||
|
ModuleFile *file = push_file(&files, argv[i]);
|
||||||
|
|
||||||
if (NULL == file) {
|
if (compile_file_to_ast(ast, file) == EXIT_SUCCESS) {
|
||||||
PANIC("File couldn't be opened!");
|
// TODO: parse AST to semantic values
|
||||||
}
|
// TODO: backend codegen
|
||||||
yyin = file;
|
}
|
||||||
|
|
||||||
root = AST_new_node(AST_Module, NULL);
|
AST_delete_node(ast);
|
||||||
yyparse();
|
|
||||||
|
|
||||||
FILE *output = fopen("test.txt", "w");
|
print_file_statistics(file);
|
||||||
AST_fprint_graphviz(output, root);
|
}
|
||||||
fclose(output);
|
|
||||||
AST_delete_node(root);
|
print_unit_statistics(&files);
|
||||||
return 0;
|
|
||||||
|
delete_files(&files);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
#define LOG_LEVEL_INFORMATION 1
|
#define LOG_LEVEL_INFORMATION 1
|
||||||
#define LOG_LEVEL_DEBUG 0
|
#define LOG_LEVEL_DEBUG 0
|
||||||
|
|
||||||
#define LOG_LEVEL LOG_LEVEL_DEBUG
|
#define LOG_LEVEL LOG_LEVEL_ERROR
|
||||||
|
|
||||||
#define LOG_STRING_PANIC "Critical"
|
#define LOG_STRING_PANIC "Critical"
|
||||||
#define LOG_STRING_FATAL "Fatal"
|
#define LOG_STRING_FATAL "Fatal"
|
||||||
|
|
|
@ -5,8 +5,9 @@
|
||||||
#include <sys/log.h>
|
#include <sys/log.h>
|
||||||
#include <ast/ast.h>
|
#include <ast/ast.h>
|
||||||
#include <sys/col.h>
|
#include <sys/col.h>
|
||||||
|
#include <io/files.h>
|
||||||
extern int yylineno;
|
extern int yylineno;
|
||||||
|
extern ModuleFile* current_file;
|
||||||
|
|
||||||
int yyerror(const char*);
|
int yyerror(const char*);
|
||||||
|
|
||||||
|
@ -16,6 +17,7 @@
|
||||||
extern int yylex();
|
extern int yylex();
|
||||||
extern AST_NODE_PTR root;
|
extern AST_NODE_PTR root;
|
||||||
|
|
||||||
|
#define new_loc() new_location(yylloc.first_line, yylloc.first_column, yylloc.last_line, yylloc.last_column)
|
||||||
}
|
}
|
||||||
|
|
||||||
%union {
|
%union {
|
||||||
|
@ -144,11 +146,11 @@ programbody: moduleimport {$$ = $1;}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
expr: ValFloat {$$ = AST_new_node(AST_Float, $1);}
|
expr: ValFloat {$$ = AST_new_node(new_loc(), AST_Float, $1);}
|
||||||
| ValInt {$$ = AST_new_node(AST_Int, $1);}
|
| ValInt {$$ = AST_new_node(new_loc(), AST_Int, $1);}
|
||||||
| ValMultistr {$$ = AST_new_node(AST_String, $1);}
|
| ValMultistr {$$ = AST_new_node(new_loc(), AST_String, $1);}
|
||||||
| ValStr {$$ = AST_new_node(AST_String, $1);}
|
| ValStr {$$ = AST_new_node(new_loc(), AST_String, $1);}
|
||||||
| Ident {$$ = AST_new_node(AST_Ident, $1);}
|
| Ident {$$ = AST_new_node(new_loc(), AST_Ident, $1);}
|
||||||
| operation {$$ = $1;}
|
| operation {$$ = $1;}
|
||||||
| boxaccess {$$ = $1;}
|
| boxaccess {$$ = $1;}
|
||||||
| boxselfaccess{$$ = $1;}
|
| boxselfaccess{$$ = $1;}
|
||||||
|
@ -157,22 +159,22 @@ expr: ValFloat {$$ = AST_new_node(AST_Float, $1);}
|
||||||
|
|
||||||
exprlist: expr ',' exprlist {AST_push_node($3, $1);
|
exprlist: expr ',' exprlist {AST_push_node($3, $1);
|
||||||
$$ = $3;}
|
$$ = $3;}
|
||||||
| expr {AST_NODE_PTR list = AST_new_node(AST_ExprList, NULL);
|
| expr {AST_NODE_PTR list = AST_new_node(new_loc(), AST_ExprList, NULL);
|
||||||
AST_push_node(list, $1);
|
AST_push_node(list, $1);
|
||||||
$$ = list;};
|
$$ = list;};
|
||||||
|
|
||||||
argumentlist: argumentlist '(' exprlist ')' {AST_push_node($1, $3);
|
argumentlist: argumentlist '(' exprlist ')' {AST_push_node($1, $3);
|
||||||
$$ = $1;}
|
$$ = $1;}
|
||||||
| '(' exprlist ')'{AST_NODE_PTR list = AST_new_node(AST_ArgList, NULL);
|
| '(' exprlist ')'{AST_NODE_PTR list = AST_new_node(new_loc(), AST_ArgList, NULL);
|
||||||
AST_push_node(list, $2);
|
AST_push_node(list, $2);
|
||||||
$$ = list;}
|
$$ = list;}
|
||||||
| argumentlist '(' ')'
|
| argumentlist '(' ')'
|
||||||
| '(' ')'{AST_NODE_PTR list = AST_new_node(AST_ArgList, NULL);
|
| '(' ')'{AST_NODE_PTR list = AST_new_node(new_loc(), AST_ArgList, NULL);
|
||||||
$$ = list;};
|
$$ = list;};
|
||||||
|
|
||||||
|
|
||||||
fundef: KeyFun Ident paramlist '{' statementlist'}' {AST_NODE_PTR fun = AST_new_node(AST_Fun, NULL);
|
fundef: KeyFun Ident paramlist '{' statementlist'}' {AST_NODE_PTR fun = AST_new_node(new_loc(), AST_Fun, NULL);
|
||||||
AST_NODE_PTR ident = AST_new_node(AST_Ident, $2);
|
AST_NODE_PTR ident = AST_new_node(new_loc(), AST_Ident, $2);
|
||||||
AST_push_node(fun, ident);
|
AST_push_node(fun, ident);
|
||||||
AST_push_node(fun, $3);
|
AST_push_node(fun, $3);
|
||||||
AST_push_node(fun, $5);
|
AST_push_node(fun, $5);
|
||||||
|
@ -182,66 +184,66 @@ fundef: KeyFun Ident paramlist '{' statementlist'}' {AST_NODE_PTR fun = AST_new_
|
||||||
paramlist: paramlist '(' params ')' {AST_push_node($1, $3);
|
paramlist: paramlist '(' params ')' {AST_push_node($1, $3);
|
||||||
$$ = $1;}
|
$$ = $1;}
|
||||||
| paramlist '(' ')'{$$ = $1;}
|
| paramlist '(' ')'{$$ = $1;}
|
||||||
| '(' params ')' {AST_NODE_PTR list = AST_new_node(AST_List, NULL);
|
| '(' params ')' {AST_NODE_PTR list = AST_new_node(new_loc(), AST_List, NULL);
|
||||||
AST_push_node(list, $2);
|
AST_push_node(list, $2);
|
||||||
$$ = list;}
|
$$ = list;}
|
||||||
| '(' ')' {$$ = AST_new_node(AST_List, NULL);};
|
| '(' ')' {$$ = AST_new_node(new_loc(), AST_List, NULL);};
|
||||||
|
|
||||||
params: IOqualifyier paramdecl ',' params {AST_NODE_PTR parameter = AST_new_node(AST_Parameter, NULL);
|
params: IOqualifyier paramdecl ',' params {AST_NODE_PTR parameter = AST_new_node(new_loc(), AST_Parameter, NULL);
|
||||||
AST_push_node(parameter, $1);
|
AST_push_node(parameter, $1);
|
||||||
AST_push_node(parameter, $2);
|
AST_push_node(parameter, $2);
|
||||||
AST_push_node($4, parameter);
|
AST_push_node($4, parameter);
|
||||||
$$ = $4;}
|
$$ = $4;}
|
||||||
| IOqualifyier paramdecl {AST_NODE_PTR list = AST_new_node(AST_ParamList, NULL);
|
| IOqualifyier paramdecl {AST_NODE_PTR list = AST_new_node(new_loc(), AST_ParamList, NULL);
|
||||||
AST_NODE_PTR parameter = AST_new_node(AST_Parameter, NULL);
|
AST_NODE_PTR parameter = AST_new_node(new_loc(), AST_Parameter, NULL);
|
||||||
AST_push_node(parameter, $1);
|
AST_push_node(parameter, $1);
|
||||||
AST_push_node(parameter, $2);
|
AST_push_node(parameter, $2);
|
||||||
AST_push_node(list, parameter);
|
AST_push_node(list, parameter);
|
||||||
$$ = list;};
|
$$ = list;};
|
||||||
|
|
||||||
IOqualifyier: KeyIn { AST_NODE_PTR in = AST_new_node(AST_Qualifyier, "in");
|
IOqualifyier: KeyIn { AST_NODE_PTR in = AST_new_node(new_loc(), AST_Qualifyier, "in");
|
||||||
AST_NODE_PTR list = AST_new_node(AST_List, NULL);
|
AST_NODE_PTR list = AST_new_node(new_loc(), AST_List, NULL);
|
||||||
AST_push_node(list, in);
|
AST_push_node(list, in);
|
||||||
$$ = list;}
|
$$ = list;}
|
||||||
| KeyOut{ AST_NODE_PTR out = AST_new_node(AST_Qualifyier, "out");
|
| KeyOut{ AST_NODE_PTR out = AST_new_node(new_loc(), AST_Qualifyier, "out");
|
||||||
AST_NODE_PTR list = AST_new_node(AST_List, NULL);
|
AST_NODE_PTR list = AST_new_node(new_loc(), AST_List, NULL);
|
||||||
AST_push_node(list, out);
|
AST_push_node(list, out);
|
||||||
$$ = list;}
|
$$ = list;}
|
||||||
| KeyIn KeyOut{ AST_NODE_PTR in = AST_new_node(AST_Qualifyier, "in");
|
| KeyIn KeyOut{ AST_NODE_PTR in = AST_new_node(new_loc(), AST_Qualifyier, "in");
|
||||||
AST_NODE_PTR out = AST_new_node(AST_Qualifyier, "out");
|
AST_NODE_PTR out = AST_new_node(new_loc(), AST_Qualifyier, "out");
|
||||||
AST_NODE_PTR list = AST_new_node(AST_List, NULL);
|
AST_NODE_PTR list = AST_new_node(new_loc(), AST_List, NULL);
|
||||||
AST_push_node(list, in);
|
AST_push_node(list, in);
|
||||||
AST_push_node(list, out);
|
AST_push_node(list, out);
|
||||||
$$ = list;}
|
$$ = list;}
|
||||||
| KeyOut KeyIn{ AST_NODE_PTR in = AST_new_node(AST_Qualifyier, "in");
|
| KeyOut KeyIn{ AST_NODE_PTR in = AST_new_node(new_loc(), AST_Qualifyier, "in");
|
||||||
AST_NODE_PTR out = AST_new_node(AST_Qualifyier, "out");
|
AST_NODE_PTR out = AST_new_node(new_loc(), AST_Qualifyier, "out");
|
||||||
AST_NODE_PTR list = AST_new_node(AST_List, NULL);
|
AST_NODE_PTR list = AST_new_node(new_loc(), AST_List, NULL);
|
||||||
AST_push_node(list, in);
|
AST_push_node(list, in);
|
||||||
AST_push_node(list, out);
|
AST_push_node(list, out);
|
||||||
$$ = list;}
|
$$ = list;}
|
||||||
| {$$ = AST_new_node(AST_List, NULL);};
|
| {$$ = AST_new_node(new_loc(), AST_List, NULL);};
|
||||||
|
|
||||||
paramdecl: type ':' Ident { AST_NODE_PTR paramdecl = AST_new_node(AST_ParamDecl, NULL);
|
paramdecl: type ':' Ident { AST_NODE_PTR paramdecl = AST_new_node(new_loc(), AST_ParamDecl, NULL);
|
||||||
AST_push_node(paramdecl, $1);
|
AST_push_node(paramdecl, $1);
|
||||||
AST_NODE_PTR ident = AST_new_node(AST_Ident, $3);
|
AST_NODE_PTR ident = AST_new_node(new_loc(), AST_Ident, $3);
|
||||||
AST_push_node(paramdecl, ident);
|
AST_push_node(paramdecl, ident);
|
||||||
$$ = paramdecl;
|
$$ = paramdecl;
|
||||||
DEBUG("Param-Declaration"); };
|
DEBUG("Param-Declaration"); };
|
||||||
|
|
||||||
box: KeyType KeyBox ':' Ident '{' boxbody '}' {AST_NODE_PTR box = AST_new_node(AST_Box, NULL);
|
box: KeyType KeyBox ':' Ident '{' boxbody '}' {AST_NODE_PTR box = AST_new_node(new_loc(), AST_Box, NULL);
|
||||||
AST_NODE_PTR ident = AST_new_node(AST_Ident, $4);
|
AST_NODE_PTR ident = AST_new_node(new_loc(), AST_Ident, $4);
|
||||||
AST_push_node(box, ident);
|
AST_push_node(box, ident);
|
||||||
AST_push_node(box, $6);
|
AST_push_node(box, $6);
|
||||||
$$ = box;
|
$$ = box;
|
||||||
DEBUG("Box"); }
|
DEBUG("Box"); }
|
||||||
| KeyType KeyBox ':' Ident '{' '}' {AST_NODE_PTR box = AST_new_node(AST_Box, NULL);
|
| KeyType KeyBox ':' Ident '{' '}' {AST_NODE_PTR box = AST_new_node(new_loc(), AST_Box, NULL);
|
||||||
AST_NODE_PTR ident = AST_new_node(AST_Ident, $4);
|
AST_NODE_PTR ident = AST_new_node(new_loc(), AST_Ident, $4);
|
||||||
AST_push_node(box, ident);
|
AST_push_node(box, ident);
|
||||||
$$ = box;};
|
$$ = box;};
|
||||||
|
|
||||||
boxbody: boxbody boxcontent {AST_push_node($1, $2);
|
boxbody: boxbody boxcontent {AST_push_node($1, $2);
|
||||||
$$ = $1;}
|
$$ = $1;}
|
||||||
| boxcontent {AST_NODE_PTR list = AST_new_node(AST_List, NULL);
|
| boxcontent {AST_NODE_PTR list = AST_new_node(new_loc(), AST_List, NULL);
|
||||||
AST_push_node(list, $1);
|
AST_push_node(list, $1);
|
||||||
$$ = list;};
|
$$ = list;};
|
||||||
|
|
||||||
|
@ -249,66 +251,66 @@ boxcontent: decl { $$ = $1;DEBUG("Box decl Content"); }
|
||||||
| definition { $$ = $1;DEBUG("Box def Content"); }
|
| definition { $$ = $1;DEBUG("Box def Content"); }
|
||||||
| fundef { $$ = $1;DEBUG("Box fun Content"); };
|
| fundef { $$ = $1;DEBUG("Box fun Content"); };
|
||||||
|
|
||||||
boxselfaccess: KeySelf '.' Ident {AST_NODE_PTR boxselfaccess = AST_new_node(AST_List, NULL);
|
boxselfaccess: KeySelf '.' Ident {AST_NODE_PTR boxselfaccess = AST_new_node(new_loc(), AST_List, NULL);
|
||||||
AST_NODE_PTR self = AST_new_node(AST_Ident, "self");
|
AST_NODE_PTR self = AST_new_node(new_loc(), AST_Ident, "self");
|
||||||
AST_push_node(boxselfaccess, self);
|
AST_push_node(boxselfaccess, self);
|
||||||
AST_NODE_PTR identlist = AST_new_node(AST_IdentList, NULL);
|
AST_NODE_PTR identlist = AST_new_node(new_loc(), AST_IdentList, NULL);
|
||||||
AST_NODE_PTR ident = AST_new_node(AST_Ident, $3);
|
AST_NODE_PTR ident = AST_new_node(new_loc(), AST_Ident, $3);
|
||||||
AST_push_node(identlist,ident);
|
AST_push_node(identlist,ident);
|
||||||
AST_push_node(boxselfaccess, identlist);
|
AST_push_node(boxselfaccess, identlist);
|
||||||
$$ = boxselfaccess;}
|
$$ = boxselfaccess;}
|
||||||
| KeySelf '.' boxaccess {AST_NODE_PTR boxselfaccess = AST_new_node(AST_List, NULL);
|
| KeySelf '.' boxaccess {AST_NODE_PTR boxselfaccess = AST_new_node(new_loc(), AST_List, NULL);
|
||||||
AST_NODE_PTR self = AST_new_node(AST_Ident, "self");
|
AST_NODE_PTR self = AST_new_node(new_loc(), AST_Ident, "self");
|
||||||
AST_push_node(boxselfaccess, self);
|
AST_push_node(boxselfaccess, self);
|
||||||
AST_push_node(boxselfaccess, $3);
|
AST_push_node(boxselfaccess, $3);
|
||||||
$$ = boxselfaccess;};
|
$$ = boxselfaccess;};
|
||||||
|
|
||||||
boxaccess: Ident '.' Ident {AST_NODE_PTR identlist = AST_new_node(AST_IdentList, NULL);
|
boxaccess: Ident '.' Ident {AST_NODE_PTR identlist = AST_new_node(new_loc(), AST_IdentList, NULL);
|
||||||
AST_NODE_PTR ident1 = AST_new_node(AST_Ident, $1);
|
AST_NODE_PTR ident1 = AST_new_node(new_loc(), AST_Ident, $1);
|
||||||
AST_NODE_PTR ident2 = AST_new_node(AST_Ident, $3);
|
AST_NODE_PTR ident2 = AST_new_node(new_loc(), AST_Ident, $3);
|
||||||
AST_push_node(identlist,ident1);
|
AST_push_node(identlist,ident1);
|
||||||
AST_push_node(identlist,ident2);
|
AST_push_node(identlist,ident2);
|
||||||
$$ = identlist;}
|
$$ = identlist;}
|
||||||
| Ident '.' boxaccess {AST_NODE_PTR ident = AST_new_node(AST_Ident, $1);
|
| Ident '.' boxaccess {AST_NODE_PTR ident = AST_new_node(new_loc(), AST_Ident, $1);
|
||||||
AST_push_node($3,ident);
|
AST_push_node($3,ident);
|
||||||
$$ = $3;};
|
$$ = $3;};
|
||||||
|
|
||||||
boxcall: boxaccess argumentlist {AST_NODE_PTR boxcall = AST_new_node(AST_Call, NULL);
|
boxcall: boxaccess argumentlist {AST_NODE_PTR boxcall = AST_new_node(new_loc(), AST_Call, NULL);
|
||||||
AST_push_node(boxcall, $1);
|
AST_push_node(boxcall, $1);
|
||||||
AST_push_node(boxcall, $2);
|
AST_push_node(boxcall, $2);
|
||||||
$$ = boxcall;}
|
$$ = boxcall;}
|
||||||
| boxselfaccess argumentlist {AST_NODE_PTR boxcall = AST_new_node(AST_Call, NULL);
|
| boxselfaccess argumentlist {AST_NODE_PTR boxcall = AST_new_node(new_loc(), AST_Call, NULL);
|
||||||
AST_push_node(boxcall, $1);
|
AST_push_node(boxcall, $1);
|
||||||
AST_push_node(boxcall, $2);
|
AST_push_node(boxcall, $2);
|
||||||
$$ = boxcall;};
|
$$ = boxcall;};
|
||||||
|
|
||||||
|
|
||||||
typecast: expr KeyAs type %prec KeyAs {AST_NODE_PTR cast = AST_new_node(AST_Typecast, NULL);
|
typecast: expr KeyAs type %prec KeyAs {AST_NODE_PTR cast = AST_new_node(new_loc(), AST_Typecast, NULL);
|
||||||
AST_push_node(cast, $1);
|
AST_push_node(cast, $1);
|
||||||
AST_push_node(cast, $3);
|
AST_push_node(cast, $3);
|
||||||
$$ = cast;
|
$$ = cast;
|
||||||
DEBUG("Type-Cast"); };
|
DEBUG("Type-Cast"); };
|
||||||
|
|
||||||
reinterpretcast: '(' type ')' expr { AST_NODE_PTR cast = AST_new_node(AST_Transmute, NULL);
|
reinterpretcast: '(' type ')' expr { AST_NODE_PTR cast = AST_new_node(new_loc(), AST_Transmute, NULL);
|
||||||
AST_push_node(cast, $4);
|
AST_push_node(cast, $4);
|
||||||
AST_push_node(cast, $2);
|
AST_push_node(cast, $2);
|
||||||
$$ = cast;
|
$$ = cast;
|
||||||
DEBUG("Reinterpret-Cast"); };
|
DEBUG("Reinterpret-Cast"); };
|
||||||
|
|
||||||
|
|
||||||
funcall: Ident argumentlist {AST_NODE_PTR funcall = AST_new_node(AST_Call, NULL);
|
funcall: Ident argumentlist {AST_NODE_PTR funcall = AST_new_node(new_loc(), AST_Call, NULL);
|
||||||
AST_NODE_PTR ident = AST_new_node(AST_Ident, $1);
|
AST_NODE_PTR ident = AST_new_node(new_loc(), AST_Ident, $1);
|
||||||
AST_push_node(funcall, ident);
|
AST_push_node(funcall, ident);
|
||||||
AST_push_node(funcall, $2);
|
AST_push_node(funcall, $2);
|
||||||
$$ = funcall;
|
$$ = funcall;
|
||||||
DEBUG("Function call"); };
|
DEBUG("Function call"); };
|
||||||
|
|
||||||
moduleimport: KeyImport ValStr {$$ = AST_new_node(AST_Import, $2);
|
moduleimport: KeyImport ValStr {$$ = AST_new_node(new_loc(), AST_Import, $2);
|
||||||
DEBUG("Module-Import"); };
|
DEBUG("Module-Import"); };
|
||||||
|
|
||||||
statementlist: statementlist statement {AST_push_node($1, $2);
|
statementlist: statementlist statement {AST_push_node($1, $2);
|
||||||
$$ = $1;}
|
$$ = $1;}
|
||||||
| statement {AST_NODE_PTR list = AST_new_node(AST_StmtList, NULL);
|
| statement {AST_NODE_PTR list = AST_new_node(new_loc(), AST_StmtList, NULL);
|
||||||
AST_push_node(list, $1);
|
AST_push_node(list, $1);
|
||||||
$$ = list;};
|
$$ = list;};
|
||||||
|
|
||||||
|
@ -320,16 +322,16 @@ statement: assign {$$ = $1;}
|
||||||
| funcall {$$ = $1;}
|
| funcall {$$ = $1;}
|
||||||
| boxcall{$$ = $1;};
|
| boxcall{$$ = $1;};
|
||||||
|
|
||||||
branchif: KeyIf expr '{' statementlist '}' { AST_NODE_PTR branch = AST_new_node(AST_If, NULL);
|
branchif: KeyIf expr '{' statementlist '}' { AST_NODE_PTR branch = AST_new_node(new_loc(), AST_If, NULL);
|
||||||
AST_push_node(branch, $2);
|
AST_push_node(branch, $2);
|
||||||
AST_push_node(branch, $4);
|
AST_push_node(branch, $4);
|
||||||
$$ = branch; };
|
$$ = branch; };
|
||||||
|
|
||||||
branchelse: KeyElse '{' statementlist '}' { AST_NODE_PTR branch = AST_new_node(AST_Else, NULL);
|
branchelse: KeyElse '{' statementlist '}' { AST_NODE_PTR branch = AST_new_node(new_loc(), AST_Else, NULL);
|
||||||
AST_push_node(branch, $3);
|
AST_push_node(branch, $3);
|
||||||
$$ = branch; };
|
$$ = branch; };
|
||||||
|
|
||||||
branchelseif: KeyElse KeyIf expr '{' statementlist '}' { AST_NODE_PTR branch = AST_new_node(AST_IfElse, NULL);
|
branchelseif: KeyElse KeyIf expr '{' statementlist '}' { AST_NODE_PTR branch = AST_new_node(new_loc(), AST_IfElse, NULL);
|
||||||
AST_push_node(branch, $3);
|
AST_push_node(branch, $3);
|
||||||
AST_push_node(branch, $5);
|
AST_push_node(branch, $5);
|
||||||
$$ = branch; };
|
$$ = branch; };
|
||||||
|
@ -337,49 +339,49 @@ branchelseif: KeyElse KeyIf expr '{' statementlist '}' { AST_NODE_PTR branch = A
|
||||||
branchfull: branchhalf { $$ = $1;};
|
branchfull: branchhalf { $$ = $1;};
|
||||||
|branchhalf branchelse { AST_push_node($1 , $2);
|
|branchhalf branchelse { AST_push_node($1 , $2);
|
||||||
$$ = $1; }
|
$$ = $1; }
|
||||||
branchhalf: branchif { AST_NODE_PTR branch = AST_new_node(AST_Stmt, NULL);
|
branchhalf: branchif { AST_NODE_PTR branch = AST_new_node(new_loc(), AST_Stmt, NULL);
|
||||||
AST_push_node(branch, $1);
|
AST_push_node(branch, $1);
|
||||||
$$ = branch; }
|
$$ = branch; }
|
||||||
| branchhalf branchelseif { AST_push_node($1 , $2);
|
| branchhalf branchelseif { AST_push_node($1 , $2);
|
||||||
$$ = $1; };
|
$$ = $1; };
|
||||||
|
|
||||||
|
|
||||||
while: KeyWhile expr '{' statementlist '}' {AST_NODE_PTR whilenode = AST_new_node(AST_While, NULL);
|
while: KeyWhile expr '{' statementlist '}' {AST_NODE_PTR whilenode = AST_new_node(new_loc(), AST_While, NULL);
|
||||||
AST_push_node(whilenode, $2);
|
AST_push_node(whilenode, $2);
|
||||||
AST_push_node(whilenode, $4);
|
AST_push_node(whilenode, $4);
|
||||||
$$ = whilenode;};
|
$$ = whilenode;};
|
||||||
|
|
||||||
identlist: Ident ',' identlist {AST_NODE_PTR ident = AST_new_node(AST_Ident, $1);
|
identlist: Ident ',' identlist {AST_NODE_PTR ident = AST_new_node(new_loc(), AST_Ident, $1);
|
||||||
AST_push_node($3, ident);
|
AST_push_node($3, ident);
|
||||||
$$ = $3;}
|
$$ = $3;}
|
||||||
| Ident {AST_NODE_PTR list = AST_new_node(AST_IdentList, NULL);
|
| Ident {AST_NODE_PTR list = AST_new_node(new_loc(), AST_IdentList, NULL);
|
||||||
AST_NODE_PTR ident = AST_new_node(AST_Ident, $1);
|
AST_NODE_PTR ident = AST_new_node(new_loc(), AST_Ident, $1);
|
||||||
AST_push_node(list, ident);
|
AST_push_node(list, ident);
|
||||||
$$ = list;};
|
$$ = list;};
|
||||||
|
|
||||||
decl: type ':' identlist {AST_NODE_PTR decl = AST_new_node(AST_Decl, NULL);
|
decl: type ':' identlist {AST_NODE_PTR decl = AST_new_node(new_loc(), AST_Decl, NULL);
|
||||||
AST_push_node(decl, $1);
|
AST_push_node(decl, $1);
|
||||||
AST_push_node(decl, $3);
|
AST_push_node(decl, $3);
|
||||||
$$ = decl;}
|
$$ = decl;}
|
||||||
| storagequalifier type ':' identlist {AST_NODE_PTR decl = AST_new_node(AST_Decl, NULL);
|
| storagequalifier type ':' identlist {AST_NODE_PTR decl = AST_new_node(new_loc(), AST_Decl, NULL);
|
||||||
AST_push_node(decl, $1);
|
AST_push_node(decl, $1);
|
||||||
AST_push_node(decl, $2);
|
AST_push_node(decl, $2);
|
||||||
AST_push_node(decl, $4);
|
AST_push_node(decl, $4);
|
||||||
$$ = decl;}
|
$$ = decl;}
|
||||||
|
|
||||||
|
|
||||||
definition: decl '=' expr { AST_NODE_PTR def = AST_new_node(AST_Def, NULL);
|
definition: decl '=' expr { AST_NODE_PTR def = AST_new_node(new_loc(), AST_Def, NULL);
|
||||||
AST_push_node(def, $1);
|
AST_push_node(def, $1);
|
||||||
AST_push_node(def, $3);
|
AST_push_node(def, $3);
|
||||||
$$ = def;
|
$$ = def;
|
||||||
DEBUG("Definition"); };
|
DEBUG("Definition"); };
|
||||||
|
|
||||||
storagequalifier: KeyGlobal {$$ = AST_new_node(AST_Storage, "global");}
|
storagequalifier: KeyGlobal {$$ = AST_new_node(new_loc(), AST_Storage, "global");}
|
||||||
| KeyStatic {$$ = AST_new_node(AST_Storage, "static");}
|
| KeyStatic {$$ = AST_new_node(new_loc(), AST_Storage, "static");}
|
||||||
| KeyLocal {$$ = AST_new_node(AST_Storage, "local");};
|
| KeyLocal {$$ = AST_new_node(new_loc(), AST_Storage, "local");};
|
||||||
|
|
||||||
assign: Ident '=' expr { AST_NODE_PTR assign = AST_new_node(AST_Assign, NULL);
|
assign: Ident '=' expr { AST_NODE_PTR assign = AST_new_node(new_loc(), AST_Assign, NULL);
|
||||||
AST_NODE_PTR ident = AST_new_node(AST_Ident, $1);
|
AST_NODE_PTR ident = AST_new_node(new_loc(), AST_Ident, $1);
|
||||||
AST_push_node(assign, ident);
|
AST_push_node(assign, ident);
|
||||||
AST_push_node(assign, $3);
|
AST_push_node(assign, $3);
|
||||||
$$ = assign;
|
$$ = assign;
|
||||||
|
@ -388,60 +390,60 @@ assign: Ident '=' expr { AST_NODE_PTR assign = AST_new_node(AST_Assign, NULL);
|
||||||
| boxaccess '=' expr
|
| boxaccess '=' expr
|
||||||
| boxselfaccess '=' expr ;
|
| boxselfaccess '=' expr ;
|
||||||
|
|
||||||
sign: KeySigned {$$ = AST_new_node(AST_Sign, "signed");}
|
sign: KeySigned {$$ = AST_new_node(new_loc(), AST_Sign, "signed");}
|
||||||
| KeyUnsigned{$$ = AST_new_node(AST_Sign, "unsigned");};
|
| KeyUnsigned{$$ = AST_new_node(new_loc(), AST_Sign, "unsigned");};
|
||||||
|
|
||||||
typedef: KeyType type':' Ident {AST_NODE_PTR typeDef = AST_new_node(AST_Typedef, NULL);
|
typedef: KeyType type':' Ident {AST_NODE_PTR typeDef = AST_new_node(new_loc(), AST_Typedef, NULL);
|
||||||
AST_push_node(typeDef, $2);
|
AST_push_node(typeDef, $2);
|
||||||
AST_NODE_PTR ident = AST_new_node(AST_Ident, $4);
|
AST_NODE_PTR ident = AST_new_node(new_loc(), AST_Ident, $4);
|
||||||
AST_push_node(typeDef, ident);
|
AST_push_node(typeDef, ident);
|
||||||
$$ = typeDef;};
|
$$ = typeDef;};
|
||||||
|
|
||||||
scale: scale KeyShort {AST_NODE_PTR shortnode = AST_new_node(AST_Scale, "short");
|
scale: scale KeyShort {AST_NODE_PTR shortnode = AST_new_node(new_loc(), AST_Scale, "short");
|
||||||
AST_push_node($1, shortnode);
|
AST_push_node($1, shortnode);
|
||||||
$$ = $1;}
|
$$ = $1;}
|
||||||
| scale KeyHalf {AST_NODE_PTR shortnode = AST_new_node(AST_Scale, "half");
|
| scale KeyHalf {AST_NODE_PTR shortnode = AST_new_node(new_loc(), AST_Scale, "half");
|
||||||
AST_push_node($1, shortnode);
|
AST_push_node($1, shortnode);
|
||||||
$$ = $1;}
|
$$ = $1;}
|
||||||
| scale KeyLong {AST_NODE_PTR shortnode = AST_new_node(AST_Scale, "long");
|
| scale KeyLong {AST_NODE_PTR shortnode = AST_new_node(new_loc(), AST_Scale, "long");
|
||||||
AST_push_node($1, shortnode);
|
AST_push_node($1, shortnode);
|
||||||
$$ = $1;}
|
$$ = $1;}
|
||||||
| scale KeyDouble {AST_NODE_PTR shortnode = AST_new_node(AST_Scale, "double");
|
| scale KeyDouble {AST_NODE_PTR shortnode = AST_new_node(new_loc(), AST_Scale, "double");
|
||||||
AST_push_node($1, shortnode);
|
AST_push_node($1, shortnode);
|
||||||
$$ = $1;}
|
$$ = $1;}
|
||||||
| KeyShort {AST_NODE_PTR scale = AST_new_node(AST_List, NULL);
|
| KeyShort {AST_NODE_PTR scale = AST_new_node(new_loc(), AST_List, NULL);
|
||||||
AST_NODE_PTR shortnode = AST_new_node(AST_Scale, "short");
|
AST_NODE_PTR shortnode = AST_new_node(new_loc(), AST_Scale, "short");
|
||||||
AST_push_node(scale, shortnode);
|
AST_push_node(scale, shortnode);
|
||||||
$$ = scale;}
|
$$ = scale;}
|
||||||
| KeyHalf {AST_NODE_PTR scale = AST_new_node(AST_List, NULL);
|
| KeyHalf {AST_NODE_PTR scale = AST_new_node(new_loc(), AST_List, NULL);
|
||||||
AST_NODE_PTR shortnode = AST_new_node(AST_Scale, "half");
|
AST_NODE_PTR shortnode = AST_new_node(new_loc(), AST_Scale, "half");
|
||||||
AST_push_node(scale, shortnode);
|
AST_push_node(scale, shortnode);
|
||||||
$$ = scale;}
|
$$ = scale;}
|
||||||
| KeyLong {AST_NODE_PTR scale = AST_new_node(AST_List, NULL);
|
| KeyLong {AST_NODE_PTR scale = AST_new_node(new_loc(), AST_List, NULL);
|
||||||
AST_NODE_PTR shortnode = AST_new_node(AST_Scale, "long");
|
AST_NODE_PTR shortnode = AST_new_node(new_loc(), AST_Scale, "long");
|
||||||
AST_push_node(scale, shortnode);
|
AST_push_node(scale, shortnode);
|
||||||
$$ = scale;}
|
$$ = scale;}
|
||||||
| KeyDouble {AST_NODE_PTR scale = AST_new_node(AST_List, NULL);
|
| KeyDouble {AST_NODE_PTR scale = AST_new_node(new_loc(), AST_List, NULL);
|
||||||
AST_NODE_PTR shortnode = AST_new_node(AST_Scale, "double");
|
AST_NODE_PTR shortnode = AST_new_node(new_loc(), AST_Scale, "double");
|
||||||
AST_push_node(scale, shortnode);
|
AST_push_node(scale, shortnode);
|
||||||
$$ = scale;};
|
$$ = scale;};
|
||||||
|
|
||||||
typekind: Ident {$$ = AST_new_node(AST_Typekind, $1);}
|
typekind: Ident {$$ = AST_new_node(new_loc(), AST_Typekind, $1);}
|
||||||
| KeyInt {$$ = AST_new_node(AST_Typekind, "int");}
|
| KeyInt {$$ = AST_new_node(new_loc(), AST_Typekind, "int");}
|
||||||
| KeyFloat {$$ = AST_new_node(AST_Typekind, "float");};
|
| KeyFloat {$$ = AST_new_node(new_loc(), AST_Typekind, "float");};
|
||||||
|
|
||||||
type: typekind {AST_NODE_PTR type = AST_new_node(AST_Type, NULL);
|
type: typekind {AST_NODE_PTR type = AST_new_node(new_loc(), AST_Type, NULL);
|
||||||
AST_push_node(type, $1);
|
AST_push_node(type, $1);
|
||||||
$$ = type;}
|
$$ = type;}
|
||||||
| scale typekind {AST_NODE_PTR type = AST_new_node(AST_Type, NULL);
|
| scale typekind {AST_NODE_PTR type = AST_new_node(new_loc(), AST_Type, NULL);
|
||||||
AST_push_node(type, $1);
|
AST_push_node(type, $1);
|
||||||
AST_push_node(type, $2);
|
AST_push_node(type, $2);
|
||||||
$$ = type;}
|
$$ = type;}
|
||||||
| sign typekind {AST_NODE_PTR type = AST_new_node(AST_Type, NULL);
|
| sign typekind {AST_NODE_PTR type = AST_new_node(new_loc(), AST_Type, NULL);
|
||||||
AST_push_node(type, $1);
|
AST_push_node(type, $1);
|
||||||
AST_push_node(type, $2);
|
AST_push_node(type, $2);
|
||||||
$$ = type;}
|
$$ = type;}
|
||||||
| sign scale typekind {AST_NODE_PTR type = AST_new_node(AST_Type, NULL);
|
| sign scale typekind {AST_NODE_PTR type = AST_new_node(new_loc(), AST_Type, NULL);
|
||||||
AST_push_node(type, $1);
|
AST_push_node(type, $1);
|
||||||
AST_push_node(type, $2);
|
AST_push_node(type, $2);
|
||||||
AST_push_node(type, $3);
|
AST_push_node(type, $3);
|
||||||
|
@ -452,136 +454,74 @@ operation: oparith {$$ = $1;}
|
||||||
| opbool {$$ = $1;}
|
| opbool {$$ = $1;}
|
||||||
| opbit {$$ = $1;};
|
| opbit {$$ = $1;};
|
||||||
|
|
||||||
oparith: expr '+' expr {AST_NODE_PTR add = AST_new_node(AST_Add, NULL);
|
oparith: expr '+' expr {AST_NODE_PTR add = AST_new_node(new_loc(), AST_Add, NULL);
|
||||||
AST_push_node(add, $1);
|
AST_push_node(add, $1);
|
||||||
AST_push_node(add, $3);
|
AST_push_node(add, $3);
|
||||||
$$ = add;}
|
$$ = add;}
|
||||||
| expr '-' expr {AST_NODE_PTR subtract = AST_new_node(AST_Sub, NULL);
|
| expr '-' expr {AST_NODE_PTR subtract = AST_new_node(new_loc(), AST_Sub, NULL);
|
||||||
AST_push_node(subtract, $1);
|
AST_push_node(subtract, $1);
|
||||||
AST_push_node(subtract, $3);
|
AST_push_node(subtract, $3);
|
||||||
$$ = subtract;}
|
$$ = subtract;}
|
||||||
| expr '*' expr {AST_NODE_PTR mul = AST_new_node(AST_Mul, NULL);
|
| expr '*' expr {AST_NODE_PTR mul = AST_new_node(new_loc(), AST_Mul, NULL);
|
||||||
AST_push_node(mul, $1);
|
AST_push_node(mul, $1);
|
||||||
AST_push_node(mul, $3);
|
AST_push_node(mul, $3);
|
||||||
$$ = mul;}
|
$$ = mul;}
|
||||||
| expr '/' expr {AST_NODE_PTR div = AST_new_node(AST_Div, NULL);
|
| expr '/' expr {AST_NODE_PTR div = AST_new_node(new_loc(), AST_Div, NULL);
|
||||||
AST_push_node(div, $1);
|
AST_push_node(div, $1);
|
||||||
AST_push_node(div, $3);
|
AST_push_node(div, $3);
|
||||||
$$ = div;}
|
$$ = div;}
|
||||||
| '-' expr %prec '*'{AST_NODE_PTR negator = AST_new_node(AST_Negate, NULL);
|
| '-' expr %prec '*'{AST_NODE_PTR negator = AST_new_node(new_loc(), AST_Negate, NULL);
|
||||||
AST_push_node(negator, $2);
|
AST_push_node(negator, $2);
|
||||||
$$ = negator;};
|
$$ = negator;};
|
||||||
|
|
||||||
oplogic: expr OpEquals expr {AST_NODE_PTR equals = AST_new_node(AST_Eq, NULL);
|
oplogic: expr OpEquals expr {AST_NODE_PTR equals = AST_new_node(new_loc(), AST_Eq, NULL);
|
||||||
AST_push_node(equals, $1);
|
AST_push_node(equals, $1);
|
||||||
AST_push_node(equals, $3);
|
AST_push_node(equals, $3);
|
||||||
$$ = equals;}
|
$$ = equals;}
|
||||||
| expr '<' expr {AST_NODE_PTR less = AST_new_node(AST_Less, NULL);
|
| expr '<' expr {AST_NODE_PTR less = AST_new_node(new_loc(), AST_Less, NULL);
|
||||||
AST_push_node(less, $1);
|
AST_push_node(less, $1);
|
||||||
AST_push_node(less, $3);
|
AST_push_node(less, $3);
|
||||||
$$ = less;}
|
$$ = less;}
|
||||||
| expr '>' expr{AST_NODE_PTR greater = AST_new_node(AST_Greater, NULL);
|
| expr '>' expr{AST_NODE_PTR greater = AST_new_node(new_loc(), AST_Greater, NULL);
|
||||||
AST_push_node(greater, $1);
|
AST_push_node(greater, $1);
|
||||||
AST_push_node(greater, $3);
|
AST_push_node(greater, $3);
|
||||||
$$ = greater;};
|
$$ = greater;};
|
||||||
|
|
||||||
opbool: expr OpAnd expr {AST_NODE_PTR and = AST_new_node(AST_BoolAnd, NULL);
|
opbool: expr OpAnd expr {AST_NODE_PTR and = AST_new_node(new_loc(), AST_BoolAnd, NULL);
|
||||||
AST_push_node(and, $1);
|
AST_push_node(and, $1);
|
||||||
AST_push_node(and, $3);
|
AST_push_node(and, $3);
|
||||||
$$ = and;}
|
$$ = and;}
|
||||||
| expr OpOr expr{AST_NODE_PTR or = AST_new_node(AST_BoolOr, NULL);
|
| expr OpOr expr{AST_NODE_PTR or = AST_new_node(new_loc(), AST_BoolOr, NULL);
|
||||||
AST_push_node(or, $1);
|
AST_push_node(or, $1);
|
||||||
AST_push_node(or, $3);
|
AST_push_node(or, $3);
|
||||||
$$ = or;}
|
$$ = or;}
|
||||||
| expr OpXor expr{AST_NODE_PTR xor = AST_new_node(AST_BoolXor, NULL);
|
| expr OpXor expr{AST_NODE_PTR xor = AST_new_node(new_loc(), AST_BoolXor, NULL);
|
||||||
AST_push_node(xor, $1);
|
AST_push_node(xor, $1);
|
||||||
AST_push_node(xor, $3);
|
AST_push_node(xor, $3);
|
||||||
$$ = xor;}
|
$$ = xor;}
|
||||||
| OpNot expr %prec OpAnd{AST_NODE_PTR not = AST_new_node(AST_BoolNot, NULL);
|
| OpNot expr %prec OpAnd{AST_NODE_PTR not = AST_new_node(new_loc(), AST_BoolNot, NULL);
|
||||||
AST_push_node(not, $2);
|
AST_push_node(not, $2);
|
||||||
$$ = not;};
|
$$ = not;};
|
||||||
|
|
||||||
opbit: expr OpBitand expr {AST_NODE_PTR and = AST_new_node(AST_BitAnd, NULL);
|
opbit: expr OpBitand expr {AST_NODE_PTR and = AST_new_node(new_loc(), AST_BitAnd, NULL);
|
||||||
AST_push_node(and, $1);
|
AST_push_node(and, $1);
|
||||||
AST_push_node(and, $3);
|
AST_push_node(and, $3);
|
||||||
$$ = and;}
|
$$ = and;}
|
||||||
| expr OpBitor expr{AST_NODE_PTR or = AST_new_node(AST_BitOr, NULL);
|
| expr OpBitor expr{AST_NODE_PTR or = AST_new_node(new_loc(), AST_BitOr, NULL);
|
||||||
AST_push_node(or, $1);
|
AST_push_node(or, $1);
|
||||||
AST_push_node(or, $3);
|
AST_push_node(or, $3);
|
||||||
$$ = or;}
|
$$ = or;}
|
||||||
| expr OpBitxor expr{AST_NODE_PTR xor = AST_new_node(AST_BitXor, NULL);
|
| expr OpBitxor expr{AST_NODE_PTR xor = AST_new_node(new_loc(), AST_BitXor, NULL);
|
||||||
AST_push_node(xor, $1);
|
AST_push_node(xor, $1);
|
||||||
AST_push_node(xor, $3);
|
AST_push_node(xor, $3);
|
||||||
$$ = xor;}
|
$$ = xor;}
|
||||||
| OpBitnot expr %prec OpBitand{AST_NODE_PTR not = AST_new_node(AST_BitNot, NULL);
|
| OpBitnot expr %prec OpBitand{AST_NODE_PTR not = AST_new_node(new_loc(), AST_BitNot, NULL);
|
||||||
AST_push_node(not, $2);
|
AST_push_node(not, $2);
|
||||||
$$ = not;};
|
$$ = not;};
|
||||||
%%
|
%%
|
||||||
|
|
||||||
|
|
||||||
const char* ERROR = "error";
|
|
||||||
const char* WARNING = "warning";
|
|
||||||
const char* NOTE = "note";
|
|
||||||
|
|
||||||
int print_message(const char* kind, const char* message) {
|
|
||||||
// number of characters written
|
|
||||||
int char_count = 0;
|
|
||||||
// highlight to use
|
|
||||||
char* HIGHLIGHT = CYAN;
|
|
||||||
|
|
||||||
// convert message kind into color
|
|
||||||
if (kind == ERROR) {
|
|
||||||
HIGHLIGHT = RED;
|
|
||||||
} else if (kind == WARNING) {
|
|
||||||
HIGHLIGHT = YELLOW;
|
|
||||||
}
|
|
||||||
|
|
||||||
// print message
|
|
||||||
char_count += printf("%sfilename:%d:%d%s:%s%s %s: %s%s\n", BOLD, yylloc.first_line, yylloc.first_column, RESET, HIGHLIGHT, BOLD, kind, RESET, message);
|
|
||||||
|
|
||||||
// print line in which error occurred
|
|
||||||
|
|
||||||
char_count += printf(" %4d | ", yylloc.first_line);
|
|
||||||
|
|
||||||
for (int i = 0; i < yylloc.first_column - 1; i++) {
|
|
||||||
if (buffer[i] == '\n') {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
printf("%c", buffer[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
char_count += printf("%s%s", BOLD, HIGHLIGHT);
|
|
||||||
|
|
||||||
for (int i = yylloc.first_column - 1; i < yylloc.last_column; i++) {
|
|
||||||
if (buffer[i] == '\n') {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
char_count += printf("%c", buffer[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
char_count += printf("%s", RESET);
|
|
||||||
|
|
||||||
for (int i = yylloc.last_column; buffer[i] != '\0' && buffer[i] != '\n'; i++) {
|
|
||||||
printf("%c", buffer[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
char_count += printf("\n | ");
|
|
||||||
|
|
||||||
for (int i = 0; i < yylloc.first_column - 1; i++) {
|
|
||||||
char_count += printf(" ");
|
|
||||||
}
|
|
||||||
|
|
||||||
char_count += printf("%s^", HIGHLIGHT);
|
|
||||||
|
|
||||||
for (int i = 0; i < yylloc.last_column - yylloc.first_column; i++) {
|
|
||||||
printf("~");
|
|
||||||
}
|
|
||||||
|
|
||||||
char_count += printf("%s\n\n", RESET);
|
|
||||||
|
|
||||||
return char_count;
|
|
||||||
}
|
|
||||||
|
|
||||||
int yyerror(const char *s) {
|
int yyerror(const char *s) {
|
||||||
return print_message(ERROR, s);
|
TokenLocation location = new_loc();
|
||||||
|
print_diagnostic(current_file, &location, Error, s);
|
||||||
|
return 0;
|
||||||
}
|
}
|
Loading…
Reference in New Issue