commit d8df1c019a874612f0df6d2231581e395714175a Author: cosmonaut Date: Fri Apr 16 00:35:35 2021 -0700 initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e69de29 diff --git a/ast.h b/ast.h new file mode 100644 index 0000000..24e4213 --- /dev/null +++ b/ast.h @@ -0,0 +1,168 @@ +#include +#include +#include + +typedef enum +{ + Assignment, + BinaryExpression, + Boolean, + Comment, + Expression, + ForLoop, + Identifier, + Number, + Return, + String, + UnaryExpression +} SyntaxKind; + +typedef enum +{ + Negate +} UnaryOperator; + +typedef enum +{ + Add, + Subtract +} BinaryOperator; + +typedef union +{ + UnaryOperator unaryOperator; + BinaryOperator binaryOperator; +} Operator; + +typedef union +{ + const char *string; + uint64_t number; +} Value; + +typedef struct Node +{ + SyntaxKind syntaxKind; + struct Node **children; + uint32_t childCount; + union + { + UnaryOperator unaryOperator; + BinaryOperator binaryOperator; + } operator; + Value value; +} Node; + +const char* SyntaxKindString(SyntaxKind syntaxKind) +{ + switch(syntaxKind) + { + case Assignment: return "Assignment"; + case BinaryExpression: return "BinaryExpression"; + case Identifier: return "Identifier"; + case Number: return "Number"; + case String: return "String"; + case UnaryExpression: return "UnaryExpression"; + default: return "Unknown"; + } +} + +Node* MakeIdentifierNode( + const char *id +) { + Node* node = (Node*) malloc(sizeof(Node)); + node->syntaxKind = Identifier; + node->value.string = id; + node->childCount = 0; + return node; +} + +Node* MakeNumberNode( + const char *numberString +) { + char *ptr; + Node* node = (Node*) malloc(sizeof(Node)); + node->syntaxKind = Number; + node->value.number = strtoul(numberString, &ptr, 10); + node->childCount = 0; + return node; +} + +Node* MakeStringNode( + const char *string +) { + Node* node = (Node*) malloc(sizeof(Node)); + node->syntaxKind = String; + node->value.string = string; + node->childCount = 0; + return node; +} + +Node* MakeUnaryNode( + UnaryOperator operator, + Node *child +) { + Node* node = (Node*) malloc(sizeof(Node)); + node->syntaxKind = UnaryExpression; + node->operator.unaryOperator = operator; + node->children = malloc(sizeof(Node*)); + node->children[0] = child; + node->childCount = 1; + return node; +} + +Node* MakeBinaryNode( + BinaryOperator operator, + Node *left, + Node *right +) { + Node* node = (Node*) malloc(sizeof(Node)); + node->syntaxKind = BinaryExpression; + node->operator.binaryOperator = operator; + node->children = malloc(sizeof(Node*) * 2); + node->children[0] = left; + node->children[1] = right; + node->childCount = 2; + return node; +} + +static void PrintBinaryOperator(BinaryOperator expression) +{ + switch (expression) + { + case Add: + printf("+"); + break; + + case Subtract: + printf("-"); + break; + } + + printf("\n"); +} + +static void PrintNode(Node *node) +{ + printf("%s\n", SyntaxKindString(node->syntaxKind)); + switch (node->syntaxKind) + { + case BinaryExpression: + PrintBinaryOperator(node->operator.binaryOperator); + break; + + case Number: + printf("%lu\n", node->value.number); + break; + } +} + +void PrintTree(Node *node) +{ + uint32_t i; + PrintNode(node); + for (i = 0; i < node->childCount; i += 1) + { + PrintTree(node->children[i]); + } +} diff --git a/wraith.lex b/wraith.lex new file mode 100644 index 0000000..c08cdf9 --- /dev/null +++ b/wraith.lex @@ -0,0 +1,35 @@ +%{ +extern int yywrap() { return 1; } +%} + +%% +[0-9]+ return NUMBER; +[a-zA-Z][a-zA-Z0-9]* return ID; +\"[a-zA-Z][a-zA-Z0-9]*\" return STRING; +"+" return PLUS; +"-" return MINUS; +"*" return MULTIPLY; +"/" return DIVIDE; +"%" return MOD; +"<" return LESS_THAN; +">" return GREATER_THAN; +"=" return EQUAL; +"\"" return QUOTE; +"!" return BANG; +"|" return BAR; +"&" return AMPERSAND; +"." return POINT; +"," return COMMA; +";" return SEMICOLON; +":" return COLON; +"?" return QUESTION; +"(" return LEFT_PAREN; +")" return RIGHT_PAREN; +"[" return LEFT_BRACKET; +"]" return RIGHT_BRACKET; +"{" return LEFT_BRACE; +"}" return RIGHT_BRACE; +"//" return COMMENT; +"\n" return NEWLINE; +[ \t] ; +%% diff --git a/wraith.y b/wraith.y new file mode 100644 index 0000000..3a3bd90 --- /dev/null +++ b/wraith.y @@ -0,0 +1,91 @@ +%token NUMBER +%token ID +%token STRING +%token PLUS +%token MINUS +%token MULTIPLY +%token DIVIDE +%token MOD +%token EQUAL +%token LESS_THAN +%token GREATER_THAN +%token QUOTE +%token BANG +%token BAR +%token AMPERSAND +%token POINT +%token COMMA +%token SEMICOLON +%token COLON +%token QUESTION +%token LEFT_PAREN +%token RIGHT_PAREN +%token LEFT_BRACE +%token RIGHT_BRACE +%token LEFT_BRACKET +%token RIGHT_BRACKET +%token COMMENT +%token NEWLINE + +%left PLUS MINUS +%left BANG +%left LEFT_PAREN RIGHT_PAREN + +%{ +#include "ast.h" +#define YYSTYPE struct Node* +%} + +%% +Main : Expression NEWLINE + { + PrintTree($1); + } + +PrimaryExpression : ID + { + $$ = MakeIdentifierNode(yytext); + } + | NUMBER + { + $$ = MakeNumberNode(yytext); + } + | STRING + { + $$ = MakeStringNode(yytext); + } + | LEFT_PAREN Expression RIGHT_PAREN + ; + +UnaryExpression : BANG Expression + { + $$ = MakeUnaryNode(Negate, $2); + } + +BinaryExpression : Expression PLUS Expression + { + $$ = MakeBinaryNode(Add, $1, $3); + } + | Expression MINUS Expression + { + $$ = MakeBinaryNode(Subtract, $1, $3); + } + +Expression : PrimaryExpression + | UnaryExpression + | BinaryExpression + ; +%% + +#include "lex.yy.c" + +/* yacc error handler */ +void yyerror(char *s) +{ + fprintf (stderr, "%s\n", s); +} + +int main(void) +{ + return yyparse(); +}