-#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 {
- NK_Nul,
- NK_Arr,
+typedef enum NodeKind {
+ NK_Namespace,
+ NK_Struct,
+ NK_Func,
+ NK_VarList,
+ NK_ExprList,
+ NK_Var,
+ NK_VarDecl,
+ NK_VarType,
+ NK_Type,
+ NK_Body,
+ NK_If,
+ NK_While,
+ NK_Num,
NK_Str,
+ NK_Call,
+ NK_Op,
NK_COUNT
} NodeKind;
+const char *NK_STRINGS[NK_COUNT] = {
+ "NK_Namespace",
+ "NK_Struct",
+ "NK_Func",
+ "NK_VarList",
+ "NK_ExprList",
+ "NK_Var",
+ "NK_VarDecl",
+ "NK_VarType",
+ "NK_Type",
+ "NK_Body",
+ "NK_If",
+ "NK_While",
+ "NK_Num",
+ "NK_Str",
+ "NK_Call",
+ "NK_Op",
+};
+
typedef struct Node Node;
struct Node {
NodeKind kind;
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;
- for (int i = 0; i < indent; i++)
- printf(" ");
-
- 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_Nul: printf("null\n"); break;
- case NK_Arr: printf("(%d) [\n", n->childCount); for (int i = 0; i < n->childCount; i++) NodeDraw(NodeGetChild(n, i), selected); printf("]\n"); break;
- case NK_Str: printf("'%.16s'\n", (char *)n->data); 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; }
}
-
- if (n == selected) vt100DisableNegative();
}
// Input
typedef enum Input {
IN_None,
- IN_A,
- IN_S,
+ IN_SPACE,
IN_D,
+ IN_A,
IN_H,
IN_J,
IN_K,
IN_L,
- IN_SPACE,
+ IN_F,
+ IN_V,
+ IN_T,
+ IN_I,
+ IN_W,
+ IN_N,
+ IN_S,
+ IN_C,
+ IN_O,
IN_Quit,
IN_COUNT
} Input;
+const char *IN_STRINGS[IN_COUNT] = {
+ "IN_None",
+
+ "IN_SPACE",
+ "IN_D",
+ "IN_A",
+
+ "IN_H",
+ "IN_J",
+ "IN_K",
+ "IN_L",
+
+ "IN_F",
+ "IN_V",
+ "IN_T",
+ "IN_I",
+ "IN_W",
+ "IN_N",
+ "IN_S",
+ "IN_C",
+ "IN_O",
+
+ "IN_Quit",
+};
+
Input InputGet() {
int c;
while (true) {
c = getch();
switch (c) {
- case 'a': return IN_A;
- case 's': return IN_S;
+ case ' ': return IN_SPACE;
case 'd': return IN_D;
case 'h': return IN_H;
case 'k': return IN_K;
case 'l': return IN_L;
- case ' ': return IN_SPACE;
+ 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;
+ case 'o': return IN_O;
case 'q': return IN_Quit;
}
typedef enum InputAction {
IA_None,
- IA_AppendArray,
- IA_AppendString,
+
IA_StartEditing,
IA_Delete,
IA_MoveLeft,
- IA_MoveDown,
IA_MoveUp,
+ 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,
+
IA_COUNT
} InputAction;
+const char *IA_STRINGS[IA_COUNT] = {
+ "IA_None",
+
+ "IA_StartEditing",
+ "IA_Delete",
+
+ "IA_MoveLeft",
+ "IA_MoveUp",
+ "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",
+};
+
+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:%s", NK_STRINGS[nk], (mode == IM_Normal ? "" : " (editing)"));
+
+ for (int i = 0; i < IN_COUNT; i++) {
+ InputAction action = actions[nk][i];
+ if (action != IA_None) {
+ vt100CursorPos(line++, h-30);
+ printf("%s %s", IN_STRINGS[i], IA_STRINGS[action]);
+ }
+ }
+}
+
Node *GetNode(InputAction actions[NK_COUNT][IN_COUNT]) {
- Node * result = NEW(Node);
- result->kind = NK_Arr;
+ 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);
+ 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);
if (c == KEY_BACKSPACE1 || c == KEY_BACKSPACE2) {
s[slen-1] = '\0';
}
- else if (c == 13) {
- mode = Mode_Normal;
+ else if (c == '\n' || c == '\r') {
+ 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 NODE_APPEND(KIND, DATA) Node *newNode = NEW(Node); newNode->kind = KIND; newNode->data = DATA; NodeAppend(n, newNode); n = newNode;
+ #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_AppendArray: { NODE_APPEND(NK_Arr, 0); break; }
- case IA_AppendString: { NODE_APPEND(NK_Str, NEWARR(char, STR_SIZE)); mode = Mode_Editing; break; }
- 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_MoveDown: { if (n->child != NULL) n = n->child; 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_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 NODE_APPEND
+ #undef NA
+ #undef NS
}
}
int main() {
// Setup
- InputAction actions[NK_COUNT][IN_COUNT];
+ static InputAction actions[NK_COUNT][IN_COUNT];
- actions[NK_Arr][IN_A] = IA_AppendArray;
- actions[NK_Arr][IN_S] = IA_AppendString;
- actions[NK_Arr][IN_D] = IA_Delete;
- actions[NK_Arr][IN_H] = IA_MoveLeft;
- actions[NK_Arr][IN_J] = IA_MoveDown;
- actions[NK_Arr][IN_K] = IA_MoveUp;
- actions[NK_Arr][IN_L] = IA_MoveRight;
+ for (int i = 0; i < NK_COUNT; i++) {
+ actions[i][IN_H] = IA_MoveLeft;
+ actions[i][IN_J] = IA_MoveUp;
+ actions[i][IN_K] = IA_MoveDown;
+ 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_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_ExprList][IN_O] = IA_AddOp;
+
+ 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_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_Body][IN_O] = IA_AddOp;
+
+ 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_Str][IN_SPACE] = IA_StartEditing;
actions[NK_Str][IN_D] = IA_Delete;
- actions[NK_Str][IN_H] = IA_MoveLeft;
- actions[NK_Str][IN_J] = IA_MoveDown;
- actions[NK_Str][IN_K] = IA_MoveUp;
- actions[NK_Str][IN_L] = IA_MoveRight;
+ actions[NK_Str][IN_SPACE] = IA_StartEditing;
+
+ actions[NK_Call][IN_D] = IA_Delete;
+ actions[NK_Call][IN_SPACE] = IA_StartEditing;
+
+ actions[NK_Op][IN_D] = IA_Delete;
+ 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;
+ actions[NK_Op][IN_O] = IA_AddOp;
// Main
vt100EnableAlternateBuffer();
vt100GetScreenSize(&v, &h);
printf("Screen Size: %d | %d\n", v, h);
- NodeDraw(n, NULL);
+ NodeDraw(n);
return 0;
}