-#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
void vt100ClearScreen() { vt100Escape("[2J"); }
void vt100CursorHome() { vt100Escape("[H"); }
-void vt100CursorPos(int v, int h) { vt100Escape("[%d;%dH", v, h); }
+void vt100CursorPos(int v, int h) { vt100Escape("[%d;%df", v, h); }
void vt100SaveCursor() { vt100Escape("7"); }
void vt100RestoreCursor() { vt100Escape("8"); }
void vt100EnableAlternateBuffer() { vt100Escape("[?1049h"); }
// 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) {
+Node *g_NodeDrawSelected;
+
+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_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"); printf(" %s {", n->data); indent++; for (int i = 0; i < n->childCount; i++) { INDENT NodeDraw(NodeGetChild(n, i)); } indent--; INDENT printf("}"); 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("}"); break; }
+ case NK_Func: { PRINTF("fn"); printf(" %s ", n->data); NodeDraw(NodeGetChild(n, 0)); 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("}"); 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; }
}
-
- vt100DisableNegative();
}
// Input
typedef enum Input {
IN_None,
- IN_SPACE,
- IN_D,
-
IN_H,
IN_J,
IN_K,
IN_L,
+ IN_SPACE,
+ IN_D,
+ IN_A,
+
IN_F,
IN_V,
+ IN_T,
IN_I,
+ IN_W,
IN_N,
IN_S,
IN_C,
const char *IN_STRINGS[IN_COUNT] = {
"IN_None",
- "IN_SPACE",
- "IN_D",
-
"IN_H",
"IN_J",
"IN_K",
"IN_L",
+ "IN_SPACE",
+ "IN_D",
+ "IN_A",
+
"IN_F",
"IN_V",
+ "IN_T",
"IN_I",
+ "IN_W",
"IN_N",
"IN_S",
"IN_C",
while (true) {
c = getch();
switch (c) {
- case ' ': return IN_SPACE;
- case 'd': return IN_D;
-
case 'h': return IN_H;
case 'j': return IN_J;
case 'k': return IN_K;
case 'l': return IN_L;
+ case ' ': return IN_SPACE;
+ case 'd': return IN_D;
+
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;
typedef enum InputAction {
IA_None,
- IA_StartEditing,
- IA_Delete,
-
IA_MoveLeft,
IA_MoveUp,
IA_MoveDown,
IA_MoveRight,
+ IA_StartEditing,
+ IA_Delete,
+
+ IA_AddNamespace,
+ IA_AddStruct,
IA_AddFunc,
IA_AddVar,
+ IA_AddVarDecl,
+ IA_AddType,
IA_AddIf,
+ IA_AddWhile,
IA_AddNum,
IA_AddStr,
IA_AddCall,
const char *IA_STRINGS[IA_COUNT] = {
"IA_None",
- "IA_StartEditing",
- "IA_Delete",
-
"IA_MoveLeft",
"IA_MoveUp",
"IA_MoveDown",
"IA_MoveRight",
+ "IA_StartEditing",
+ "IA_Delete",
+
+ "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]);
+ vt100CursorPos(line++, h-10);
+ printf("%s:%s", NK_STRINGS[nk], (mode == IM_Normal ? "" : " (editing)"));
- for (int i = 0; i < IN_COUNT; i++) {
+ for (int i = IN_L+1; i < IN_COUNT; i++) {
InputAction action = actions[nk][i];
if (action != IA_None) {
- vt100CursorPos(line++, h-30);
+ vt100CursorPos(line++, h-10);
printf("%s %s", IN_STRINGS[i], IA_STRINGS[action]);
}
}
}
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);
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 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_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_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_StartEditing: { mode = IM_Editing; break; }
+ case IA_Delete: { n = NodeRemove(n->parent, n); 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
}
-int main() {
- // Setup
- static InputAction actions[NK_COUNT][IN_COUNT];
-
+void SetupInputActions(InputAction actions[NK_COUNT][IN_COUNT]) {
for (int i = 0; i < NK_COUNT; i++) {
actions[i][IN_H] = IA_MoveLeft;
actions[i][IN_J] = IA_MoveUp;
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_Str][IN_D] = IA_Delete;
+ 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_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;
+}
+
+int main() {
+ // Setup
+ static InputAction actions[NK_COUNT][IN_COUNT];
+ SetupInputActions(actions);
// Main
vt100EnableAlternateBuffer();
vt100DisableAlternateBuffer();
vt100ShowCursor();
- int v, h;
- vt100GetScreenSize(&v, &h);
- printf("Screen Size: %d | %d\n", v, h);
-
- NodeDraw(n, NULL);
+ NodeDraw(n);
+ printf("\n");
return 0;
}