diff --git a/ast.h b/ast.h index 24e4213..67aab6d 100644 --- a/ast.h +++ b/ast.h @@ -1,19 +1,20 @@ #include #include #include +#include typedef enum { Assignment, BinaryExpression, - Boolean, Comment, + Declaration, Expression, ForLoop, Identifier, Number, Return, - String, + StringLiteral, UnaryExpression } SyntaxKind; @@ -28,18 +29,22 @@ typedef enum Subtract } BinaryOperator; +typedef enum +{ + Bool, + Int, + UInt, + Float, + Double, + String +} PrimitiveType; + typedef union { UnaryOperator unaryOperator; BinaryOperator binaryOperator; } Operator; -typedef union -{ - const char *string; - uint64_t number; -} Value; - typedef struct Node { SyntaxKind syntaxKind; @@ -50,18 +55,37 @@ typedef struct Node UnaryOperator unaryOperator; BinaryOperator binaryOperator; } operator; - Value value; + union + { + char *string; + uint64_t number; + } value; + PrimitiveType type; } Node; +char* strdup (const char* s) +{ + size_t slen = strlen(s); + char* result = malloc(slen + 1); + if(result == NULL) + { + return NULL; + } + + memcpy(result, s, slen+1); + return result; +} + const char* SyntaxKindString(SyntaxKind syntaxKind) { switch(syntaxKind) { case Assignment: return "Assignment"; case BinaryExpression: return "BinaryExpression"; + case Declaration: return "Declaration"; case Identifier: return "Identifier"; case Number: return "Number"; - case String: return "String"; + case StringLiteral: return "StringLiteral"; case UnaryExpression: return "UnaryExpression"; default: return "Unknown"; } @@ -72,7 +96,7 @@ Node* MakeIdentifierNode( ) { Node* node = (Node*) malloc(sizeof(Node)); node->syntaxKind = Identifier; - node->value.string = id; + node->value.string = strdup(id); node->childCount = 0; return node; } @@ -92,8 +116,8 @@ Node* MakeStringNode( const char *string ) { Node* node = (Node*) malloc(sizeof(Node)); - node->syntaxKind = String; - node->value.string = string; + node->syntaxKind = StringLiteral; + node->value.string = strdup(string); node->childCount = 0; return node; } @@ -126,6 +150,43 @@ Node* MakeBinaryNode( return node; } +Node* MakeDeclarationNode( + PrimitiveType type, + const char *id +) { + Node* node = (Node*) malloc(sizeof(Node)); + node->syntaxKind = Declaration; + node->type = type; + node->value.string = strdup(id); + node->childCount = 0; + return node; +} + +Node* MakeAssignmentNode( + Node *left, + Node *right +) { + Node* node = (Node*) malloc(sizeof(Node)); + node->syntaxKind = Assignment; + node->childCount = 2; + node->children = malloc(sizeof(Node*) * 2); + node->children[0] = left; + node->children[1] = right; + return node; +} + +static const char* PrimitiveTypeToString(PrimitiveType type) +{ + switch (type) + { + case Int: return "Int"; + case UInt: return "UInt"; + case Bool: return "Bool"; + } + + return "Unknown"; +} + static void PrintBinaryOperator(BinaryOperator expression) { switch (expression) @@ -142,27 +203,43 @@ static void PrintBinaryOperator(BinaryOperator expression) printf("\n"); } -static void PrintNode(Node *node) +static void PrintNode(Node *node, int tabCount) { - printf("%s\n", SyntaxKindString(node->syntaxKind)); + uint32_t i; + for (i = 0; i < tabCount; i += 1) + { + printf(" "); + } + + printf("%s: ", SyntaxKindString(node->syntaxKind)); switch (node->syntaxKind) { case BinaryExpression: PrintBinaryOperator(node->operator.binaryOperator); break; + case Declaration: + printf("%s %s", PrimitiveTypeToString(node->type), node->value.string); + break; + + case Identifier: + printf("%s", node->value.string); + break; + case Number: - printf("%lu\n", node->value.number); + printf("%lu", node->value.number); break; } + + printf("\n"); } -void PrintTree(Node *node) +void PrintTree(Node *node, uint32_t tabCount) { uint32_t i; - PrintNode(node); + PrintNode(node, tabCount); for (i = 0; i < node->childCount; i += 1) { - PrintTree(node->children[i]); + PrintTree(node->children[i], tabCount + 1); } } diff --git a/wraith.lex b/wraith.lex index c08cdf9..4ed8a6b 100644 --- a/wraith.lex +++ b/wraith.lex @@ -1,11 +1,15 @@ -%{ -extern int yywrap() { return 1; } -%} +%option noyywrap %% [0-9]+ return NUMBER; +"int" return INT; +"uint" return UINT; +"float" return FLOAT; +"double" return DOUBLE; +"string" return STRING; +"bool" return BOOL; [a-zA-Z][a-zA-Z0-9]* return ID; -\"[a-zA-Z][a-zA-Z0-9]*\" return STRING; +\"[a-zA-Z][a-zA-Z0-9]*\" return STRING_LITERAL; "+" return PLUS; "-" return MINUS; "*" return MULTIPLY; @@ -30,6 +34,7 @@ extern int yywrap() { return 1; } "{" return LEFT_BRACE; "}" return RIGHT_BRACE; "//" return COMMENT; -"\n" return NEWLINE; +" " ; +"\n" ; [ \t] ; %% diff --git a/wraith.y b/wraith.y index 3a3bd90..52ec75e 100644 --- a/wraith.y +++ b/wraith.y @@ -1,6 +1,25 @@ +%{ +#include +#include "ast.h" +#define YYSTYPE struct Node* +void yyerror(FILE *fp, char *s) +{ + fprintf (stderr, "%s\n", s); +} +Node **statements; +uint32_t statementCount; +uint32_t i; +%} + %token NUMBER -%token ID +%token INT +%token UINT +%token FLOAT +%token DOUBLE %token STRING +%token BOOL +%token ID +%token STRING_LITERAL %token PLUS %token MINUS %token MULTIPLY @@ -27,25 +46,27 @@ %token COMMENT %token NEWLINE +%parse-param { FILE* fp } + %left PLUS MINUS %left BANG %left LEFT_PAREN RIGHT_PAREN -%{ -#include "ast.h" -#define YYSTYPE struct Node* -%} - %% -Main : Expression NEWLINE +Program : Statements { - PrintTree($1); + for (i = 0; i < statementCount; i += 1) + { + PrintTree(statements[i], 0); + } } -PrimaryExpression : ID +Identifier : ID { $$ = MakeIdentifierNode(yytext); } + +PrimaryExpression : Identifier | NUMBER { $$ = MakeNumberNode(yytext); @@ -75,17 +96,71 @@ Expression : PrimaryExpression | UnaryExpression | BinaryExpression ; + +VariableDeclaration : INT ID + { + $$ = 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); + } + +AssignmentStatement : VariableDeclaration EQUAL Expression + { + $$ = MakeAssignmentNode($1, $3); + } + | Identifier EQUAL Expression + { + $$ = MakeAssignmentNode($1, $3); + } + +Statement : AssignmentStatement + ; + +CompleteStatement : Statement SEMICOLON; + +Statements : Statements CompleteStatement + { + statements = realloc(statements, statementCount + 1); + statements[statementCount] = $2; + statementCount += 1; + } + | + { + $$ = NULL; + } %% #include "lex.yy.c" -/* yacc error handler */ -void yyerror(char *s) +int main(int argc, char *argv[]) { - fprintf (stderr, "%s\n", s); -} + if (argc < 2) + { + printf("Please provide a file.\n"); + return 1; + } -int main(void) -{ - return yyparse(); + FILE *fp = fopen(argv[1], "r"); + yyin = fp; + yyparse(fp); + fclose(fp); + return 0; }