From 4bc7aca15e47ea2d7ff5772596a9a34987203f30 Mon Sep 17 00:00:00 2001
From: cosmonaut <evan@moonside.games>
Date: Sun, 18 Apr 2021 13:14:50 -0700
Subject: [PATCH] stack sequence structure

---
 ast.h      | 121 ++++++++++++++++++++++++++++++++++++++---
 stack.h    |  92 +++++++++++++++++++++++++++++++
 wraith.lex |   1 +
 wraith.y   | 155 ++++++++++++++++++++++++++++++++++++++++-------------
 4 files changed, 324 insertions(+), 45 deletions(-)
 create mode 100644 stack.h

diff --git a/ast.h b/ast.h
index 67aab6d..bf58d26 100644
--- a/ast.h
+++ b/ast.h
@@ -1,3 +1,6 @@
+#ifndef WRAITH_AST_H
+#define WRAITH_AST_H
+
 #include <stdint.h>
 #include <stdlib.h>
 #include <stdio.h>
@@ -9,12 +12,18 @@ typedef enum
     BinaryExpression,
     Comment,
     Declaration,
+    DeclarationSequence,
     Expression,
     ForLoop,
+    FunctionDeclaration,
+    FunctionSignature,
     Identifier,
     Number,
     Return,
+    StatementSequence,
     StringLiteral,
+    StructDeclaration,
+    Type,
     UnaryExpression
 } SyntaxKind;
 
@@ -82,15 +91,33 @@ const char* SyntaxKindString(SyntaxKind syntaxKind)
     {
         case Assignment: return "Assignment";
         case BinaryExpression: return "BinaryExpression";
+        case Comment: return "Comment";
         case Declaration: return "Declaration";
+        case DeclarationSequence: return "DeclarationSequence";
+        case FunctionDeclaration: return "FunctionDeclaration";
+        case FunctionSignature: return "FunctionSignature";
         case Identifier: return "Identifier";
         case Number: return "Number";
+        case Return: return "Return";
+        case StatementSequence: return "StatementSequence";
         case StringLiteral: return "StringLiteral";
+        case StructDeclaration: return "StructDeclaration";
+        case Type: return "Type";
         case UnaryExpression: return "UnaryExpression";
         default: return "Unknown";
     }
 }
 
+Node* MakeTypeNode(
+    PrimitiveType type
+) {
+    Node* node = (Node*) malloc(sizeof(Node));
+    node->syntaxKind = Type;
+    node->type = type;
+    node->childCount = 0;
+    return node;
+}
+
 Node* MakeIdentifierNode(
     const char *id
 ) {
@@ -151,14 +178,15 @@ Node* MakeBinaryNode(
 }
 
 Node* MakeDeclarationNode(
-    PrimitiveType type,
-    const char *id
+    Node* typeNode,
+    Node* identifierNode
 ) {
     Node* node = (Node*) malloc(sizeof(Node));
     node->syntaxKind = Declaration;
-    node->type = type;
-    node->value.string = strdup(id);
-    node->childCount = 0;
+    node->children = (Node**) malloc(sizeof(Node*) * 2);
+    node->childCount = 2;
+    node->children[0] = typeNode;
+    node->children[1] = identifierNode;
     return node;
 }
 
@@ -175,6 +203,80 @@ Node* MakeAssignmentNode(
     return node;
 }
 
+Node* MakeStatementSequenceNode(
+    Node** pNodes,
+    uint32_t nodeCount
+) {
+    int32_t i;
+    Node* node = (Node*) malloc(sizeof(Node));
+    node->syntaxKind = StatementSequence;
+    node->children = (Node**) malloc(sizeof(Node*) * nodeCount);
+    node->childCount = nodeCount;
+    for (i = nodeCount - 1; i >= 0; i -= 1)
+    {
+        node->children[nodeCount - 1 - i] = pNodes[i];
+    }
+    return node;
+}
+
+Node* MakeFunctionSignatureNode(
+    Node *identifierNode,
+    Node* typeNode,
+    Node* arguments
+) {
+    uint32_t i;
+    Node* node = (Node*) malloc(sizeof(Node));
+    node->syntaxKind = FunctionSignature;
+    node->childCount = 3;
+    node->children = (Node**) malloc(sizeof(Node*) * (node->childCount));
+    node->children[0] = identifierNode;
+    node->children[1] = typeNode;
+    node->children[2] = arguments;
+    return node;
+}
+
+Node* MakeFunctionDeclarationNode(
+    Node* functionSignatureNode,
+    Node* functionBodyNode
+) {
+    Node* node = (Node*) malloc(sizeof(Node));
+    node->syntaxKind = FunctionDeclaration;
+    node->childCount = 2;
+    node->children = (Node**) malloc(sizeof(Node*) * 2);
+    node->children[0] = functionSignatureNode;
+    node->children[1] = functionBodyNode;
+    return node;
+}
+
+Node* MakeStructDeclarationNode(
+    Node *identifierNode,
+    Node *declarationSequenceNode
+) {
+    Node* node = (Node*) malloc(sizeof(Node));
+    node->syntaxKind = StructDeclaration;
+    node->childCount = 2;
+    node->children = (Node**) malloc(sizeof(Node*) * 2);
+    node->children[0] = identifierNode;
+    node->children[1] = declarationSequenceNode;
+    return node;
+}
+
+Node* MakeDeclarationSequenceNode(
+    Node **pNodes,
+    uint32_t nodeCount
+) {
+    int32_t i;
+    Node* node = (Node*) malloc(sizeof(Node));
+    node->syntaxKind = DeclarationSequence;
+    node->children = (Node**) malloc(sizeof(Node*) * nodeCount);
+    node->childCount = nodeCount;
+    for (i = nodeCount - 1; i >= 0; i -= 1)
+    {
+        node->children[nodeCount - 1 - i] = pNodes[i];
+    }
+    return node;
+}
+
 static const char* PrimitiveTypeToString(PrimitiveType type)
 {
     switch (type)
@@ -199,8 +301,6 @@ static void PrintBinaryOperator(BinaryOperator expression)
             printf("-");
             break;
     }
-
-    printf("\n");
 }
 
 static void PrintNode(Node *node, int tabCount)
@@ -219,7 +319,10 @@ static void PrintNode(Node *node, int tabCount)
             break;
 
         case Declaration:
-            printf("%s %s", PrimitiveTypeToString(node->type), node->value.string);
+            break;
+
+        case Type:
+            printf("%s", PrimitiveTypeToString(node->type));
             break;
 
         case Identifier:
@@ -243,3 +346,5 @@ void PrintTree(Node *node, uint32_t tabCount)
         PrintTree(node->children[i], tabCount + 1);
     }
 }
+
+#endif /* WRAITH_AST_H */
diff --git a/stack.h b/stack.h
new file mode 100644
index 0000000..deea3d9
--- /dev/null
+++ b/stack.h
@@ -0,0 +1,92 @@
+#ifndef WRAITH_STACK_H
+#define WRAITH_STACK_H
+
+#include <stdint.h>
+#include "ast.h"
+
+typedef struct StackFrame
+{
+    Node **statements;
+    uint32_t statementCount;
+    uint32_t statementCapacity;
+
+    Node **declarations;
+    uint32_t declarationCount;
+    uint32_t declarationCapacity;
+} StackFrame;
+
+typedef struct Stack
+{
+    StackFrame *stackFrames;
+    uint32_t stackCapacity;
+    uint32_t stackIndex;
+} Stack;
+
+Stack* CreateStack()
+{
+    Stack *stack = (Stack*) malloc(sizeof(Stack));
+    stack->stackCapacity = 4;
+    stack->stackFrames = (StackFrame*) malloc(sizeof(StackFrame) * stack->stackCapacity);
+    stack->stackIndex = 0;
+    return stack;
+}
+
+void PushStackFrame(Stack *stack)
+{
+    stack->stackIndex += 1;
+
+    if (stack->stackIndex == stack->stackCapacity)
+    {
+        stack->stackCapacity += 1;
+        stack->stackFrames = (StackFrame*) realloc(stack->stackFrames, sizeof(StackFrame) * stack->stackCapacity);
+
+        stack->stackFrames[stack->stackIndex].statementCapacity = 0;
+        stack->stackFrames[stack->stackIndex].declarationCapacity = 0;
+    }
+
+    stack->stackFrames[stack->stackIndex].statementCount = 0;
+    stack->stackFrames[stack->stackIndex].declarationCount = 0;
+}
+
+void PopStackFrame(Stack *stack)
+{
+    stack->stackIndex -= 1;
+}
+
+void AddStatement(Stack *stack, Node *statementNode)
+{
+    StackFrame *stackFrame = &stack->stackFrames[stack->stackIndex];
+    if (stackFrame->statementCount == stackFrame->statementCapacity)
+    {
+        stackFrame->statementCapacity += 1;
+        stackFrame->statements = (Node**) realloc(stackFrame->statements, stackFrame->statementCapacity);
+    }
+    stackFrame->statements[stackFrame->statementCount] = statementNode;
+    stackFrame->statementCount += 1;
+}
+
+Node** GetStatements(Stack *stack, uint32_t *pCount)
+{
+    *pCount = stack->stackFrames[stack->stackIndex].statementCount;
+    return stack->stackFrames[stack->stackIndex].statements;
+}
+
+void AddDeclaration(Stack *stack, Node *declarationNode)
+{
+    StackFrame *stackFrame = &stack->stackFrames[stack->stackIndex];
+    if (stackFrame->declarationCount == stackFrame->declarationCapacity)
+    {
+        stackFrame->declarationCapacity += 1;
+        stackFrame->declarations = (Node**) realloc(stackFrame->declarations, stackFrame->declarationCapacity);
+    }
+    stackFrame->declarations[stackFrame->declarationCount] = declarationNode;
+    stackFrame->declarationCount += 1;
+}
+
+Node** GetDeclarations(Stack *stack, uint32_t *pCount)
+{
+    *pCount = stack->stackFrames[stack->stackIndex].declarationCount;
+    return stack->stackFrames[stack->stackIndex].declarations;
+}
+
+#endif /* WRAITH_STACK_H */
\ No newline at end of file
diff --git a/wraith.lex b/wraith.lex
index 4ed8a6b..e8f3d36 100644
--- a/wraith.lex
+++ b/wraith.lex
@@ -8,6 +8,7 @@
 "double"                    return DOUBLE;
 "string"                    return STRING;
 "bool"                      return BOOL;
+"struct"                    return STRUCT;
 [a-zA-Z][a-zA-Z0-9]*        return ID;
 \"[a-zA-Z][a-zA-Z0-9]*\"    return STRING_LITERAL;
 "+"                         return PLUS;
diff --git a/wraith.y b/wraith.y
index 52ec75e..3a0e040 100644
--- a/wraith.y
+++ b/wraith.y
@@ -1,14 +1,17 @@
 %{
 #include <stdio.h>
 #include "ast.h"
+#include "stack.h"
 #define YYSTYPE struct Node*
 void yyerror(FILE *fp, char *s)
 {
     fprintf (stderr, "%s\n", s);
 }
-Node **statements;
-uint32_t statementCount;
-uint32_t i;
+
+Stack *stack;
+
+#define YYDEBUG 1
+int yydebug=1;
 %}
 
 %token NUMBER
@@ -18,6 +21,7 @@ uint32_t i;
 %token DOUBLE
 %token STRING
 %token BOOL
+%token STRUCT
 %token ID
 %token STRING_LITERAL
 %token PLUS
@@ -53,14 +57,45 @@ uint32_t i;
 %left LEFT_PAREN RIGHT_PAREN
 
 %%
-Program                 : Statements
+Program                 : Declarations
                         {
-                            for (i = 0; i < statementCount; i += 1)
-                            {
-                                PrintTree(statements[i], 0);
-                            }
+                            Node **declarations;
+                            Node *declarationSequence;
+                            uint32_t declarationCount;
+
+                            declarations = GetDeclarations(stack, &declarationCount);
+                            declarationSequence = MakeDeclarationSequenceNode(declarations, declarationCount);
+
+                            PopStackFrame(stack);
+                            PrintTree(declarationSequence, 0);
                         }
 
+Type                    : INT
+                        {
+                            $$ = MakeTypeNode(Int);
+                        }
+                        | UINT
+                        {
+                            $$ = MakeTypeNode(UInt);
+                        }
+                        | FLOAT
+                        {
+                            $$ = MakeTypeNode(Float);
+                        }
+                        | DOUBLE
+                        {
+                            $$ = MakeTypeNode(Double);
+                        }
+                        | STRING
+                        {
+                            $$ = MakeTypeNode(String);
+                        }
+                        | BOOL
+                        {
+                            $$ = MakeTypeNode(Bool);
+                        }
+                        ;
+
 Identifier              : ID
                         {
                             $$ = MakeIdentifierNode(yytext);
@@ -76,6 +111,9 @@ PrimaryExpression       : Identifier
                             $$ = MakeStringNode(yytext);
                         }
                         | LEFT_PAREN Expression RIGHT_PAREN
+                        {
+                            $$ = $2;
+                        }
                         ;
 
 UnaryExpression         : BANG Expression
@@ -97,29 +135,9 @@ Expression              : PrimaryExpression
                         | BinaryExpression
                         ;
 
-VariableDeclaration     : INT ID
+VariableDeclaration     : Type Identifier SEMICOLON
                         {
-                            $$ = MakeDeclarationNode(Int, yytext);
-                        }
-                        | UINT ID
-                        {
-                            $$ = MakeDeclarationNode(UInt, yytext);
-                        }
-                        | FLOAT ID
-                        {
-                            $$ = MakeDeclarationNode(Float, yytext);
-                        }
-                        | DOUBLE ID
-                        {
-                            $$ = MakeDeclarationNode(Double, yytext);
-                        }
-                        | STRING ID
-                        {
-                            $$ = MakeDeclarationNode(String, yytext);
-                        }
-                        | BOOL ID
-                        {
-                            $$ = MakeDeclarationNode(Bool, yytext);
+                            $$ = MakeDeclarationNode($1, $2);
                         }
 
 AssignmentStatement     : VariableDeclaration EQUAL Expression
@@ -131,20 +149,80 @@ AssignmentStatement     : VariableDeclaration EQUAL Expression
                             $$ = MakeAssignmentNode($1, $3);
                         }
 
-Statement               : AssignmentStatement
+PartialStatement        : AssignmentStatement
+                        | VariableDeclaration
                         ;
 
-CompleteStatement       : Statement SEMICOLON;
+Statement               : PartialStatement SEMICOLON;
 
-Statements              : Statements CompleteStatement
+Statements              : Statement
                         {
-                            statements = realloc(statements, statementCount + 1);
-                            statements[statementCount] = $2;
-                            statementCount += 1;
+                            Node **statements;
+                            uint32_t statementCount;
+
+                            AddStatement(stack, $1);
+
+                            statements = GetStatements(stack, &statementCount);
+                            $$ = MakeStatementSequenceNode(statements, statementCount);
+                            PopStackFrame(stack);
+                        }
+                        | Statement Statements
+                        {
+                            AddStatement(stack, $2);
+                        }
+
+Arguments               : Arguments COMMA VariableDeclaration
+                        | VariableDeclaration
+                        ;
+
+Body                    : LEFT_BRACE Statements RIGHT_BRACE
+                        {
+                            $$ = $2;
+                        }
+
+FunctionSignature       : Type Identifier LEFT_PAREN Arguments RIGHT_PAREN
+                        {
+                            $$ = MakeFunctionSignatureNode($2, $1, $4);
+                        }
+
+FunctionDeclaration     : FunctionSignature Body
+                        {
+                            $$ = MakeFunctionDeclarationNode($1, $2);
+                        }
+
+VariableDeclarations    : VariableDeclaration VariableDeclarations
+                        {
+                            AddDeclaration(stack, $1);
                         }
                         |
                         {
-                            $$ = NULL;
+                            PushStackFrame(stack);
+                        }
+
+StructDeclaration       : STRUCT Identifier LEFT_BRACE VariableDeclarations RIGHT_BRACE
+                        {
+                            Node **declarations;
+                            Node *declarationSequence;
+                            uint32_t declarationCount;
+
+                            declarations = GetDeclarations(stack, &declarationCount);
+                            declarationSequence = MakeDeclarationSequenceNode(declarations, declarationCount);
+                            $$ = MakeStructDeclarationNode($2, declarationSequence);
+
+                            PopStackFrame(stack);
+                        }
+
+Declaration             : StructDeclaration
+                        | FunctionDeclaration
+                        ;
+
+Declarations            : Declaration Declarations
+                        {
+                            AddDeclaration(stack, $1);
+                        }
+                        |
+                        {
+                            PushStackFrame(stack);
                         }
 %%
 
@@ -158,9 +236,12 @@ int main(int argc, char *argv[])
         return 1;
     }
 
+    stack = CreateStack();
+
     FILE *fp = fopen(argv[1], "r");
     yyin = fp;
     yyparse(fp);
     fclose(fp);
+
     return 0;
 }