diff options
Diffstat (limited to 'boot')
| -rw-r--r-- | boot/catboot.c | 1 | ||||
| -rw-r--r-- | boot/common.c | 10 | ||||
| -rw-r--r-- | boot/lex.c | 1 | ||||
| -rw-r--r-- | boot/tree.c | 340 |
4 files changed, 352 insertions, 0 deletions
diff --git a/boot/catboot.c b/boot/catboot.c index e47d4b9..fec47c0 100644 --- a/boot/catboot.c +++ b/boot/catboot.c @@ -22,6 +22,7 @@ #include "common.c" #include "lex.c" +#include "tree.c" const ascii* read_file(const ascii* path) diff --git a/boot/common.c b/boot/common.c index 388aea5..d814538 100644 --- a/boot/common.c +++ b/boot/common.c @@ -62,6 +62,10 @@ check(bool condition, const ascii* message) if (!condition) failure(message); } +// for each entry in a linked list. +#define FOR_EACH(type, cursor, head) \ + for (type cursor = head; cursor != nil; cursor = cursor->next) + // the common size of region memory blocks. #define REGION_SIZE 65536 @@ -156,6 +160,12 @@ string_length(struct String s) return s.length; } +void +string_print(struct String s) +{ + printf("%.*s", (int32)s.length, s.data); +} + // single iteration of the CRC32 checksum algorithm // described in POSIX. // see: https://pubs.opengroup.org/onlinepubs/9799919799/utilities/cksum.html diff --git a/boot/lex.c b/boot/lex.c index db0173e..9a94c55 100644 --- a/boot/lex.c +++ b/boot/lex.c @@ -219,6 +219,7 @@ token_new(enum Token_Kind kind, struct Span span, struct Cursor location, union .kind = kind, .span = span, .value = value, + .location = location, }; } diff --git a/boot/tree.c b/boot/tree.c new file mode 100644 index 0000000..339f12c --- /dev/null +++ b/boot/tree.c @@ -0,0 +1,340 @@ +/* + * abstract syntax tree types for a catskill source. + */ + +enum Unary_Operation +{ + UNARY_MINUS, + UNARY_NOT, + + UNARY_BITWISE_NOT, +}; + +const ascii* +unary_operation_to_string(enum Unary_Operation operation) +{ + switch (operation) { + case UNARY_MINUS: + return "-"; + case UNARY_NOT: + return "!"; + case UNARY_BITWISE_NOT: + return "~"; + + default: + return "unknown"; + } +} + +enum Binary_Operation +{ + BINARY_PLUS, + BINARY_MINUS, + BINARY_MULTIPLY, + BINARY_DIVIDE, + BINARY_MODULO, + + BINARY_EQUAL, + BINARY_NOT_EQUAL, + BINARY_GREATER_THAN, + BINARY_GREATER_THAN_EQUAL, + BINARY_LESS_THAN, + BINARY_LESS_THAN_EQUAL, + BINARY_AND, + BINARY_OR, + + BINARY_BITWISE_AND, + BINARY_BITWISE_OR, + BINARY_BITWISE_XOR, + BINARY_BITWISE_LEFT_SHIFT, + BINARY_BITWISE_RIGHT_SHIFT, +}; + +const ascii* +binary_operation_to_string(enum Binary_Operation operation) +{ + switch (operation) { + case BINARY_PLUS: + return "+"; + case BINARY_MINUS: + return "-"; + case BINARY_MULTIPLY: + return "*"; + case BINARY_DIVIDE: + return "/"; + case BINARY_MODULO: + return "%"; + + case BINARY_EQUAL: + return "=="; + case BINARY_NOT_EQUAL: + return "!="; + case BINARY_GREATER_THAN: + return ">"; + case BINARY_GREATER_THAN_EQUAL: + return ">="; + case BINARY_LESS_THAN: + return "<"; + case BINARY_LESS_THAN_EQUAL: + return "<="; + case BINARY_AND: + return "&&"; + case BINARY_OR: + return "||"; + + case BINARY_BITWISE_AND: + return "&"; + case BINARY_BITWISE_OR: + return "|"; + case BINARY_BITWISE_XOR: + return "^"; + case BINARY_BITWISE_LEFT_SHIFT: + return "<<"; + case BINARY_BITWISE_RIGHT_SHIFT: + return ">>"; + + default: + return "unknown"; + } +} + +enum Expression_Kind +{ + EXPRESSION_NONE, + + EXPRESSION_INTEGER_LITERAL, + EXPRESSION_FLOAT_LITERAL, + EXPRESSION_STRING_LITERAL, + EXPRESSION_BOOLEAN_LITERAL, + EXPRESSION_NAME, + + EXPRESSION_UNARY_OPERATION, + EXPRESSION_BINARY_OPERATION, + + EXPRESSION_GROUP, + EXPRESSION_CALL, + EXPRESSION_SUBSCRIPT, + EXPRESSION_MEMBER, +}; + +struct Expression_Integer_Literal +{ + int64 value; // might not fit entire number given in source. +}; + +struct Expression_Float_Literal +{ + float64 value; +}; + +struct Expression_String_Literal +{ + struct String value; +}; + +struct Expression_Bool_Literal +{ + bool value; +}; + +struct Expression_Name +{ + struct String name; +}; + +struct Expression_Unary_Operator +{ + enum Unary_Operation operation; + struct Expression* operand; +}; + +struct Expression_Binary_Operator +{ + enum Binary_Operation operation; + struct Expression* left_operand; + struct Expression* right_operand; +}; + +struct Expression_Group +{ + struct Expression* inner_expression; +}; + +struct Expression_Call +{ + struct Expression* subject; + struct Expression* arguments; // linked list of expressions. +}; + +struct Expression_Subscript +{ + struct Expression* subject; + struct Expression* index; +}; + +struct Expression_Member +{ + struct Expression* subject; + struct String name; +}; + +union Expression_Value +{ + struct Expression_Integer_Literal integer_literal; + struct Expression_Float_Literal float_literal; + struct Expression_String_Literal string_literal; + struct Expression_Bool_Literal bool_literal; + struct Expression_Name name; + struct Expression_Unary_Operator unary_operator; + struct Expression_Binary_Operator binary_operator; + struct Expression_Group group; + struct Expression_Call call; + struct Expression_Subscript subscript; + struct Expression_Member member; +}; + +struct Expression +{ + enum Expression_Kind kind; + union Expression_Value value; + + struct Span span; + struct Cursor location; + + // if expression is within a group of multiple expressions, + // points to the next expression within it. + struct Expression* next; +}; + +REGION(struct Expression, expression) + +void +expression_print(const struct Expression* expression) +{ + printf("(expr "); + switch (expression->kind) { + case EXPRESSION_NONE: + printf("none"); + break; + case EXPRESSION_INTEGER_LITERAL: + printf("%ld", expression->value.integer_literal.value); + break; + case EXPRESSION_FLOAT_LITERAL: + printf("%lf", expression->value.float_literal.value); + break; + case EXPRESSION_STRING_LITERAL: + printf("\"%s\"", expression->value.string_literal.value.data); + break; + case EXPRESSION_BOOLEAN_LITERAL: + printf("%s", expression->value.bool_literal.value ? "true" : "false"); + break; + case EXPRESSION_NAME: + printf("(name %s)", expression->value.name.name.data); + break; + case EXPRESSION_UNARY_OPERATION: + printf("(unary %s ", unary_operation_to_string(expression->value.unary_operator.operation)); + expression_print(expression->value.unary_operator.operand); + printf(")"); + break; + case EXPRESSION_BINARY_OPERATION: + printf( + "(binary %s ", binary_operation_to_string(expression->value.binary_operator.operation)); + expression_print(expression->value.binary_operator.left_operand); + printf(" "); + expression_print(expression->value.binary_operator.right_operand); + printf(")"); + break; + case EXPRESSION_GROUP: + printf("(group "); + expression_print(expression->value.group.inner_expression); + printf(")"); + break; + case EXPRESSION_CALL: + printf("(call "); + expression_print(expression->value.call.subject); + FOR_EACH(struct Expression*, argument, expression->value.call.arguments) + { + printf(" "); + expression_print(argument); + } + printf(")"); + break; + case EXPRESSION_SUBSCRIPT: + printf("(subscript "); + expression_print(expression->value.subscript.subject); + printf(" "); + expression_print(expression->value.subscript.index); + printf(")"); + break; + case EXPRESSION_MEMBER: + printf("(member "); + expression_print(expression->value.member.subject); + printf(")"); + break; + default: + break; + } + printf(")"); +} + +enum Statement_Kind +{ + STATEMENT_NONE, + STATEMENT_EXPRESSION, +}; + +union Statement_Value +{ + struct Expression* expression; +}; + +struct Statement +{ + enum Statement_Kind kind; + union Statement_Value value; + + struct Span span; + struct Cursor location; + + // if statement is within a group of multiple statements, + // points to the next statement within it. + struct Statement* next; +}; + +REGION(struct Statement, statement) + +void +statement_print(const struct Statement* statement) +{ + printf("(stmt "); + switch (statement->kind) { + case STATEMENT_NONE: + printf("none"); + break; + case STATEMENT_EXPRESSION: { + const struct Expression* expression = statement->value.expression; + expression_print(expression); + break; + } + default: + printf("unknown"); + break; + } + printf(")"); +} + +// the top-level tree of a single catskill source file. +struct Tree +{ + struct Statement* top_level_statements; +}; + +void +tree_print(const struct Tree* tree) +{ + FOR_EACH(struct Statement*, statement, tree->top_level_statements) + { + statement_print(statement); + printf("\n"); + } +} \ No newline at end of file |
