Merge pull request #112 from Servostar/91-allow-to-parse-multiple-files

91 allow to parse multiple files
This commit is contained in:
servostar 2024-05-31 16:14:36 +02:00 committed by GitHub
commit dda040c996
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
17 changed files with 603 additions and 236 deletions

View File

@ -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;

View File

@ -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.

235
src/io/files.c Normal file
View File

@ -0,0 +1,235 @@
//
// 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;
}
TokenLocation empty_location(void) {
TokenLocation location;
location.line_start = 0;
location.line_end = 0;
location.col_start = 0;
location.col_end = 0;
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");
}

79
src/io/files.h Normal file
View File

@ -0,0 +1,79 @@
//
// 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);
TokenLocation empty_location(void);
[[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

View File

@ -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);

View File

@ -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

View File

@ -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,62 @@ 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(&notify_exit); atexit(&notify_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); if (files.files == NULL) {
return 0; printf("No input files, nothing to do.\n\n");
exit(1);
}
print_unit_statistics(&files);
delete_files(&files);
return 0;
} }

View File

@ -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 {
@ -145,11 +147,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;}
@ -159,22 +161,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);
@ -184,66 +186,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;};
@ -251,66 +253,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: expr KeyTo type %prec KeyTo { AST_NODE_PTR cast = AST_new_node(AST_Transmute, NULL); reinterpretcast: expr KeyTo type %prec KeyTo { AST_NODE_PTR cast = AST_new_node(new_loc(), AST_Transmute, NULL);
AST_push_node(cast, $1); AST_push_node(cast, $1);
AST_push_node(cast, $3); AST_push_node(cast, $3);
$$ = 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;};
@ -322,16 +324,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; };
@ -339,49 +341,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;
@ -390,60 +392,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);
@ -454,136 +456,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;
} }

View File

@ -2,6 +2,14 @@ include(CTest)
include_directories(${PROJECT_SOURCE_DIR}/src) include_directories(${PROJECT_SOURCE_DIR}/src)
# ------------------------------------------------ #
# Setup Glib 2.0 #
# ------------------------------------------------ #
find_package(PkgConfig REQUIRED)
pkg_search_module(GLIB REQUIRED IMPORTED_TARGET glib-2.0)
include_directories(PRIVATE ${GLIB_INCLUDE_DIRS})
# ------------------------------------------------------- # # ------------------------------------------------------- #
# CTEST 1 # CTEST 1
# test building the syntax tree # test building the syntax tree
@ -9,11 +17,14 @@ include_directories(${PROJECT_SOURCE_DIR}/src)
add_executable(ast_build_tree add_executable(ast_build_tree
${PROJECT_SOURCE_DIR}/src/ast/ast.c ${PROJECT_SOURCE_DIR}/src/ast/ast.c
${PROJECT_SOURCE_DIR}/src/sys/log.c ${PROJECT_SOURCE_DIR}/src/sys/log.c
${PROJECT_SOURCE_DIR}/src/io/files.c
${PROJECT_SOURCE_DIR}/src/sys/col.c
build_tree.c) build_tree.c)
set_target_properties(ast_build_tree set_target_properties(ast_build_tree
PROPERTIES PROPERTIES
OUTPUT_NAME "build_tree" OUTPUT_NAME "build_tree"
RUNTIME_OUTPUT_DIRECTORY ${GEMSTONE_BINARY_DIR}/tests/ast) RUNTIME_OUTPUT_DIRECTORY ${GEMSTONE_BINARY_DIR}/tests/ast)
target_link_libraries(ast_build_tree PkgConfig::GLIB)
add_test(NAME ast_build_tree add_test(NAME ast_build_tree
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
COMMAND python ${GEMSTONE_TEST_DIR}/ast/test_ast.py check_build_tree) COMMAND python ${GEMSTONE_TEST_DIR}/ast/test_ast.py check_build_tree)
@ -25,11 +36,14 @@ add_test(NAME ast_build_tree
add_executable(ast_print_node add_executable(ast_print_node
${PROJECT_SOURCE_DIR}/src/ast/ast.c ${PROJECT_SOURCE_DIR}/src/ast/ast.c
${PROJECT_SOURCE_DIR}/src/sys/log.c ${PROJECT_SOURCE_DIR}/src/sys/log.c
${PROJECT_SOURCE_DIR}/src/io/files.c
${PROJECT_SOURCE_DIR}/src/sys/col.c
print_node.c) print_node.c)
set_target_properties(ast_print_node set_target_properties(ast_print_node
PROPERTIES PROPERTIES
OUTPUT_NAME "print_node" OUTPUT_NAME "print_node"
RUNTIME_OUTPUT_DIRECTORY ${GEMSTONE_BINARY_DIR}/tests/ast) RUNTIME_OUTPUT_DIRECTORY ${GEMSTONE_BINARY_DIR}/tests/ast)
target_link_libraries(ast_print_node PkgConfig::GLIB)
add_test(NAME ast_print_node add_test(NAME ast_print_node
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
COMMAND python ${GEMSTONE_TEST_DIR}/ast/test_ast.py check_print_node) COMMAND python ${GEMSTONE_TEST_DIR}/ast/test_ast.py check_print_node)
@ -41,11 +55,14 @@ add_test(NAME ast_print_node
add_executable(ast_graphviz add_executable(ast_graphviz
${PROJECT_SOURCE_DIR}/src/ast/ast.c ${PROJECT_SOURCE_DIR}/src/ast/ast.c
${PROJECT_SOURCE_DIR}/src/sys/log.c ${PROJECT_SOURCE_DIR}/src/sys/log.c
${PROJECT_SOURCE_DIR}/src/io/files.c
${PROJECT_SOURCE_DIR}/src/sys/col.c
print_graphviz.c) print_graphviz.c)
set_target_properties(ast_graphviz set_target_properties(ast_graphviz
PROPERTIES PROPERTIES
OUTPUT_NAME "print_graphviz" OUTPUT_NAME "print_graphviz"
RUNTIME_OUTPUT_DIRECTORY ${GEMSTONE_BINARY_DIR}/tests/ast) RUNTIME_OUTPUT_DIRECTORY ${GEMSTONE_BINARY_DIR}/tests/ast)
target_link_libraries(ast_graphviz PkgConfig::GLIB)
add_test(NAME ast_graphviz add_test(NAME ast_graphviz
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
COMMAND python ${GEMSTONE_TEST_DIR}/ast/test_ast.py check_print_graphviz) COMMAND python ${GEMSTONE_TEST_DIR}/ast/test_ast.py check_print_graphviz)

View File

@ -6,22 +6,22 @@
#include <sys/log.h> #include <sys/log.h>
void generate_statement(const AST_NODE_PTR stmt) { void generate_statement(const AST_NODE_PTR stmt) {
const AST_NODE_PTR add = AST_new_node(AST_Add, NULL); const AST_NODE_PTR add = AST_new_node(empty_location(), AST_Add, NULL);
AST_push_node(add, AST_new_node(AST_Int, "3")); AST_push_node(add, AST_new_node(empty_location(), AST_Int, "3"));
AST_push_node(add, AST_new_node(AST_Int, "6")); AST_push_node(add, AST_new_node(empty_location(), AST_Int, "6"));
AST_push_node(stmt, add); AST_push_node(stmt, add);
} }
void generate_branch(const AST_NODE_PTR stmt) { void generate_branch(const AST_NODE_PTR stmt) {
const AST_NODE_PTR branch = AST_new_node(AST_If, NULL); const AST_NODE_PTR branch = AST_new_node(empty_location(), AST_If, NULL);
const AST_NODE_PTR gt = AST_new_node(AST_Greater, NULL); const AST_NODE_PTR gt = AST_new_node(empty_location(), AST_Greater, NULL);
AST_push_node(branch, gt); AST_push_node(branch, gt);
AST_push_node(gt, AST_new_node(AST_Float, "2.3")); AST_push_node(gt, AST_new_node(empty_location(), AST_Float, "2.3"));
AST_push_node(gt, AST_new_node(AST_Float, "0.79")); AST_push_node(gt, AST_new_node(empty_location(), AST_Float, "0.79"));
AST_push_node(stmt, branch); AST_push_node(stmt, branch);
@ -30,7 +30,7 @@ void generate_branch(const AST_NODE_PTR stmt) {
int main(void) { int main(void) {
const AST_NODE_PTR root = AST_new_node(AST_Stmt, NULL); const AST_NODE_PTR root = AST_new_node(empty_location(), AST_Stmt, NULL);
generate_branch(root); generate_branch(root);

View File

@ -7,15 +7,15 @@
int main(void) { int main(void) {
struct AST_Node_t* node = AST_new_node(AST_If, NULL); struct AST_Node_t* node = AST_new_node(empty_location(), AST_If, NULL);
struct AST_Node_t* child = AST_new_node(AST_Add, NULL); struct AST_Node_t* child = AST_new_node(empty_location(), AST_Add, NULL);
AST_push_node(child, AST_new_node(AST_Int, "43")); AST_push_node(child, AST_new_node(empty_location(), AST_Int, "43"));
AST_push_node(child, AST_new_node(AST_Int, "9")); AST_push_node(child, AST_new_node(empty_location(), AST_Int, "9"));
AST_push_node(node, child); AST_push_node(node, child);
AST_push_node(node, AST_new_node(AST_Expr, NULL)); AST_push_node(node, AST_new_node(empty_location(), AST_Expr, NULL));
AST_push_node(node, AST_new_node(AST_Expr, NULL)); AST_push_node(node, AST_new_node(empty_location(), AST_Expr, NULL));
FILE* out = fopen("ast.gv", "w+"); FILE* out = fopen("ast.gv", "w+");
// convert this file ^^^^^^ // convert this file ^^^^^^

View File

@ -6,22 +6,22 @@
#include <sys/log.h> #include <sys/log.h>
void generate_statement(const AST_NODE_PTR stmt) { void generate_statement(const AST_NODE_PTR stmt) {
const AST_NODE_PTR add = AST_new_node(AST_Add, NULL); const AST_NODE_PTR add = AST_new_node(empty_location(), AST_Add, NULL);
AST_push_node(add, AST_new_node(AST_Int, "3")); AST_push_node(add, AST_new_node(empty_location(), AST_Int, "3"));
AST_push_node(add, AST_new_node(AST_Int, "6")); AST_push_node(add, AST_new_node(empty_location(), AST_Int, "6"));
AST_push_node(stmt, add); AST_push_node(stmt, add);
} }
void generate_branch(const AST_NODE_PTR stmt) { void generate_branch(const AST_NODE_PTR stmt) {
const AST_NODE_PTR branch = AST_new_node(AST_If, NULL); const AST_NODE_PTR branch = AST_new_node(empty_location(), AST_If, NULL);
const AST_NODE_PTR gt = AST_new_node(AST_Greater, NULL); const AST_NODE_PTR gt = AST_new_node(empty_location(), AST_Greater, NULL);
AST_push_node(branch, gt); AST_push_node(branch, gt);
AST_push_node(gt, AST_new_node(AST_Float, "2.3")); AST_push_node(gt, AST_new_node(empty_location(), AST_Float, "2.3"));
AST_push_node(gt, AST_new_node(AST_Float, "0.79")); AST_push_node(gt, AST_new_node(empty_location(), AST_Float, "0.79"));
AST_push_node(stmt, branch); AST_push_node(stmt, branch);
@ -32,7 +32,7 @@ int main(void) {
AST_init(); AST_init();
const AST_NODE_PTR root = AST_new_node(AST_Stmt, NULL); const AST_NODE_PTR root = AST_new_node(empty_location(), AST_Stmt, NULL);
generate_branch(root); generate_branch(root);

View File

@ -8,7 +8,7 @@ int main(void) {
AST_init(); AST_init();
const AST_NODE_PTR node = AST_new_node(0, "value"); const AST_NODE_PTR node = AST_new_node(empty_location(), 0, "value");
for (size_t i = 0; i < AST_ELEMENT_COUNT; i++) { for (size_t i = 0; i < AST_ELEMENT_COUNT; i++) {
// set kind // set kind

View File

@ -2,12 +2,20 @@ include(CTest)
include_directories(${PROJECT_SOURCE_DIR}/src) include_directories(${PROJECT_SOURCE_DIR}/src)
# ------------------------------------------------ #
# Setup Glib 2.0 #
# ------------------------------------------------ #
find_package(PkgConfig REQUIRED)
pkg_search_module(GLIB REQUIRED IMPORTED_TARGET glib-2.0)
# ------------------------------------------------------- # # ------------------------------------------------------- #
# CTEST 1 # CTEST 1
# test the default output of the logger # test the default output of the logger
add_executable(logging_output add_executable(logging_output
${PROJECT_SOURCE_DIR}/src/sys/log.c ${PROJECT_SOURCE_DIR}/src/sys/log.c
${PROJECT_SOURCE_DIR}/src/sys/col.c
output.c) output.c)
set_target_properties(logging_output set_target_properties(logging_output
PROPERTIES PROPERTIES
@ -23,6 +31,7 @@ add_test(NAME logging_output
add_executable(logging_panic add_executable(logging_panic
${PROJECT_SOURCE_DIR}/src/sys/log.c ${PROJECT_SOURCE_DIR}/src/sys/log.c
${PROJECT_SOURCE_DIR}/src/sys/col.c
panic.c) panic.c)
set_target_properties(logging_panic set_target_properties(logging_panic
PROPERTIES PROPERTIES
@ -38,6 +47,7 @@ add_test(NAME logging_panic
add_executable(logging_streams add_executable(logging_streams
${PROJECT_SOURCE_DIR}/src/sys/log.c ${PROJECT_SOURCE_DIR}/src/sys/log.c
${PROJECT_SOURCE_DIR}/src/sys/col.c
streams.c) streams.c)
set_target_properties(logging_streams set_target_properties(logging_streams
PROPERTIES PROPERTIES
@ -53,6 +63,7 @@ add_test(NAME logging_streams
add_executable(logging_level add_executable(logging_level
${PROJECT_SOURCE_DIR}/src/sys/log.c ${PROJECT_SOURCE_DIR}/src/sys/log.c
${PROJECT_SOURCE_DIR}/src/sys/col.c
level.c) level.c)
set_target_properties(logging_level set_target_properties(logging_level
PROPERTIES PROPERTIES

View File

@ -3,11 +3,13 @@
// //
#include "sys/log.h" #include "sys/log.h"
#include <sys/col.h>
#define LOG_LEVEL LOG_LEVEL_WARNING #define LOG_LEVEL LOG_LEVEL_WARNING
int main(void) { int main(void) {
log_init(); log_init();
col_init();
DEBUG("logging some debug..."); DEBUG("logging some debug...");
INFO("logging some info..."); INFO("logging some info...");

View File

@ -3,9 +3,11 @@
// //
#include "sys/log.h" #include "sys/log.h"
#include <sys/col.h>
int main(void) { int main(void) {
log_init(); log_init();
col_init();
DEBUG("logging some debug..."); DEBUG("logging some debug...");
INFO("logging some info..."); INFO("logging some info...");