Merge branch 'main' into 41-add-parser-rules-for-casts
This commit is contained in:
commit
af32c32c6a
|
@ -15,3 +15,6 @@ parser.tab.c
|
|||
parser.tab.h
|
||||
build
|
||||
/Testing/
|
||||
CTestTestfile.cmake
|
||||
DartConfiguration.tcl
|
||||
*.cmake
|
||||
|
|
|
@ -61,8 +61,10 @@ set(YACC_SOURCE_FILE ${PROJECT_SOURCE_DIR}/src/yacc/parser.y)
|
|||
set(YACC_GENERATED_SOURCE_FILE ${PROJECT_SOURCE_DIR}/src/yacc/parser.tab.c)
|
||||
|
||||
add_custom_command(OUTPUT ${YACC_GENERATED_SOURCE_FILE}
|
||||
COMMAND yacc
|
||||
ARGS -Wcounterexamples -d -o ${YACC_GENERATED_SOURCE_FILE} ${YACC_SOURCE_FILE}
|
||||
|
||||
COMMAND bison
|
||||
ARGS -Wno-yacc -Wcounterexamples -d -o ${YACC_GENERATED_SOURCE_FILE} ${YACC_SOURCE_FILE}
|
||||
|
||||
COMMENT "generate C source file for parser"
|
||||
VERBATIM)
|
||||
|
||||
|
|
|
@ -33,8 +33,8 @@ void AST_init() {
|
|||
DEBUG("initializing global syntax tree...");
|
||||
|
||||
INFO("filling lookup table...");
|
||||
|
||||
lookup_table[AST_Stmt] = "stmt";
|
||||
lookup_table[AST_Module] = "module";
|
||||
lookup_table[AST_Expr] = "expr";
|
||||
|
||||
lookup_table[AST_Add] = "+";
|
||||
|
@ -69,9 +69,20 @@ void AST_init() {
|
|||
lookup_table[AST_Box] = "box";
|
||||
lookup_table[AST_Fun] = "fun";
|
||||
|
||||
lookup_table[AST_Call] = "funcall";
|
||||
lookup_table[AST_Typecast] = "cast";
|
||||
lookup_table[AST_Transmute] = "as";
|
||||
lookup_table[AST_Condition] = "condition";
|
||||
lookup_table[AST_List] = "list";
|
||||
lookup_table[AST_ExprList] = "expr list";
|
||||
lookup_table[AST_ArgList] = "arg list";
|
||||
lookup_table[AST_ParamList] = "param list";
|
||||
lookup_table[AST_StmtList] = "stmt list";
|
||||
lookup_table[AST_IdentList] = "ident list";
|
||||
lookup_table[AST_Type] = "type";
|
||||
lookup_table[AST_Negate] = "-";
|
||||
lookup_table[AST_Parameter] = "parameter";
|
||||
lookup_table[AST_ParamDecl] = "parameter-declaration";
|
||||
}
|
||||
|
||||
const char* AST_node_to_string(const struct AST_Node_t* node) {
|
||||
|
@ -87,7 +98,11 @@ const char* AST_node_to_string(const struct AST_Node_t* node) {
|
|||
case AST_Ident:
|
||||
case AST_Macro:
|
||||
case AST_Import:
|
||||
case AST_Call:
|
||||
case AST_Storage:
|
||||
case AST_Typekind:
|
||||
case AST_Sign:
|
||||
case AST_Scale:
|
||||
case AST_Qualifyier:
|
||||
string = node->value;
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
*/
|
||||
enum AST_SyntaxElement_t {
|
||||
AST_Stmt = 0,
|
||||
AST_Module,
|
||||
AST_Expr,
|
||||
// Literals
|
||||
AST_Int,
|
||||
|
@ -58,7 +59,22 @@ enum AST_SyntaxElement_t {
|
|||
AST_Fun,
|
||||
AST_Import,
|
||||
// amount of variants
|
||||
// in this enum
|
||||
// in this enums
|
||||
AST_List,
|
||||
AST_ExprList,
|
||||
AST_ArgList,
|
||||
AST_ParamList,
|
||||
AST_StmtList,
|
||||
AST_IdentList,
|
||||
AST_Storage,
|
||||
AST_Type,
|
||||
AST_Typekind,
|
||||
AST_Sign,
|
||||
AST_Scale,
|
||||
AST_Negate,
|
||||
AST_Parameter,
|
||||
AST_Qualifyier,
|
||||
AST_ParamDecl,
|
||||
AST_ELEMENT_COUNT
|
||||
};
|
||||
|
||||
|
|
|
@ -2,9 +2,21 @@
|
|||
%{
|
||||
#include <yacc/parser.tab.h>
|
||||
#include <sys/log.h>
|
||||
#include <lex/util.h>
|
||||
|
||||
int yyLineNumber = 1;
|
||||
|
||||
int yylex();
|
||||
|
||||
extern int yyerror(const char* s);
|
||||
|
||||
#define YY_USER_ACTION beginToken(yytext);
|
||||
|
||||
#define YY_INPUT(buf,result,max_size) {\
|
||||
result = nextChar(buf); \
|
||||
if ( result <= 0 ) \
|
||||
result = YY_NULL; \
|
||||
}
|
||||
%}
|
||||
|
||||
/* disable the following functions */
|
||||
|
@ -79,7 +91,17 @@
|
|||
[0-9]+ {DEBUG("\"%s\" tokenized with \'ValInt\'", yytext); yylval.string = strdup(yytext); return(ValInt); };
|
||||
[0-9]*\.[0-9]+ {DEBUG("\"%s\" tokenized with \'ValFloat\'", yytext); yylval.string = strdup(yytext); return(ValFloat);};
|
||||
[a-zA-Z_0-9]+ {DEBUG("\"%s\" tokenized with \'Ident\'", yytext); yylval.string = strdup(yytext); return(Ident); };
|
||||
\"([^\"\n])*\" {DEBUG("\"%s\" tokenized with \'ValStr\'", yytext); yylval.string = strdup(yytext); return(ValStr);};
|
||||
\"\"\"([^\"\n]|\\\n)*\"\"\" {DEBUG("\"%s\" tokenized with \'ValMultistr\'", yytext); yylval.string = strdup(yytext); return(ValMultistr);};
|
||||
.;
|
||||
|
||||
\"([^\"\n])*\" {
|
||||
yytext = yytext +1;
|
||||
yytext[yyleng - 2] = 0;
|
||||
|
||||
DEBUG("\"%s\" tokenized with \'ValStr\'", yytext); yylval.string = strdup(yytext); return(ValStr);};
|
||||
\"\"\"([^\"\n]|\\\n)*\"\"\" {
|
||||
yytext = yytext +3;
|
||||
yytext[yyleng - 4] = 0;
|
||||
|
||||
DEBUG("\"%s\" tokenized with \'ValMultistr\'", yytext); yylval.string = strdup(yytext); return(ValMultistr);};
|
||||
[ \r\t] { /* ignore whitespace */ };
|
||||
. { return yytext[0]; /* passthrough unknown token, let parser handle the error */ };
|
||||
%%
|
||||
|
|
|
@ -0,0 +1,79 @@
|
|||
|
||||
#include <lex/util.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
// implementation based on:
|
||||
// https://github.com/sunxfancy/flex-bison-examples/blob/master/error-handling/ccalc.c
|
||||
|
||||
char* buffer = NULL;
|
||||
|
||||
static int eof = 0;
|
||||
static int nRow = 0;
|
||||
static int nBuffer = 0;
|
||||
static int lBuffer = 0;
|
||||
static int nTokenStart = 0;
|
||||
static int nTokenLength = 0;
|
||||
static int nTokenNextStart = 0;
|
||||
|
||||
static void lex_deinit(void) {
|
||||
free(buffer);
|
||||
}
|
||||
|
||||
void lex_init(void) {
|
||||
buffer = malloc(MAX_READ_BUFFER_SIZE);
|
||||
atexit(lex_deinit);
|
||||
}
|
||||
|
||||
void beginToken(char *t) {
|
||||
nTokenStart = nTokenNextStart;
|
||||
nTokenLength = (int) strlen(t);
|
||||
nTokenNextStart = nBuffer + 1;
|
||||
|
||||
yylloc.first_line = nRow;
|
||||
yylloc.first_column = nTokenStart;
|
||||
yylloc.last_line = nRow;
|
||||
yylloc.last_column = nTokenStart + nTokenLength - 1;
|
||||
}
|
||||
|
||||
int nextChar(char *dst) {
|
||||
int frc;
|
||||
|
||||
if (eof)
|
||||
return 0;
|
||||
|
||||
while (nBuffer >= lBuffer) {
|
||||
frc = getNextLine();
|
||||
if (frc != 0) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
dst[0] = buffer[nBuffer];
|
||||
nBuffer += 1;
|
||||
|
||||
return dst[0] != 0;
|
||||
}
|
||||
|
||||
int getNextLine(void) {
|
||||
char *p;
|
||||
|
||||
nBuffer = 0;
|
||||
nTokenStart = -1;
|
||||
nTokenNextStart = 1;
|
||||
eof = 0;
|
||||
|
||||
p = fgets(buffer, MAX_READ_BUFFER_SIZE, yyin);
|
||||
if (p == NULL) {
|
||||
if (ferror(yyin)) {
|
||||
return -1;
|
||||
}
|
||||
eof = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
nRow += 1;
|
||||
lBuffer = (int) strlen(buffer);
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
|
||||
#ifndef LEX_UTIL_H_
|
||||
#define LEX_UTIL_H_
|
||||
|
||||
#include <yacc/parser.tab.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define MAX_READ_BUFFER_SIZE 1000
|
||||
|
||||
extern FILE* yyin;
|
||||
extern YYLTYPE yylloc;
|
||||
extern char* buffer;
|
||||
|
||||
/**
|
||||
* @brief Initialize global state needed for the lexer
|
||||
*/
|
||||
void lex_init(void);
|
||||
|
||||
/**
|
||||
* @brief Begin counting a new token. This will fill the global struct yylloc.
|
||||
* @param t the text of the token. Must be null terminated
|
||||
*/
|
||||
[[gnu::nonnull(1)]]
|
||||
void beginToken(char *t);
|
||||
|
||||
/**
|
||||
* @brief Stores the next character into the supplied buffer
|
||||
* @param dst the buffer to store character in
|
||||
*/
|
||||
int nextChar(char *dst);
|
||||
|
||||
/**
|
||||
* @brief Reads the next line from yyin into a global buffer
|
||||
*/
|
||||
int getNextLine(void);
|
||||
|
||||
#endif // LEX_UTIL_H_
|
12
src/main.c
12
src/main.c
|
@ -2,10 +2,13 @@
|
|||
#include <stdlib.h>
|
||||
#include <sys/log.h>
|
||||
#include <yacc/parser.tab.h>
|
||||
#include <sys/col.h>
|
||||
#include <lex/util.h>
|
||||
|
||||
#define LOG_LEVEL LOG_LEVEL_DEBUG
|
||||
|
||||
extern FILE *yyin;
|
||||
AST_NODE_PTR root;
|
||||
|
||||
/**
|
||||
* @brief Log a debug message to inform about beginning exit procedures
|
||||
|
@ -41,6 +44,10 @@ void setup(void) {
|
|||
// actual setup
|
||||
AST_init();
|
||||
|
||||
col_init();
|
||||
|
||||
lex_init();
|
||||
|
||||
DEBUG("finished starting up gemstone...");
|
||||
}
|
||||
|
||||
|
@ -65,7 +72,12 @@ int main(int argc, char *argv[]) {
|
|||
}
|
||||
yyin = file;
|
||||
|
||||
root = AST_new_node(AST_Module, NULL);
|
||||
yyparse();
|
||||
|
||||
FILE *output = fopen("test.txt", "w");
|
||||
AST_fprint_graphviz(output, root);
|
||||
fclose(output);
|
||||
AST_delete_node(root);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,87 @@
|
|||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/col.h>
|
||||
#include <sys/log.h>
|
||||
|
||||
#ifdef __unix__
|
||||
#include <unistd.h>
|
||||
#elif defined(_WIN32) || defined(WIN32)
|
||||
#include <Windows.h>
|
||||
#endif
|
||||
|
||||
char *RED;
|
||||
char *YELLOW;
|
||||
char *MAGENTA;
|
||||
char *CYAN;
|
||||
char *GREEN;
|
||||
char *RESET;
|
||||
char *BOLD;
|
||||
char *FAINT;
|
||||
|
||||
void col_init(void) {
|
||||
if (stdout_supports_ansi_esc()) {
|
||||
enable_ansi_colors();
|
||||
} else {
|
||||
disable_ansi_colors();
|
||||
}
|
||||
}
|
||||
|
||||
void disable_ansi_colors() {
|
||||
DEBUG("disabling ANSI escape codes");
|
||||
|
||||
RED = "";
|
||||
YELLOW = "";
|
||||
MAGENTA = "";
|
||||
CYAN = "";
|
||||
GREEN = "";
|
||||
RESET = "";
|
||||
BOLD = "";
|
||||
FAINT = "";
|
||||
}
|
||||
|
||||
void enable_ansi_colors() {
|
||||
DEBUG("enabling ANSI escape codes");
|
||||
|
||||
RED = "\x1b[31m";
|
||||
YELLOW = "\x1b[33m";
|
||||
MAGENTA = "\x1b[35m";
|
||||
CYAN = "\x1b[36m";
|
||||
GREEN = "\x1b[32m";
|
||||
RESET = "\x1b[0m";
|
||||
BOLD = "\x1b[1m";
|
||||
FAINT = "\x1b[2m";
|
||||
}
|
||||
|
||||
int stdout_supports_ansi_esc() {
|
||||
|
||||
#ifdef __unix__
|
||||
// check if TTY
|
||||
if (isatty(STDOUT_FILENO)) {
|
||||
const char *colors = getenv("COLORTERM");
|
||||
// check if colors are set and allowed
|
||||
if (colors != NULL && (strcmp(colors, "truecolor") == 0 || strcmp(colors, "24bit") == 0)) {
|
||||
return ANSI_ENABLED;
|
||||
}
|
||||
}
|
||||
#elif defined(_WIN32) || defined(WIN32)
|
||||
// see:
|
||||
// https://stackoverflow.com/questions/63913005/how-to-test-if-console-supports-ansi-color-codes
|
||||
DWORD mode;
|
||||
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
|
||||
if (!GetConsoleMode(hConsole, &mode)) {
|
||||
ERROR("failed to get console mode");
|
||||
return ANSI_ENABLED;
|
||||
}
|
||||
|
||||
if ((mode & ENABLE_VIRTUAL_TERMINAL_INPUT) |
|
||||
(mode & ENABLE_VIRTUAL_TERMINAL_PROCESSING)) {
|
||||
return ANSI_ENABLED;
|
||||
}
|
||||
#else
|
||||
#warning "unsupported platform, ASNI escape codes disabled by default"
|
||||
#endif
|
||||
|
||||
return ASNI_DISABLED;
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
|
||||
#ifndef COLORS_H_
|
||||
#define COLORS_H_
|
||||
|
||||
#define ANSI_ENABLED 1
|
||||
#define ASNI_DISABLED 0
|
||||
|
||||
// Common escape codes
|
||||
// can be used to print colored text
|
||||
extern char *RED;
|
||||
extern char *YELLOW;
|
||||
extern char *MAGENTA;
|
||||
extern char *CYAN;
|
||||
extern char *GREEN;
|
||||
extern char *RESET;
|
||||
extern char *BOLD;
|
||||
extern char *FAINT;
|
||||
|
||||
/**
|
||||
* @brief Initialize global state
|
||||
*/
|
||||
void col_init(void);
|
||||
|
||||
/**
|
||||
* @brief Enable ANSI escape codes. This will set the correct escape codes to
|
||||
* the global strings above.
|
||||
*/
|
||||
void enable_ansi_colors();
|
||||
|
||||
/**
|
||||
* @brief Disable ANSI escape codes. This will set all the above global strings to be empty.
|
||||
*/
|
||||
void disable_ansi_colors();
|
||||
|
||||
/**
|
||||
* @brief Check if stdout may support ANSI escape codes.
|
||||
* @attention This function may report escape codes to be unavailable even if they actually are.
|
||||
* @return ANSI_ENABLED if escape sequences are supported ASNI_DISABLED otherwise
|
||||
*/
|
||||
[[nodiscard]]
|
||||
int stdout_supports_ansi_esc();
|
||||
|
||||
#endif // COLORS_H_
|
|
@ -1,16 +1,73 @@
|
|||
%{
|
||||
%locations
|
||||
%define parse.error verbose
|
||||
|
||||
%code requires {
|
||||
#include <sys/log.h>
|
||||
#include <ast/ast.h>
|
||||
#include <sys/col.h>
|
||||
extern int yylineno;
|
||||
|
||||
int yyerror(char*);
|
||||
|
||||
int yyerror(const char*);
|
||||
|
||||
extern char* buffer;
|
||||
extern int yylineno;
|
||||
|
||||
extern int yylex();
|
||||
%}
|
||||
extern AST_NODE_PTR root;
|
||||
|
||||
}
|
||||
|
||||
%union {
|
||||
char *string;
|
||||
AST_NODE_PTR node_ptr;
|
||||
}
|
||||
|
||||
%type <node_ptr> operation
|
||||
%type <node_ptr> boxaccess
|
||||
%type <node_ptr> boxselfaccess
|
||||
%type <node_ptr> statement
|
||||
%type <node_ptr> statementlist
|
||||
%type <node_ptr> assign
|
||||
%type <node_ptr> oparith
|
||||
%type <node_ptr> decl
|
||||
%type <node_ptr> definition
|
||||
%type <node_ptr> while
|
||||
%type <node_ptr> funcall
|
||||
%type <node_ptr> boxcall
|
||||
%type <node_ptr> branchhalf
|
||||
%type <node_ptr> branchfull
|
||||
%type <node_ptr> branchelse
|
||||
%type <node_ptr> branchelseif
|
||||
%type <node_ptr> branchif
|
||||
%type <node_ptr> type
|
||||
%type <node_ptr> identlist
|
||||
%type <node_ptr> storagequalifier
|
||||
%type <node_ptr> typekind
|
||||
%type <node_ptr> scale
|
||||
%type <node_ptr> sign
|
||||
%type <node_ptr> expr
|
||||
%type <node_ptr> oplogic
|
||||
%type <node_ptr> opbool
|
||||
%type <node_ptr> opbit
|
||||
%type <node_ptr> moduleimport
|
||||
%type <node_ptr> programbody
|
||||
%type <node_ptr> fundef
|
||||
%type <node_ptr> box
|
||||
%type <node_ptr> typedef
|
||||
%type <node_ptr> exprlist
|
||||
%type <node_ptr> argumentlist
|
||||
%type <node_ptr> paramlist
|
||||
%type <node_ptr> params
|
||||
%type <node_ptr> IOqualifyier
|
||||
%type <node_ptr> paramdecl
|
||||
%type <node_ptr> boxbody
|
||||
%type <node_ptr> boxcontent
|
||||
%type <node_ptr> typecast
|
||||
%type <node_ptr> reinterpretcast
|
||||
%type <node_ptr> program
|
||||
|
||||
|
||||
%token KeyInt
|
||||
%token KeyFloat
|
||||
%token KeySelf
|
||||
|
@ -55,8 +112,11 @@
|
|||
%token FunFunname
|
||||
%token FunLineno
|
||||
%token FunExtsupport
|
||||
%token Invalid
|
||||
|
||||
/* Operator associativity */
|
||||
/* Operators at lower line number have lower precedence */
|
||||
/* Operators in same line have same precedence */
|
||||
%right '='
|
||||
%left OpOr
|
||||
%left OpXor
|
||||
|
@ -72,168 +132,452 @@
|
|||
%left '(' ')'
|
||||
|
||||
%%
|
||||
program: program programbody
|
||||
| programbody;
|
||||
program: program programbody {AST_push_node(root, $2);}
|
||||
| programbody {AST_push_node(root, $1);};
|
||||
|
||||
programbody: moduleimport
|
||||
| fundef
|
||||
| box
|
||||
| definition
|
||||
| decl
|
||||
| typedef;
|
||||
|
||||
expr: ValFloat
|
||||
| ValInt
|
||||
| ValMultistr
|
||||
| ValStr
|
||||
| Ident
|
||||
| operation
|
||||
| boxaccess
|
||||
| boxselfaccess
|
||||
| typecast
|
||||
| reinterpretcast;
|
||||
|
||||
exprlist: expr ',' exprlist
|
||||
| expr;
|
||||
|
||||
argumentlist: argumentlist '(' exprlist ')'
|
||||
| ;
|
||||
programbody: moduleimport {$$ = $1;}
|
||||
| fundef{$$ = $1;}
|
||||
| box{$$ = $1;}
|
||||
| definition{$$ = $1;}
|
||||
| decl{$$ = $1;}
|
||||
| typedef{$$ = $1;};
|
||||
|
||||
|
||||
fundef: KeyFun Ident paramlist '{' statementlist'}' { DEBUG("Function");};
|
||||
|
||||
paramlist: paramlist '(' params ')'
|
||||
| paramlist '(' ')'
|
||||
| '(' params ')'
|
||||
| '(' ')';
|
||||
expr: ValFloat {$$ = AST_new_node(AST_Float, $1);}
|
||||
| ValInt {$$ = AST_new_node(AST_Int, $1);}
|
||||
| ValMultistr {$$ = AST_new_node(AST_String, $1);}
|
||||
| ValStr {$$ = AST_new_node(AST_String, $1);}
|
||||
| Ident {$$ = AST_new_node(AST_Ident, $1);}
|
||||
| operation {$$ = $1;}
|
||||
| boxaccess {$$ = $1;}
|
||||
| boxselfaccess{$$ = $1;}
|
||||
| typecast{$$ = $1;}
|
||||
| reinterpretcast{$$ = $1;}
|
||||
|
||||
params: IOqualifyier paramdecl ',' params
|
||||
| IOqualifyier paramdecl;
|
||||
exprlist: expr ',' exprlist {AST_push_node($3, $1);
|
||||
$$ = $3;}
|
||||
| expr {AST_NODE_PTR list = AST_new_node(AST_ExprList, NULL);
|
||||
AST_push_node(list, $1);
|
||||
$$ = list;};
|
||||
|
||||
IOqualifyier: KeyIn
|
||||
| KeyOut
|
||||
| KeyIn KeyOut
|
||||
| KeyOut KeyIn
|
||||
| ;
|
||||
argumentlist: argumentlist '(' exprlist ')' {AST_push_node($1, $3);
|
||||
$$ = $1;}
|
||||
| '(' exprlist ')'{AST_NODE_PTR list = AST_new_node(AST_ArgList, NULL);
|
||||
AST_push_node(list, $2);
|
||||
$$ = list;}
|
||||
| argumentlist '(' ')'
|
||||
| '(' ')'{AST_NODE_PTR list = AST_new_node(AST_ArgList, NULL);
|
||||
$$ = list;};
|
||||
|
||||
typecast: expr KeyAs type %prec KeyAs { DEBUG("Type-Cast"); };
|
||||
|
||||
reinterpretcast: '(' type ')' expr { DEBUG("Reinterpret-Cast"); };
|
||||
fundef: KeyFun Ident paramlist '{' statementlist'}' {AST_NODE_PTR fun = AST_new_node(AST_Fun, NULL);
|
||||
AST_NODE_PTR ident = AST_new_node(AST_Ident, $2);
|
||||
AST_push_node(fun, ident);
|
||||
AST_push_node(fun, $3);
|
||||
AST_push_node(fun, $5);
|
||||
$$ = fun;
|
||||
DEBUG("Function");};
|
||||
|
||||
paramdecl: type ':' Ident { DEBUG("Param-Declaration"); };
|
||||
paramlist: paramlist '(' params ')' {AST_push_node($1, $3);
|
||||
$$ = $1;}
|
||||
| paramlist '(' ')'{$$ = $1;}
|
||||
| '(' params ')' {AST_NODE_PTR list = AST_new_node(AST_List, NULL);
|
||||
AST_push_node(list, $2);
|
||||
$$ = list;}
|
||||
| '(' ')' {$$ = AST_new_node(AST_List, NULL);};
|
||||
|
||||
box: KeyType KeyBox ':' Ident '{' boxbody '}' { DEBUG("Box"); }
|
||||
| KeyType KeyBox ':' Ident '{' '}';
|
||||
params: IOqualifyier paramdecl ',' params {AST_NODE_PTR parameter = AST_new_node(AST_Parameter, NULL);
|
||||
AST_push_node(parameter, $1);
|
||||
AST_push_node(parameter, $2);
|
||||
AST_push_node($4, parameter);
|
||||
$$ = $4;}
|
||||
| IOqualifyier paramdecl {AST_NODE_PTR list = AST_new_node(AST_ParamList, NULL);
|
||||
AST_NODE_PTR parameter = AST_new_node(AST_Parameter, NULL);
|
||||
AST_push_node(parameter, $1);
|
||||
AST_push_node(parameter, $2);
|
||||
AST_push_node(list, parameter);
|
||||
$$ = list;};
|
||||
|
||||
boxbody: boxbody boxcontent
|
||||
| boxcontent;
|
||||
IOqualifyier: KeyIn { AST_NODE_PTR in = AST_new_node(AST_Qualifyier, "in");
|
||||
AST_NODE_PTR list = AST_new_node(AST_List, NULL);
|
||||
AST_push_node(list, in);
|
||||
$$ = list;}
|
||||
| KeyOut{ AST_NODE_PTR out = AST_new_node(AST_Qualifyier, "out");
|
||||
AST_NODE_PTR list = AST_new_node(AST_List, NULL);
|
||||
AST_push_node(list, out);
|
||||
$$ = list;}
|
||||
| KeyIn KeyOut{ AST_NODE_PTR in = AST_new_node(AST_Qualifyier, "in");
|
||||
AST_NODE_PTR out = AST_new_node(AST_Qualifyier, "out");
|
||||
AST_NODE_PTR list = AST_new_node(AST_List, NULL);
|
||||
AST_push_node(list, in);
|
||||
AST_push_node(list, out);
|
||||
$$ = list;}
|
||||
| KeyOut KeyIn{ AST_NODE_PTR in = AST_new_node(AST_Qualifyier, "in");
|
||||
AST_NODE_PTR out = AST_new_node(AST_Qualifyier, "out");
|
||||
AST_NODE_PTR list = AST_new_node(AST_List, NULL);
|
||||
AST_push_node(list, in);
|
||||
AST_push_node(list, out);
|
||||
$$ = list;}
|
||||
| {$$ = AST_new_node(AST_List, NULL);};
|
||||
|
||||
boxcontent: decl { DEBUG("Box decl Content"); }
|
||||
| definition { DEBUG("Box def Content"); }
|
||||
| fundef { DEBUG("Box fun Content"); };
|
||||
paramdecl: type ':' Ident { AST_NODE_PTR paramdecl = AST_new_node(AST_ParamDecl, NULL);
|
||||
AST_push_node(paramdecl, $1);
|
||||
AST_NODE_PTR ident = AST_new_node(AST_Ident, $3);
|
||||
AST_push_node(paramdecl, ident);
|
||||
$$ = paramdecl;
|
||||
DEBUG("Param-Declaration"); };
|
||||
|
||||
boxselfaccess: KeySelf '.' Ident
|
||||
| KeySelf '.' boxaccess;
|
||||
box: KeyType KeyBox ':' Ident '{' boxbody '}' {AST_NODE_PTR box = AST_new_node(AST_Box, NULL);
|
||||
AST_NODE_PTR ident = AST_new_node(AST_Ident, $4);
|
||||
AST_push_node(box, ident);
|
||||
AST_push_node(box, $6);
|
||||
$$ = box;
|
||||
DEBUG("Box"); }
|
||||
| KeyType KeyBox ':' Ident '{' '}' {AST_NODE_PTR box = AST_new_node(AST_Box, NULL);
|
||||
AST_NODE_PTR ident = AST_new_node(AST_Ident, $4);
|
||||
AST_push_node(box, ident);
|
||||
$$ = box;};
|
||||
|
||||
boxaccess: Ident '.' Ident
|
||||
| Ident '.' boxaccess;
|
||||
boxbody: boxbody boxcontent {AST_push_node($1, $2);
|
||||
$$ = $1;}
|
||||
| boxcontent {AST_NODE_PTR list = AST_new_node(AST_List, NULL);
|
||||
AST_push_node(list, $1);
|
||||
$$ = list;};
|
||||
|
||||
boxcall: boxaccess argumentlist
|
||||
| boxselfaccess argumentlist;
|
||||
boxcontent: decl { $$ = $1;DEBUG("Box decl Content"); }
|
||||
| definition { $$ = $1;DEBUG("Box def Content"); }
|
||||
| fundef { $$ = $1;DEBUG("Box fun Content"); };
|
||||
|
||||
funcall: Ident argumentlist { DEBUG("Function call"); };
|
||||
boxselfaccess: KeySelf '.' Ident {AST_NODE_PTR boxselfaccess = AST_new_node(AST_List, NULL);
|
||||
AST_NODE_PTR self = AST_new_node(AST_Ident, "self");
|
||||
AST_push_node(boxselfaccess, self);
|
||||
AST_NODE_PTR identlist = AST_new_node(AST_IdentList, NULL);
|
||||
AST_NODE_PTR ident = AST_new_node(AST_Ident, $3);
|
||||
AST_push_node(identlist,ident);
|
||||
AST_push_node(boxselfaccess, identlist);
|
||||
$$ = boxselfaccess;}
|
||||
| KeySelf '.' boxaccess {AST_NODE_PTR boxselfaccess = AST_new_node(AST_List, NULL);
|
||||
AST_NODE_PTR self = AST_new_node(AST_Ident, "self");
|
||||
AST_push_node(boxselfaccess, self);
|
||||
AST_push_node(boxselfaccess, $3);
|
||||
$$ = boxselfaccess;};
|
||||
|
||||
moduleimport: KeyImport ValStr { DEBUG("Module-Import"); };
|
||||
boxaccess: Ident '.' Ident {AST_NODE_PTR identlist = AST_new_node(AST_IdentList, NULL);
|
||||
AST_NODE_PTR ident1 = AST_new_node(AST_Ident, $1);
|
||||
AST_NODE_PTR ident2 = AST_new_node(AST_Ident, $3);
|
||||
AST_push_node(identlist,ident1);
|
||||
AST_push_node(identlist,ident2);
|
||||
$$ = identlist;}
|
||||
| Ident '.' boxaccess {AST_NODE_PTR ident = AST_new_node(AST_Ident, $1);
|
||||
AST_push_node($3,ident);
|
||||
$$ = $3;};
|
||||
|
||||
statementlist: statement statementlist
|
||||
| statement;
|
||||
boxcall: boxaccess argumentlist {AST_NODE_PTR boxcall = AST_new_node(AST_Call, NULL);
|
||||
AST_push_node(boxcall, $1);
|
||||
AST_push_node(boxcall, $2);
|
||||
$$ = boxcall;}
|
||||
| boxselfaccess argumentlist {AST_NODE_PTR boxcall = AST_new_node(AST_Call, NULL);
|
||||
AST_push_node(boxcall, $1);
|
||||
AST_push_node(boxcall, $2);
|
||||
$$ = boxcall;};
|
||||
|
||||
statement: assign
|
||||
| decl
|
||||
| definition
|
||||
| while
|
||||
| branch
|
||||
| funcall
|
||||
| boxcall;
|
||||
|
||||
branchif: KeyIf expr '{' statementlist '}' { DEBUG("if"); };
|
||||
branchelse: KeyElse '{' statementlist '}' { DEBUG("if-else"); };
|
||||
branchelseif: KeyElse KeyIf expr '{' statementlist '}' { DEBUG("else-if"); };
|
||||
typecast: expr KeyAs type %prec KeyAs {{AST_NODE_PTR reinterpretcast = AST_new_node(AST_reinterpretcast, NULL);
|
||||
$$ = typecast;
|
||||
DEBUG("Type-Cast"); };
|
||||
|
||||
branchelseifs: branchelseifs branchelseif
|
||||
| branchelseif;
|
||||
reinterpretcast: '(' type ')' expr {AST_NODE_PTR reinterpretcast = AST_new_node(AST_reinterpretcast, NULL);
|
||||
$$ = reinterpretcast;
|
||||
DEBUG("Reinterpret-Cast"); };
|
||||
|
||||
branch: branchif branchelseifs
|
||||
| branchif branchelseifs branchelse;
|
||||
|
||||
while: KeyWhile expr '{' statementlist '}' { DEBUG("while"); };
|
||||
funcall: Ident argumentlist {AST_NODE_PTR funcall = AST_new_node(AST_Call, NULL);
|
||||
AST_NODE_PTR ident = AST_new_node(AST_Ident, $1);
|
||||
AST_push_node(funcall, ident);
|
||||
AST_push_node(funcall, $2);
|
||||
$$ = funcall;
|
||||
DEBUG("Function call"); };
|
||||
|
||||
identlist: Ident ',' identlist
|
||||
| Ident;
|
||||
moduleimport: KeyImport ValStr {$$ = AST_new_node(AST_Import, $2);
|
||||
DEBUG("Module-Import"); };
|
||||
|
||||
decl: type ':' identlist
|
||||
| storagequalifier type ':' identlist
|
||||
statementlist: statementlist statement {AST_push_node($1, $2);
|
||||
$$ = $1;}
|
||||
| statement {AST_NODE_PTR list = AST_new_node(AST_StmtList, NULL);
|
||||
AST_push_node(list, $1);
|
||||
$$ = list;};
|
||||
|
||||
definition: decl '=' expr { DEBUG("Definition"); };
|
||||
statement: assign {$$ = $1;}
|
||||
| decl {$$ = $1;}
|
||||
| definition {$$ = $1;}
|
||||
| while {$$ = $1;}
|
||||
| branchfull {$$ = $1;}
|
||||
| funcall {$$ = $1;}
|
||||
| boxcall{$$ = $1;};
|
||||
|
||||
storagequalifier: KeyGlobal
|
||||
| KeyStatic
|
||||
| KeyLocal;
|
||||
branchif: KeyIf expr '{' statementlist '}' { AST_NODE_PTR branch = AST_new_node(AST_If, NULL);
|
||||
AST_push_node(branch, $2);
|
||||
AST_push_node(branch, $4);
|
||||
$$ = branch; };
|
||||
|
||||
branchelse: KeyElse '{' statementlist '}' { AST_NODE_PTR branch = AST_new_node(AST_Else, NULL);
|
||||
AST_push_node(branch, $3);
|
||||
$$ = branch; };
|
||||
|
||||
branchelseif: KeyElse KeyIf expr '{' statementlist '}' { AST_NODE_PTR branch = AST_new_node(AST_IfElse, NULL);
|
||||
AST_push_node(branch, $3);
|
||||
AST_push_node(branch, $5);
|
||||
$$ = branch; };
|
||||
|
||||
branchfull: branchhalf { $$ = $1;};
|
||||
|branchhalf branchelse { AST_push_node($1 , $2);
|
||||
$$ = $1; }
|
||||
branchhalf: branchif { AST_NODE_PTR branch = AST_new_node(AST_Stmt, NULL);
|
||||
AST_push_node(branch, $1);
|
||||
$$ = branch; }
|
||||
| branchhalf branchelseif { AST_push_node($1 , $2);
|
||||
$$ = $1; };
|
||||
|
||||
|
||||
while: KeyWhile expr '{' statementlist '}' {AST_NODE_PTR whilenode = AST_new_node(AST_While, NULL);
|
||||
AST_push_node(whilenode, $2);
|
||||
AST_push_node(whilenode, $4);
|
||||
$$ = whilenode;};
|
||||
|
||||
identlist: Ident ',' identlist {AST_NODE_PTR ident = AST_new_node(AST_Ident, $1);
|
||||
AST_push_node($3, ident);
|
||||
$$ = $3;}
|
||||
| Ident {AST_NODE_PTR list = AST_new_node(AST_IdentList, NULL);
|
||||
AST_NODE_PTR ident = AST_new_node(AST_Ident, $1);
|
||||
AST_push_node(list, ident);
|
||||
$$ = list;};
|
||||
|
||||
decl: type ':' identlist {AST_NODE_PTR decl = AST_new_node(AST_Decl, NULL);
|
||||
AST_push_node(decl, $1);
|
||||
AST_push_node(decl, $3);
|
||||
$$ = decl;}
|
||||
| storagequalifier type ':' identlist {AST_NODE_PTR decl = AST_new_node(AST_Decl, NULL);
|
||||
AST_push_node(decl, $1);
|
||||
AST_push_node(decl, $2);
|
||||
AST_push_node(decl, $4);
|
||||
$$ = decl;}
|
||||
|
||||
|
||||
definition: decl '=' expr { AST_NODE_PTR def = AST_new_node(AST_Def, NULL);
|
||||
AST_push_node(def, $1);
|
||||
AST_push_node(def, $3);
|
||||
$$ = def;
|
||||
DEBUG("Definition"); };
|
||||
|
||||
storagequalifier: KeyGlobal {$$ = AST_new_node(AST_Storage, "global");}
|
||||
| KeyStatic {$$ = AST_new_node(AST_Storage, "static");}
|
||||
| KeyLocal {$$ = AST_new_node(AST_Storage, "local");};
|
||||
|
||||
assign: Ident '=' expr { AST_NODE_PTR assign = AST_new_node(AST_Assign, NULL);
|
||||
AST_NODE_PTR ident = AST_new_node(AST_Ident, $1);
|
||||
AST_push_node(assign, ident);
|
||||
AST_push_node(assign, $3);
|
||||
$$ = assign;
|
||||
DEBUG("Assignment"); }
|
||||
|
||||
assign: Ident '=' expr { DEBUG("Assignment"); }
|
||||
| boxaccess '=' expr
|
||||
| boxselfaccess '=' expr ;
|
||||
|
||||
sign: KeySigned
|
||||
| KeyUnsigned;
|
||||
sign: KeySigned {$$ = AST_new_node(AST_Sign, "signed");}
|
||||
| KeyUnsigned{$$ = AST_new_node(AST_Sign, "unsigned");};
|
||||
|
||||
typedef: KeyType type':' Ident;
|
||||
typedef: KeyType type':' Ident {AST_NODE_PTR typeDef = AST_new_node(AST_Typedef, NULL);
|
||||
AST_push_node(typeDef, $2);
|
||||
AST_NODE_PTR ident = AST_new_node(AST_Ident, $4);
|
||||
AST_push_node(typeDef, ident);
|
||||
$$ = typeDef;};
|
||||
|
||||
scale: scale KeyShort
|
||||
| scale KeyHalf
|
||||
| scale KeyLong
|
||||
| scale KeyDouble
|
||||
| KeyShort
|
||||
| KeyHalf
|
||||
| KeyLong
|
||||
| KeyDouble;
|
||||
scale: scale KeyShort {AST_NODE_PTR shortnode = AST_new_node(AST_Scale, "short");
|
||||
AST_push_node($1, shortnode);
|
||||
$$ = $1;}
|
||||
| scale KeyHalf {AST_NODE_PTR shortnode = AST_new_node(AST_Scale, "half");
|
||||
AST_push_node($1, shortnode);
|
||||
$$ = $1;}
|
||||
| scale KeyLong {AST_NODE_PTR shortnode = AST_new_node(AST_Scale, "long");
|
||||
AST_push_node($1, shortnode);
|
||||
$$ = $1;}
|
||||
| scale KeyDouble {AST_NODE_PTR shortnode = AST_new_node(AST_Scale, "double");
|
||||
AST_push_node($1, shortnode);
|
||||
$$ = $1;}
|
||||
| KeyShort {AST_NODE_PTR scale = AST_new_node(AST_List, NULL);
|
||||
AST_NODE_PTR shortnode = AST_new_node(AST_Scale, "short");
|
||||
AST_push_node(scale, shortnode);
|
||||
$$ = scale;}
|
||||
| KeyHalf {AST_NODE_PTR scale = AST_new_node(AST_List, NULL);
|
||||
AST_NODE_PTR shortnode = AST_new_node(AST_Scale, "half");
|
||||
AST_push_node(scale, shortnode);
|
||||
$$ = scale;}
|
||||
| KeyLong {AST_NODE_PTR scale = AST_new_node(AST_List, NULL);
|
||||
AST_NODE_PTR shortnode = AST_new_node(AST_Scale, "long");
|
||||
AST_push_node(scale, shortnode);
|
||||
$$ = scale;}
|
||||
| KeyDouble {AST_NODE_PTR scale = AST_new_node(AST_List, NULL);
|
||||
AST_NODE_PTR shortnode = AST_new_node(AST_Scale, "double");
|
||||
AST_push_node(scale, shortnode);
|
||||
$$ = scale;};
|
||||
|
||||
typekind: Ident
|
||||
| KeyInt
|
||||
| KeyFloat;
|
||||
typekind: Ident {$$ = AST_new_node(AST_Typekind, $1);}
|
||||
| KeyInt {$$ = AST_new_node(AST_Typekind, "int");}
|
||||
| KeyFloat {$$ = AST_new_node(AST_Typekind, "float");};
|
||||
|
||||
type: typekind
|
||||
| scale typekind
|
||||
| sign typekind
|
||||
| sign scale typekind;
|
||||
type: typekind {AST_NODE_PTR type = AST_new_node(AST_Type, NULL);
|
||||
AST_push_node(type, $1);
|
||||
$$ = type;}
|
||||
| scale typekind {AST_NODE_PTR type = AST_new_node(AST_Type, NULL);
|
||||
AST_push_node(type, $1);
|
||||
AST_push_node(type, $2);
|
||||
$$ = type;}
|
||||
| sign typekind {AST_NODE_PTR type = AST_new_node(AST_Type, NULL);
|
||||
AST_push_node(type, $1);
|
||||
AST_push_node(type, $2);
|
||||
$$ = type;}
|
||||
| sign scale typekind {AST_NODE_PTR type = AST_new_node(AST_Type, NULL);
|
||||
AST_push_node(type, $1);
|
||||
AST_push_node(type, $2);
|
||||
AST_push_node(type, $3);
|
||||
$$ = type;};
|
||||
|
||||
operation: oparith
|
||||
| oplogic
|
||||
| opbool
|
||||
| opbit;
|
||||
operation: oparith {$$ = $1;}
|
||||
| oplogic {$$ = $1;}
|
||||
| opbool {$$ = $1;}
|
||||
| opbit {$$ = $1;};
|
||||
|
||||
oparith: expr '+' expr
|
||||
| expr '-' expr
|
||||
| expr '*' expr
|
||||
| expr '/' expr
|
||||
| '-' expr %prec '*';
|
||||
oparith: expr '+' expr {AST_NODE_PTR add = AST_new_node(AST_Add, NULL);
|
||||
AST_push_node(add, $1);
|
||||
AST_push_node(add, $3);
|
||||
$$ = add;}
|
||||
| expr '-' expr {AST_NODE_PTR subtract = AST_new_node(AST_Sub, NULL);
|
||||
AST_push_node(subtract, $1);
|
||||
AST_push_node(subtract, $3);
|
||||
$$ = subtract;}
|
||||
| expr '*' expr {AST_NODE_PTR mul = AST_new_node(AST_Mul, NULL);
|
||||
AST_push_node(mul, $1);
|
||||
AST_push_node(mul, $3);
|
||||
$$ = mul;}
|
||||
| expr '/' expr {AST_NODE_PTR div = AST_new_node(AST_Div, NULL);
|
||||
AST_push_node(div, $1);
|
||||
AST_push_node(div, $3);
|
||||
$$ = div;}
|
||||
| '-' expr %prec '*'{AST_NODE_PTR negator = AST_new_node(AST_Negate, NULL);
|
||||
AST_push_node(negator, $2);
|
||||
$$ = negator;};
|
||||
|
||||
oplogic: expr OpEquals expr
|
||||
| expr '<' expr
|
||||
| expr '>' expr;
|
||||
oplogic: expr OpEquals expr {AST_NODE_PTR equals = AST_new_node(AST_Eq, NULL);
|
||||
AST_push_node(equals, $1);
|
||||
AST_push_node(equals, $3);
|
||||
$$ = equals;}
|
||||
| expr '<' expr {AST_NODE_PTR less = AST_new_node(AST_Less, NULL);
|
||||
AST_push_node(less, $1);
|
||||
AST_push_node(less, $3);
|
||||
$$ = less;}
|
||||
| expr '>' expr{AST_NODE_PTR greater = AST_new_node(AST_Greater, NULL);
|
||||
AST_push_node(greater, $1);
|
||||
AST_push_node(greater, $3);
|
||||
$$ = greater;};
|
||||
|
||||
opbool: expr OpAnd expr
|
||||
| expr OpOr expr
|
||||
| expr OpXor expr
|
||||
| OpNot expr %prec OpAnd;
|
||||
opbool: expr OpAnd expr {AST_NODE_PTR and = AST_new_node(AST_BoolAnd, NULL);
|
||||
AST_push_node(and, $1);
|
||||
AST_push_node(and, $3);
|
||||
$$ = and;}
|
||||
| expr OpOr expr{AST_NODE_PTR or = AST_new_node(AST_BoolOr, NULL);
|
||||
AST_push_node(or, $1);
|
||||
AST_push_node(or, $3);
|
||||
$$ = or;}
|
||||
| expr OpXor expr{AST_NODE_PTR xor = AST_new_node(AST_BoolXor, NULL);
|
||||
AST_push_node(xor, $1);
|
||||
AST_push_node(xor, $3);
|
||||
$$ = xor;}
|
||||
| OpNot expr %prec OpAnd{AST_NODE_PTR not = AST_new_node(AST_BoolNot, NULL);
|
||||
AST_push_node(not, $2);
|
||||
$$ = not;};
|
||||
|
||||
opbit: expr OpBitand expr
|
||||
| expr OpBitor expr
|
||||
| expr OpBitxor expr
|
||||
| OpBitnot expr %prec OpBitand;
|
||||
opbit: expr OpBitand expr {AST_NODE_PTR and = AST_new_node(AST_BitAnd, NULL);
|
||||
AST_push_node(and, $1);
|
||||
AST_push_node(and, $3);
|
||||
$$ = and;}
|
||||
| expr OpBitor expr{AST_NODE_PTR or = AST_new_node(AST_BitOr, NULL);
|
||||
AST_push_node(or, $1);
|
||||
AST_push_node(or, $3);
|
||||
$$ = or;}
|
||||
| expr OpBitxor expr{AST_NODE_PTR xor = AST_new_node(AST_BitXor, NULL);
|
||||
AST_push_node(xor, $1);
|
||||
AST_push_node(xor, $3);
|
||||
$$ = xor;}
|
||||
| OpBitnot expr %prec OpBitand{AST_NODE_PTR not = AST_new_node(AST_BitNot, NULL);
|
||||
AST_push_node(not, $2);
|
||||
$$ = not;};
|
||||
%%
|
||||
|
||||
int yyerror(char *s) {
|
||||
ERROR("%s", s);
|
||||
return 0;
|
||||
|
||||
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) {
|
||||
return print_message(ERROR, s);
|
||||
}
|
|
@ -29,42 +29,58 @@ def run_check_print_node():
|
|||
assert p.returncode == 0
|
||||
|
||||
assert """0 stmt
|
||||
1 expr
|
||||
2 value
|
||||
1 module
|
||||
2 expr
|
||||
3 value
|
||||
4 value
|
||||
5 while
|
||||
6 if
|
||||
7 else if
|
||||
8 else
|
||||
9 condition
|
||||
10 decl
|
||||
11 assign
|
||||
12 def
|
||||
13 value
|
||||
14 +
|
||||
15 -
|
||||
16 *
|
||||
17 /
|
||||
18 &
|
||||
19 |
|
||||
20 ^
|
||||
21 !
|
||||
22 &&
|
||||
23 ||
|
||||
24 ^^
|
||||
25 !!
|
||||
26 ==
|
||||
27 >
|
||||
28 <
|
||||
29 cast
|
||||
30 as
|
||||
31 value
|
||||
32 value
|
||||
33 typedef
|
||||
34 box
|
||||
35 fun
|
||||
36 value
|
||||
5 value
|
||||
6 while
|
||||
7 if
|
||||
8 else if
|
||||
9 else
|
||||
10 condition
|
||||
11 decl
|
||||
12 assign
|
||||
13 def
|
||||
14 value
|
||||
15 +
|
||||
16 -
|
||||
17 *
|
||||
18 /
|
||||
19 &
|
||||
20 |
|
||||
21 ^
|
||||
22 !
|
||||
23 &&
|
||||
24 ||
|
||||
25 ^^
|
||||
26 !!
|
||||
27 ==
|
||||
28 >
|
||||
29 <
|
||||
30 cast
|
||||
31 as
|
||||
32 funcall
|
||||
33 value
|
||||
34 typedef
|
||||
35 box
|
||||
36 fun
|
||||
37 value
|
||||
38 list
|
||||
39 expr list
|
||||
40 arg list
|
||||
41 param list
|
||||
42 stmt list
|
||||
43 ident list
|
||||
44 value
|
||||
45 type
|
||||
46 value
|
||||
47 value
|
||||
48 value
|
||||
49 -
|
||||
50 parameter
|
||||
51 value
|
||||
52 parameter-declaration
|
||||
""" == p.stdout
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue