-#include<stdint.h>
-#include<stdbool.h>
-#include<stdio.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdarg.h>
+
// Global defines
#define NEW(TYPE) ((TYPE *)alloc(1, sizeof(TYPE)))
#define NEWARR(TYPE, NUM) ((TYPE *)alloc(NUM, sizeof(TYPE)))
+#define NEWSTR NEWARR(char, STR_SIZE)
// getch
// Node
typedef enum NodeKind {
+ NK_Namespace,
+ NK_Struct,
NK_Func,
- NK_ArgList,
+ NK_VarList,
NK_ExprList,
NK_Var,
+ NK_VarDecl,
+ NK_VarType,
+ NK_Type,
NK_Body,
NK_If,
+ NK_While,
NK_Num,
NK_Str,
NK_Call,
} NodeKind;
const char *NK_STRINGS[NK_COUNT] = {
+ "NK_Namespace",
+ "NK_Struct",
"NK_Func",
- "NK_ArgList",
+ "NK_VarList",
"NK_ExprList",
"NK_Var",
+ "NK_VarDecl",
+ "NK_VarType",
+ "NK_Type",
"NK_Body",
"NK_If",
+ "NK_While",
"NK_Num",
"NK_Str",
"NK_Call",
return prev;
}
-void NodeDraw(Node *n, Node *selected) {
+void NodeDraw(Node *n);
+Node *g_NodeDrawSelected;
+
+void Printf(char* format, ...)
+{
+ va_list argp;
+ va_start(argp, format);
+ while (*format != '\0') {
+ if (*format == '%') {
+ format++;
+ if (*format == '%') {
+ putchar('%');
+ } else if (*format == 'n') {
+ Node *n = va_arg(argp, Node*);
+ NodeDraw(n);
+ } else if (*format == 's') {
+ char *s = va_arg(argp, char*);
+ printf("%s", s);
+ } else if (*format == ',' && format[1] == 'n') {
+ Node *n = va_arg(argp, Node*);
+ for (int i = 0; i < n->childCount; i++) {
+ if (n > 0) printf(", ");
+ NodeDraw(NodeGetChild(n, i));
+ }
+ format++;
+ } else if (*format == ';' && format[1] == 'n') {
+ Node *n = va_arg(argp, Node*);
+ for (int i = 0; i < n->childCount; i++) {
+ if (n > 0) printf("\n");
+ NodeDraw(NodeGetChild(n, i));
+ }
+ format++;
+ } else {
+ fputs("Not implemented", stdout);
+ }
+ } else if (*format == '_') {
+ static bool highlighted = false;
+ if (highlighted) {
+ vt100DisableNegative();
+ highlighted = false;
+ }
+ else if (g_NodeDrawSelected == n) {
+ vt100EnableNegative();
+ highlighted = true;
+ }
+ } else {
+ putchar(*format);
+ }
+ format++;
+ }
+ va_end(argp);
+}
+
+void NodeDraw(Node *n) {
static int indent = 0;
- #define INDENT for (int i = 0; i < indent; i++) printf(" ");
-
- vt100DisableNegative();
- if (n == selected) vt100EnableNegative();
+ #define INDENT printf("\n"); for (int i = 0; i < indent; i++) printf(" ");
+ #define PRINTF(...) do { if (n == g_NodeDrawSelected) vt100EnableNegative(); printf(__VA_ARGS__); vt100DisableNegative(); } while(0);
+
+ // switch (n->kind) {
+ // case NK_Namespace: { PRINTF("namespace"); printf(" %s {", n->data); indent++; for (int i = 0; i < n->childCount; i++) { INDENT NodeDraw(NodeGetChild(n, i)); } indent--; INDENT printf("}\n"); break; }
+ // case NK_Struct: { PRINTF("struct"); printf(" %s {", n->data); indent++; for (int i = 0; i < n->childCount; i++) { INDENT NodeDraw(NodeGetChild(n, i)); } indent--; INDENT printf("}\n"); break; }
+ // case NK_Func: { PRINTF("fn"); printf(" %s ", n->data); NodeDraw(NodeGetChild(n, 0)); INDENT NodeDraw(NodeGetChild(n, 1)); break; }
+ // case NK_VarList:
+ // case NK_ExprList: { PRINTF("("); for (int i = 0; i < n->childCount; i++) { if (i != 0) printf(", "); NodeDraw(NodeGetChild(n, i)); } PRINTF(")"); break; }
+ // case NK_Var: { PRINTF("[%s]", n->data); break; }
+ // case NK_VarDecl: { PRINTF("[%s : ", n->data); NodeDraw(NodeGetChild(n, 0)); printf("]"); break; }
+ // case NK_VarType:
+ // case NK_Type: { PRINTF("%s", n->data); for (int i = 0; i < n->childCount; i++) { printf("%s", i == 0 ? "<" : ", "); NodeDraw(NodeGetChild(n, i)); if (i == n->childCount-1) printf(">"); } break; }
+ // case NK_Body: { PRINTF("{"); indent++; for (int i = 0; i < n->childCount; i++) { INDENT NodeDraw(NodeGetChild(n, i)); } indent--; INDENT PRINTF("}\n"); break; }
+ // case NK_If: { PRINTF("if"); printf(" "); NodeDraw(NodeGetChild(n, 0)); INDENT NodeDraw(NodeGetChild(n, 1)); break; }
+ // case NK_While: { PRINTF("while"); printf(" "); NodeDraw(NodeGetChild(n, 0)); INDENT NodeDraw(NodeGetChild(n, 1)); break; }
+ // case NK_Num: { PRINTF("%s", n->data); break; }
+ // case NK_Str: { PRINTF("'%s'", n->data); break; }
+ // case NK_Call: { PRINTF("!%s ", n->data); NodeDraw(NodeGetChild(n, 0)); break; }
+ // case NK_Op: { if (n->childCount <= 1) { PRINTF("%s", n->data); printf(" "); } for (int i = 0; i < n->childCount; i++) { if (i != 0) { printf(" "); PRINTF("%s", n->data); printf(" "); } NodeDraw(NodeGetChild(n, i)); } break; }
+ // }
+
switch (n->kind) {
- case NK_Func: { printf("fn %s ", n->data); NodeDraw(NodeGetChild(n, 0), selected); printf("\n"); INDENT NodeDraw(NodeGetChild(n, 1), selected); break; }
- case NK_ExprList:
- case NK_ArgList: { printf("("); for (int i = 0; i < n->childCount; i++) { if (i != 0) printf(" "); NodeDraw(NodeGetChild(n, i), selected); } printf(")"); break; }
- case NK_Var: { printf("var %s", n->data); break; }
- case NK_Body: { printf("{\n"); indent++; for (int i = 0; i < n->childCount; i++) { INDENT NodeDraw(NodeGetChild(n, i), selected); printf("\n"); } indent--; INDENT printf("}\n"); break; }
- case NK_If: { printf("if "); NodeDraw(NodeGetChild(n, 0), selected); printf("\n"); INDENT NodeDraw(NodeGetChild(n, 1), selected); break; }
- case NK_Num: { printf("%s", n->data); break; }
- case NK_Str: { printf("'%s'", n->data); break; }
- case NK_Call: { printf("call %s ", n->data); NodeDraw(NodeGetChild(n, 0), selected); break; }
- case NK_Op: { if (n->childCount <= 1) printf("%s ", n->data); for (int i = 0; i < n->childCount; i++) { if (i != 0) printf(" %s ", n->data); NodeDraw(NodeGetChild(n, i), selected); } break; }
+ case NK_Namespace: { Printf("_namespace_ %s {%;n}\n", n->data, n); break; }
+ case NK_Struct: { Printf("_struct_ %s {%;n}\n", n->data, n); break; }
+ case NK_Func: { Printf("_fn_ %s %n %n", n->data, NodeGetChild(n, 0), NodeGetChild(n, 1)); break; }
+ case NK_VarList:
+ case NK_ExprList: { Printf("_(_%,n_)_", n); break; }
+ case NK_Var: { Printf("_[_%s_]_", n->data); break; }
+ case NK_VarDecl: { Printf("_[_%s : %n_]_", n->data, NodeGetChild(n, 0)); break; }
+ case NK_VarType:
+ case NK_Type: { Printf("%s%s%,n%s", n->data, (n->childCount > 0 ? "<" : ""), n, (n->childCount > 0 ? "<" : "")); break; }
+ case NK_Body: { Printf("_{_%;n_}_"); break; }
+ case NK_If: { Printf("_if_ %n %n", NodeGetChild(n, 0), NodeGetChild(n, 1)); break; }
+ case NK_While: { Printf("_while_ %n %n", NodeGetChild(n, 0), NodeGetChild(n, 1)); break; }
+ case NK_Num: { Printf("_%s_", n->data); break; }
+ case NK_Str: { Printf("_'%s'_", n->data); break; }
+ case NK_Call: { Printf("_!%s_%n", n->data, NodeGetChild(n, 0)); break; }
+ case NK_Op: { if (n->childCount <= 1) Printf("_%s_ ", n->data); for (int i = 0; i < n->childCount; i++) { if (i != 0) { Printf(" _%s_ ", n->data); } NodeDraw(NodeGetChild(n, i)); } break; }
}
-
- vt100DisableNegative();
}
// Input
IN_SPACE,
IN_D,
+ IN_A,
IN_H,
IN_J,
IN_F,
IN_V,
+ IN_T,
IN_I,
+ IN_W,
IN_N,
IN_S,
IN_C,
"IN_SPACE",
"IN_D",
+ "IN_A",
"IN_H",
"IN_J",
"IN_F",
"IN_V",
+ "IN_T",
"IN_I",
+ "IN_W",
"IN_N",
"IN_S",
"IN_C",
case 'f': return IN_F;
case 'v': return IN_V;
+ case 't': return IN_T;
case 'i': return IN_I;
+ case 'w': return IN_W;
case 'n': return IN_N;
case 's': return IN_S;
case 'c': return IN_C;
IA_MoveDown,
IA_MoveRight,
+ IA_AddNamespace,
+ IA_AddStruct,
IA_AddFunc,
IA_AddVar,
+ IA_AddVarDecl,
+ IA_AddType,
IA_AddIf,
+ IA_AddWhile,
IA_AddNum,
IA_AddStr,
IA_AddCall,
"IA_MoveDown",
"IA_MoveRight",
+ "IA_AddNamespace",
+ "IA_AddStruct",
"IA_AddFunc",
"IA_AddVar",
+ "IA_AddVarDecl",
+ "IA_AddType",
"IA_AddIf",
+ "IA_AddWhile",
"IA_AddNum",
"IA_AddStr",
"IA_AddCall",
"IA_AddOp",
};
-void DrawInfo(InputAction actions[NK_COUNT][IN_COUNT], NodeKind nk) {
+typedef enum InputMode {
+ IM_Normal,
+ IM_Editing,
+} InputMode;
+
+void DrawInfo(InputAction actions[NK_COUNT][IN_COUNT], NodeKind nk, InputMode mode) {
int v, h;
vt100GetScreenSize(&v, &h);
int line = 2;
vt100CursorPos(line++, h-30);
- printf("%s:", NK_STRINGS[nk]);
+ printf("%s:%s", NK_STRINGS[nk], (mode == IM_Normal ? "" : " (editing)"));
for (int i = 0; i < IN_COUNT; i++) {
InputAction action = actions[nk][i];
}
Node *GetNode(InputAction actions[NK_COUNT][IN_COUNT]) {
- Node *result = NEW(Node); result->kind = NK_Body;
+ Node *result = NEW(Node); result->data = NEWSTR; result->kind = NK_Namespace;
Node * n = result;
Input in;
InputAction action;
- enum {
- Mode_Normal,
- Mode_Editing,
- } mode = Mode_Normal;
+ InputMode mode = IM_Normal;
while (true) {
vt100ClearScreen();
vt100CursorHome();
- NodeDraw(result, n);
- DrawInfo(actions, n->kind);
+ g_NodeDrawSelected = n;
+ NodeDraw(result);
+ g_NodeDrawSelected = NULL;
+ DrawInfo(actions, n->kind, mode);
- if (mode == Mode_Editing) {
+ if (mode == IM_Editing) {
int c = getch();
char *s = (char*)n->data;
int slen = strlen(s);
s[slen-1] = '\0';
}
else if (c == '\n' || c == '\r') {
- mode = Mode_Normal;
+ mode = IM_Normal;
}
else if (slen < STR_SIZE) {
s[slen++] = (char)c;
}
}
- else if (mode == Mode_Normal) {
+ else if (mode == IM_Normal) {
in = InputGet();
if (in == IN_Quit)
action = actions[n->kind][in];
- #define NA(NAME, PARENT, KIND) Node *NAME = NEW(Node); NAME->kind = KIND; NodeAppend(PARENT, NAME);
- #define NS(NAME, PARENT, KIND) Node *NAME = NEW(Node); NAME->kind = KIND; NAME->data = NEWARR(char, STR_SIZE); NodeAppend(PARENT, NAME);
+ #define N(NAME, PARENT, KIND) Node *NAME = NEW(Node); NAME->kind = KIND; NodeAppend(PARENT, NAME);
+ #define S(NAME, PARENT, KIND) Node *NAME = NEW(Node); NAME->kind = KIND; NAME->data = NEWSTR; NodeAppend(PARENT, NAME);
switch (action) {
- case IA_StartEditing: { mode = Mode_Editing; break; }
+ case IA_StartEditing: { mode = IM_Editing; break; }
case IA_Delete: { n = NodeRemove(n->parent, n); break; }
case IA_MoveLeft: { if (n->prev != NULL) n = n->prev; break; }
case IA_MoveUp: { if (n->parent != NULL) n = n->parent; break; }
case IA_MoveRight: { if (n->next != NULL) n = n->next; break; }
- case IA_AddFunc: { NS(n1, n, NK_Func) NA(n2, n1, NK_ArgList) NA(n3, n1, NK_Body) n = n1; mode = Mode_Editing; break; }
- case IA_AddVar: { NS(n1, n, NK_Var) n = n1; mode = Mode_Editing; break; }
- case IA_AddIf: { NA(n1, n, NK_If) NA(n2, n1, NK_ExprList) NA(n3, n1, NK_Body) n = n1; break; }
- case IA_AddNum: { NS(n1, n, NK_Num) n = n1; mode = Mode_Editing; break; }
- case IA_AddStr: { NS(n1, n, NK_Str) n = n1; mode = Mode_Editing; break; }
- case IA_AddCall: { NS(n1, n, NK_Call) NA(n2, n1, NK_ExprList) n = n1; mode = Mode_Editing; break; }
- case IA_AddOp: { NS(n1, n, NK_Op) n = n1; mode = Mode_Editing; break; }
+ case IA_AddNamespace: { S(n1, n, NK_Namespace) n = n1; mode = IM_Editing; break; }
+ case IA_AddStruct: { S(n1, n, NK_Struct) n = n1; mode = IM_Editing; break; }
+ case IA_AddFunc: { S(n1, n, NK_Func) N(n2, n1, NK_VarList) N(n3, n1, NK_Body) n = n1; mode = IM_Editing; break; }
+ case IA_AddVar: { S(n1, n, NK_Var) n = n1; mode = IM_Editing; break; }
+ case IA_AddVarDecl: { S(n1, n, NK_VarDecl) S(n2, n1, NK_VarType) n = n1; mode = IM_Editing; break; }
+ case IA_AddType: { S(n1, n, NK_Type) n = n1; mode = IM_Editing; break; }
+ case IA_AddIf: { N(n1, n, NK_If) N(n2, n1, NK_ExprList) N(n3, n1, NK_Body) n = n2; break; }
+ case IA_AddWhile: { N(n1, n, NK_While) N(n2, n1, NK_ExprList) N(n3, n1, NK_Body) n = n2; break; }
+ case IA_AddNum: { S(n1, n, NK_Num) n = n1; mode = IM_Editing; break; }
+ case IA_AddStr: { S(n1, n, NK_Str) n = n1; mode = IM_Editing; break; }
+ case IA_AddCall: { S(n1, n, NK_Call) N(n2, n1, NK_ExprList) n = n1; mode = IM_Editing; break; }
+ case IA_AddOp: { S(n1, n, NK_Op) n = n1; mode = IM_Editing; break; }
}
#undef NA
actions[i][IN_L] = IA_MoveRight;
}
+ actions[NK_Namespace][IN_D] = IA_Delete;
+ actions[NK_Namespace][IN_SPACE] = IA_StartEditing;
+ actions[NK_Namespace][IN_N] = IA_AddNamespace;
+ actions[NK_Namespace][IN_S] = IA_AddStruct;
+ actions[NK_Namespace][IN_F] = IA_AddFunc;
+
+ actions[NK_Struct][IN_D] = IA_Delete;
+ actions[NK_Struct][IN_SPACE] = IA_StartEditing;
+ actions[NK_Struct][IN_V] = IA_AddVarDecl;
+ actions[NK_Struct][IN_F] = IA_AddFunc;
+
actions[NK_Func][IN_D] = IA_Delete;
actions[NK_Func][IN_SPACE] = IA_StartEditing;
- actions[NK_ArgList][IN_V] = IA_AddVar;
+ actions[NK_VarList][IN_V] = IA_AddVarDecl;
actions[NK_ExprList][IN_V] = IA_AddVar;
actions[NK_ExprList][IN_I] = IA_AddIf;
+ actions[NK_ExprList][IN_W] = IA_AddWhile;
actions[NK_ExprList][IN_N] = IA_AddNum;
actions[NK_ExprList][IN_S] = IA_AddStr;
actions[NK_ExprList][IN_C] = IA_AddCall;
actions[NK_Var][IN_D] = IA_Delete;
actions[NK_Var][IN_SPACE] = IA_StartEditing;
+ actions[NK_VarDecl][IN_D] = IA_Delete;
+ actions[NK_VarDecl][IN_SPACE] = IA_StartEditing;
+
+ actions[NK_VarType][IN_SPACE] = IA_StartEditing;
+ actions[NK_VarType][IN_T] = IA_AddType;
+
+ actions[NK_Type][IN_D] = IA_Delete;
+ actions[NK_Type][IN_SPACE] = IA_StartEditing;
+ actions[NK_Type][IN_T] = IA_AddType;
+
actions[NK_Body][IN_F] = IA_AddFunc;
- actions[NK_Body][IN_V] = IA_AddVar;
+ actions[NK_Body][IN_V] = IA_AddVarDecl;
actions[NK_Body][IN_I] = IA_AddIf;
+ actions[NK_Body][IN_W] = IA_AddWhile;
actions[NK_Body][IN_N] = IA_AddNum;
actions[NK_Body][IN_S] = IA_AddStr;
actions[NK_Body][IN_C] = IA_AddCall;
actions[NK_If][IN_D] = IA_Delete;
+ actions[NK_While][IN_D] = IA_Delete;
+
actions[NK_Num][IN_D] = IA_Delete;
actions[NK_Num][IN_SPACE] = IA_StartEditing;
actions[NK_Op][IN_SPACE] = IA_StartEditing;
actions[NK_Op][IN_V] = IA_AddVar;
actions[NK_Op][IN_I] = IA_AddIf;
+ actions[NK_Op][IN_W] = IA_AddWhile;
actions[NK_Op][IN_N] = IA_AddNum;
actions[NK_Op][IN_S] = IA_AddStr;
actions[NK_Op][IN_C] = IA_AddCall;
vt100GetScreenSize(&v, &h);
printf("Screen Size: %d | %d\n", v, h);
- NodeDraw(n, NULL);
+ NodeDraw(n);
return 0;
}