// Node
-typedef enum {
- NK_Nul,
- NK_Arr,
+typedef enum NodeKind {
+ NK_Func,
+ NK_ArgList,
+ NK_ExprList,
+ NK_Var,
+ NK_Body,
+ NK_If,
+ NK_Num,
NK_Str,
+ NK_Call,
+ NK_Op,
NK_COUNT
} NodeKind;
+const char *NK_STRINGS[NK_COUNT] = {
+ "NK_Func",
+ "NK_ArgList",
+ "NK_ExprList",
+ "NK_Var",
+ "NK_Body",
+ "NK_If",
+ "NK_Num",
+ "NK_Str",
+ "NK_Call",
+ "NK_Op",
+};
+
typedef struct Node Node;
struct Node {
NodeKind kind;
void NodeDraw(Node *n, Node *selected) {
static int indent = 0;
- for (int i = 0; i < indent; i++)
- printf(" ");
+ #define INDENT for (int i = 0; i < indent; i++) printf(" ");
+ vt100DisableNegative();
if (n == selected) vt100EnableNegative();
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_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; }
}
- if (n == selected) vt100DisableNegative();
+ vt100DisableNegative();
}
// Input
typedef enum Input {
IN_None,
- IN_A,
- IN_S,
+ IN_SPACE,
IN_D,
IN_H,
IN_K,
IN_L,
- IN_SPACE,
+ IN_F,
+ IN_V,
+ IN_I,
+ 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_H",
+ "IN_J",
+ "IN_K",
+ "IN_L",
+
+ "IN_F",
+ "IN_V",
+ "IN_I",
+ "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 'i': return IN_I;
+ 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_AddFunc,
+ IA_AddVar,
+ IA_AddIf,
+ 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_AddFunc",
+ "IA_AddVar",
+ "IA_AddIf",
+ "IA_AddNum",
+ "IA_AddStr",
+ "IA_AddCall",
+ "IA_AddOp",
+};
+
+void DrawInfo(InputAction actions[NK_COUNT][IN_COUNT], NodeKind nk) {
+ int v, h;
+ vt100GetScreenSize(&v, &h);
+
+ int line = 2;
+
+ vt100CursorPos(line++, h-30);
+ printf("%s:", NK_STRINGS[nk]);
+
+ 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->kind = NK_Body;
Node * n = result;
vt100ClearScreen();
vt100CursorHome();
NodeDraw(result, n);
+ DrawInfo(actions, n->kind);
if (mode == Mode_Editing) {
int c = getch();
if (c == KEY_BACKSPACE1 || c == KEY_BACKSPACE2) {
s[slen-1] = '\0';
}
- else if (c == 13) {
+ else if (c == '\n' || c == '\r') {
mode = Mode_Normal;
}
else if (slen < STR_SIZE) {
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 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);
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_Delete: { n = NodeRemove(n->parent, n); 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; }
}
- #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_Func][IN_D] = IA_Delete;
+ actions[NK_Func][IN_SPACE] = IA_StartEditing;
+
+ actions[NK_ArgList][IN_V] = IA_AddVar;
+
+ actions[NK_ExprList][IN_V] = IA_AddVar;
+ actions[NK_ExprList][IN_I] = IA_AddIf;
+ 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_Body][IN_F] = IA_AddFunc;
+ actions[NK_Body][IN_V] = IA_AddVar;
+ actions[NK_Body][IN_I] = IA_AddIf;
+ 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_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_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();