Compare commits
6 Commits
2abfa54890
...
dev-feat-p
| Author | SHA1 | Date | |
|---|---|---|---|
| 53e9cb2577 | |||
| 9c94663045 | |||
| d8c0b2a762 | |||
| 3682559a56 | |||
| 1e15ec36d2 | |||
| 9d1a9147b7 |
5
Makefile
5
Makefile
@@ -11,7 +11,10 @@ TARGET := cval.out
|
||||
|
||||
.PHONY: all clean
|
||||
|
||||
all: $(TARGET)
|
||||
all: init $(TARGET)
|
||||
|
||||
init:
|
||||
mkdir -p $(BUILD_DIR)
|
||||
|
||||
$(TARGET): $(OBJ)
|
||||
$(CC) $(CFLAGS) -o $(BUILD_DIR)/$(TARGET) $(OBJ)
|
||||
|
||||
55
README.md
55
README.md
@@ -22,7 +22,7 @@
|
||||
|
||||
## Syntax Spec
|
||||
|
||||
```spec
|
||||
```c
|
||||
program := defn*
|
||||
|
||||
defn := VAL type ID ;
|
||||
@@ -55,3 +55,56 @@ lambda := param_list compound
|
||||
|
||||
compound := LCURLY (stmt)* expr? RCURLY
|
||||
```
|
||||
|
||||
### AST Spec
|
||||
|
||||
```c
|
||||
NODE_PROGRAM:
|
||||
token: PROGRAM
|
||||
children: NODE_DEFN*
|
||||
|
||||
NODE_DEFN:
|
||||
token: VAL
|
||||
children: NODE_TYPE, TOKEN_ID, (NODE_EXPR)?
|
||||
children_count: 2 | 3
|
||||
|
||||
NODE_TYPE_SIMPLE:
|
||||
token: ID
|
||||
children: NODE_ID NODE_TYPE_STAR*
|
||||
children_count: 1+
|
||||
NODE_TYPE_COMPLEX:
|
||||
token: COMPLEX_TYPE
|
||||
children: NODE_TYPE_PARAM NODE_TYPE_OUT
|
||||
NODE_TYPE_PARAM
|
||||
token: TYPE_PARAM
|
||||
children: (NODE_TYPE | NODE_TYPE_COMPLEX)*
|
||||
children_count: 0+
|
||||
NODE_TYPE_OUT
|
||||
token: TYPE_OUT
|
||||
children: (NODE_TYPE | NODE_TYPE_COMPLEX)?
|
||||
|
||||
NODE_EXPR:
|
||||
token: EXPR
|
||||
children: (atom)+
|
||||
// atom definition
|
||||
NODE_NUM:
|
||||
token: NUM
|
||||
NODE_STR:
|
||||
token: STR
|
||||
NODE_LAMBDA:
|
||||
token: LAMBDA
|
||||
children: NODE_PARAM_LIST NODE_COMPOUND
|
||||
NODE_COMPOUND:
|
||||
token: COMPOUND
|
||||
children: (NODE_STMT)* (NODE_EXPR)?
|
||||
children_count: 0+
|
||||
|
||||
|
||||
NODE_PARAM_LIST:
|
||||
token: PARAM_LIST
|
||||
children: NODE_PARAM*
|
||||
NODE_PARAM:
|
||||
token: PARAM
|
||||
children: NODE_TYPE, TOKEN_ID
|
||||
|
||||
```
|
||||
61
include/ast_util.h
Normal file
61
include/ast_util.h
Normal file
@@ -0,0 +1,61 @@
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "globals.h"
|
||||
|
||||
void ast_node_add_child(ASTNode *parent, ASTNode *child);
|
||||
|
||||
void ast_node_free(ASTNode *node);
|
||||
|
||||
void ast_node_print(ASTNode *node, int depth);
|
||||
|
||||
/*
|
||||
NODE SPECIFIC FUNCTIONS
|
||||
*/
|
||||
|
||||
ASTNode *ast_node_program();
|
||||
|
||||
ASTNode *ast_node_defn(Token tok_val, ASTNode *type, ASTNode *id, ASTNode *expr);
|
||||
|
||||
ASTNode *ast_node_type_simple(Token tok_id);
|
||||
|
||||
ASTNode *ast_node_type_complex(Token tok_bracket, ASTNode *type_param, ASTNode *type_out);
|
||||
|
||||
ASTNode *ast_node_type_param();
|
||||
|
||||
ASTNode *ast_node_type_out();
|
||||
|
||||
ASTNode *ast_node_type_star(Token tok_star);
|
||||
|
||||
ASTNode *ast_node_type_void();
|
||||
|
||||
ASTNode *ast_node_id(Token id);
|
||||
|
||||
ASTNode *ast_node_num(Token num);
|
||||
|
||||
ASTNode *ast_node_str(Token str);
|
||||
|
||||
ASTNode *ast_node_star(Token star);
|
||||
|
||||
ASTNode *ast_node_andref(Token andref);
|
||||
|
||||
ASTNode *ast_node_expr(Token caller);
|
||||
|
||||
ASTNode *ast_node_param_list(Token tok_lparen);
|
||||
|
||||
ASTNode *ast_node_param(Token id, ASTNode *type);
|
||||
|
||||
ASTNode *ast_node_compound(Token tok_lcurly);
|
||||
|
||||
ASTNode *ast_node_lambda(ASTNode *param_list, ASTNode *body);
|
||||
|
||||
ASTNode *ast_node_stmt_return(Token tok_return, ASTNode *expr);
|
||||
|
||||
ASTNode *ast_node_stmt_expr(ASTNode *expr);
|
||||
|
||||
ASTNode *ast_node_stmt_if(Token tok_if, ASTNode *condition, ASTNode *then_branch, ASTNode *else_branch);
|
||||
|
||||
ASTNode *ast_node_stmt_set(Token tok_dollar, ASTNode *id, ASTNode *expr);
|
||||
@@ -1,7 +1,10 @@
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* Token Definitions
|
||||
*/
|
||||
typedef enum {
|
||||
LBRACK,
|
||||
RBRACK,
|
||||
@@ -28,7 +31,13 @@ typedef enum {
|
||||
ELSE,
|
||||
|
||||
EOF_TOKEN,
|
||||
ERROR
|
||||
ERROR,
|
||||
// for parser use
|
||||
|
||||
PARSER_USE,
|
||||
|
||||
VOID,
|
||||
|
||||
} TokenType;
|
||||
|
||||
typedef struct {
|
||||
@@ -42,3 +51,46 @@ typedef struct {
|
||||
TokenString data;
|
||||
} Token;
|
||||
|
||||
/**
|
||||
* AST Node Definitions
|
||||
*/
|
||||
|
||||
typedef enum {
|
||||
NODE_PROGRAM,
|
||||
NODE_DEFN,
|
||||
|
||||
NODE_TYPE_SIMPLE,
|
||||
NODE_TYPE_COMPLEX,
|
||||
NODE_TYPE_PARAM,
|
||||
NODE_TYPE_OUT,
|
||||
NODE_TYPE_STAR,
|
||||
|
||||
NODE_EXPR,
|
||||
|
||||
NODE_ID,
|
||||
NODE_NUM,
|
||||
NODE_STR,
|
||||
NODE_STAR,
|
||||
NODE_ANDREF,
|
||||
|
||||
NODE_PARAM_LIST,
|
||||
NODE_PARAM,
|
||||
|
||||
NODE_LAMBDA,
|
||||
NODE_COMPOUND,
|
||||
|
||||
NODE_STMT_RETURN,
|
||||
NODE_STMT_EXPR,
|
||||
NODE_STMT_SET,
|
||||
NODE_STMT_IF,
|
||||
|
||||
} NodeKind;
|
||||
|
||||
typedef struct ASTNode {
|
||||
NodeKind kind;
|
||||
Token token;
|
||||
|
||||
struct ASTNode **children;
|
||||
size_t count;
|
||||
size_t capacity;
|
||||
} ASTNode;
|
||||
@@ -0,0 +1,47 @@
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "globals.h"
|
||||
#include "lex.h"
|
||||
#include "ast_util.h"
|
||||
|
||||
typedef struct Parser {
|
||||
Lexer *lexer;
|
||||
|
||||
Token current;
|
||||
Token peek;
|
||||
|
||||
int flag_error;
|
||||
} Parser;
|
||||
|
||||
Parser *parser_new(Lexer *lexer);
|
||||
|
||||
void parser_free(Parser *parser);
|
||||
|
||||
/*
|
||||
PARSER PARSE FUNCTIONS
|
||||
*/
|
||||
ASTNode *parser_parse_program(Parser *parser);
|
||||
|
||||
ASTNode *parser_parse_defn(Parser *parser);
|
||||
|
||||
ASTNode *parser_parse_type(Parser *parser);
|
||||
|
||||
ASTNode *parser_parse_type_simple(Parser *parser);
|
||||
|
||||
ASTNode *parser_parse_type_complex(Parser *parser);
|
||||
|
||||
ASTNode *parser_parse_expr(Parser *parser);
|
||||
|
||||
ASTNode *parser_parse_atom(Parser *parser);
|
||||
|
||||
ASTNode *parser_parse_stmt(Parser *parser);
|
||||
|
||||
ASTNode *parser_parse_block(Parser *parser);
|
||||
|
||||
ASTNode *parser_parse_lambda(Parser *parser);
|
||||
|
||||
ASTNode *parser_parse_compound(Parser *parser);
|
||||
|
||||
ASTNode *parser_parse_params(Parser *parser);
|
||||
280
src/ast_util.c
Normal file
280
src/ast_util.c
Normal file
@@ -0,0 +1,280 @@
|
||||
#include "ast_util.h"
|
||||
#include "util.h"
|
||||
|
||||
static ASTNode *ast_node_new(NodeKind kind, Token token) {
|
||||
ASTNode *node = malloc(sizeof(ASTNode));
|
||||
node->kind = kind;
|
||||
node->token = token;
|
||||
node->children = NULL;
|
||||
node->count = 0;
|
||||
node->capacity = 0;
|
||||
return node;
|
||||
}
|
||||
|
||||
void ast_node_add_child(ASTNode *parent, ASTNode *child) {
|
||||
if (parent->count >= parent->capacity) {
|
||||
size_t new_capacity = parent->capacity == 0 ? 4 : parent->capacity * 2;
|
||||
parent->children = realloc(parent->children, new_capacity * sizeof(ASTNode *));
|
||||
parent->capacity = new_capacity;
|
||||
}
|
||||
parent->children[parent->count++] = child;
|
||||
}
|
||||
|
||||
void ast_node_free(ASTNode *node) {
|
||||
for (size_t i = 0; i < node->count; i++) {
|
||||
ast_node_free(node->children[i]);
|
||||
}
|
||||
free(node->children);
|
||||
free(node);
|
||||
}
|
||||
|
||||
void ast_node_print(ASTNode *node, int depth) {
|
||||
for (int i = 0; i < depth; i++) {
|
||||
printf(" ");
|
||||
}
|
||||
printf("NodeKind: ");
|
||||
|
||||
switch (node->kind) {
|
||||
case NODE_PROGRAM:
|
||||
printf("NODE_PROGRAM");
|
||||
break;
|
||||
case NODE_DEFN:
|
||||
printf("NODE_DEFN");
|
||||
break;
|
||||
case NODE_TYPE_SIMPLE:
|
||||
printf("NODE_TYPE_SIMPLE");
|
||||
break;
|
||||
case NODE_TYPE_COMPLEX:
|
||||
printf("NODE_TYPE_COMPLEX");
|
||||
break;
|
||||
case NODE_TYPE_PARAM:
|
||||
printf("NODE_TYPE_PARAM");
|
||||
break;
|
||||
case NODE_TYPE_OUT:
|
||||
printf("NODE_TYPE_OUT");
|
||||
break;
|
||||
case NODE_TYPE_STAR:
|
||||
printf("NODE_TYPE_STAR");
|
||||
break;
|
||||
case NODE_EXPR:
|
||||
printf("NODE_EXPR");
|
||||
break;
|
||||
case NODE_ID:
|
||||
printf("NODE_ID");
|
||||
break;
|
||||
case NODE_NUM:
|
||||
printf("NODE_NUM");
|
||||
break;
|
||||
case NODE_STR:
|
||||
printf("NODE_STR");
|
||||
break;
|
||||
case NODE_STAR:
|
||||
printf("NODE_STAR");
|
||||
break;
|
||||
case NODE_ANDREF:
|
||||
printf("NODE_ANDREF");
|
||||
break;
|
||||
case NODE_PARAM_LIST:
|
||||
printf("NODE_PARAM_LIST");
|
||||
break;
|
||||
case NODE_PARAM:
|
||||
printf("NODE_PARAM");
|
||||
break;
|
||||
case NODE_LAMBDA:
|
||||
printf("NODE_LAMBDA");
|
||||
break;
|
||||
case NODE_COMPOUND:
|
||||
printf("NODE_COMPOUND");
|
||||
break;
|
||||
case NODE_STMT_RETURN:
|
||||
printf("NODE_STMT_RETURN");
|
||||
break;
|
||||
case NODE_STMT_EXPR:
|
||||
printf("NODE_STMT_EXPR");
|
||||
break;
|
||||
case NODE_STMT_SET:
|
||||
printf("NODE_STMT_SET");
|
||||
break;
|
||||
case NODE_STMT_IF:
|
||||
printf("NODE_STMT_IF");
|
||||
break;
|
||||
}
|
||||
|
||||
printf(", Token: ");
|
||||
print_token(node->token);
|
||||
|
||||
printf("\n");
|
||||
for (size_t i = 0; i < node->count; i++) {
|
||||
ast_node_print(node->children[i], depth + 1);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
NODE SPECIFIC FUNCTIONS
|
||||
*/
|
||||
|
||||
ASTNode *ast_node_program() {
|
||||
Token tok = (Token) {
|
||||
.type = EOF_TOKEN,
|
||||
.line = 0,
|
||||
.data = {0}};
|
||||
ASTNode *node =
|
||||
ast_node_new(NODE_PROGRAM, tok);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
ASTNode *ast_node_defn(
|
||||
Token tok_val /*VAL token*/, ASTNode *type, ASTNode *id, ASTNode *expr) {
|
||||
ASTNode *node =
|
||||
ast_node_new(NODE_DEFN, tok_val);
|
||||
ast_node_add_child(node, type);
|
||||
ast_node_add_child(node, id);
|
||||
|
||||
if (expr != NULL) {
|
||||
ast_node_add_child(node, expr);
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
ASTNode *ast_node_type_simple(Token tok_id) {
|
||||
ASTNode *node =
|
||||
ast_node_new(NODE_TYPE_SIMPLE, tok_id);
|
||||
return node;
|
||||
}
|
||||
|
||||
ASTNode *ast_node_type_complex(
|
||||
Token tok_bracket, ASTNode *type_param, ASTNode *type_out) {
|
||||
ASTNode *node = ast_node_new(NODE_TYPE_COMPLEX, tok_bracket);
|
||||
type_param->token = tok_bracket;
|
||||
type_out->token = tok_bracket;
|
||||
ast_node_add_child(node, type_param);
|
||||
ast_node_add_child(node, type_out);
|
||||
return node;
|
||||
}
|
||||
|
||||
ASTNode *ast_node_type_param() {
|
||||
ASTNode *node =
|
||||
ast_node_new(NODE_TYPE_PARAM, (Token) {0});
|
||||
return node;
|
||||
}
|
||||
|
||||
ASTNode *ast_node_type_out() {
|
||||
ASTNode *node =
|
||||
ast_node_new(NODE_TYPE_OUT, (Token) {0});
|
||||
return node;
|
||||
}
|
||||
|
||||
ASTNode *ast_node_type_star(Token tok_star) {
|
||||
ASTNode *node =
|
||||
ast_node_new(NODE_TYPE_STAR, tok_star);
|
||||
return node;
|
||||
}
|
||||
|
||||
ASTNode *ast_node_type_void() {
|
||||
ASTNode *node =
|
||||
ast_node_new(NODE_TYPE_SIMPLE, (Token) {.type = VOID, .line = 0, .data = {0}});
|
||||
return node;
|
||||
}
|
||||
|
||||
ASTNode *ast_node_id(Token id) {
|
||||
ASTNode *node =
|
||||
ast_node_new(NODE_ID, id);
|
||||
return node;
|
||||
}
|
||||
|
||||
ASTNode *ast_node_num(Token num) {
|
||||
ASTNode *node =
|
||||
ast_node_new(NODE_NUM, num);
|
||||
return node;
|
||||
}
|
||||
|
||||
ASTNode *ast_node_str(Token str) {
|
||||
ASTNode *node =
|
||||
ast_node_new(NODE_STR, str);
|
||||
return node;
|
||||
}
|
||||
|
||||
ASTNode *ast_node_star(Token star) {
|
||||
ASTNode *node =
|
||||
ast_node_new(NODE_STAR, star);
|
||||
return node;
|
||||
}
|
||||
|
||||
ASTNode *ast_node_andref(Token andref) {
|
||||
ASTNode *node =
|
||||
ast_node_new(NODE_ANDREF, andref);
|
||||
return node;
|
||||
}
|
||||
|
||||
ASTNode *ast_node_expr(Token caller) {
|
||||
ASTNode *node =
|
||||
ast_node_new(NODE_EXPR, caller);
|
||||
return node;
|
||||
}
|
||||
|
||||
ASTNode *ast_node_param_list(Token tok_lparen) {
|
||||
ASTNode *node =
|
||||
ast_node_new(NODE_PARAM_LIST, tok_lparen);
|
||||
return node;
|
||||
}
|
||||
|
||||
ASTNode *ast_node_param(Token id, ASTNode *type) {
|
||||
ASTNode *node =
|
||||
ast_node_new(NODE_PARAM, id);
|
||||
ast_node_add_child(node, type);
|
||||
return node;
|
||||
}
|
||||
|
||||
ASTNode *ast_node_compound(Token tok_lcurly) {
|
||||
ASTNode *node =
|
||||
ast_node_new(NODE_COMPOUND, tok_lcurly);
|
||||
return node;
|
||||
}
|
||||
|
||||
ASTNode *ast_node_lambda(ASTNode *param_list, ASTNode *body) {
|
||||
ASTNode *node =
|
||||
ast_node_new(NODE_LAMBDA, param_list->token);
|
||||
ast_node_add_child(node, param_list);
|
||||
ast_node_add_child(node, body);
|
||||
return node;
|
||||
}
|
||||
|
||||
ASTNode *ast_node_stmt_return(Token tok_return, ASTNode *expr) {
|
||||
ASTNode *node =
|
||||
ast_node_new(NODE_STMT_RETURN, tok_return);
|
||||
if (expr != NULL) {
|
||||
ast_node_add_child(node, expr);
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
ASTNode *ast_node_stmt_expr(ASTNode *expr) {
|
||||
ASTNode *node =
|
||||
ast_node_new(NODE_STMT_EXPR, expr->token);
|
||||
ast_node_add_child(node, expr);
|
||||
return node;
|
||||
}
|
||||
|
||||
ASTNode *ast_node_stmt_if(
|
||||
Token tok_if,
|
||||
ASTNode *cond, /* compound */
|
||||
ASTNode *then_branch, /* compound */
|
||||
ASTNode *else_branch /* compound */) {
|
||||
ASTNode *node =
|
||||
ast_node_new(NODE_STMT_IF, tok_if);
|
||||
ast_node_add_child(node, cond);
|
||||
ast_node_add_child(node, then_branch);
|
||||
if (else_branch != NULL) {
|
||||
ast_node_add_child(node, else_branch);
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
ASTNode *ast_node_stmt_set(Token dollar, ASTNode *id, ASTNode *expr) {
|
||||
ASTNode *node =
|
||||
ast_node_new(NODE_STMT_SET, dollar);
|
||||
ast_node_add_child(node, id);
|
||||
ast_node_add_child(node, expr);
|
||||
return node;
|
||||
}
|
||||
36
src/main.c
36
src/main.c
@@ -1,11 +1,25 @@
|
||||
#include "globals.h"
|
||||
#include "lex.h"
|
||||
#include "util.h"
|
||||
#include "parse.h"
|
||||
|
||||
int main() {
|
||||
#define SCAN 0
|
||||
#define PARSE 1
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
Lexer *lexer = lexer_new();
|
||||
|
||||
FILE *f = fopen("test.cval", "r");
|
||||
FILE * f;
|
||||
|
||||
if (argc > 2) {
|
||||
printf("Usage: %s [source_file]\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
else if (argc == 2) {
|
||||
f = fopen(argv[1], "r");
|
||||
} else {
|
||||
f = fopen("test.cval", "r");
|
||||
}
|
||||
|
||||
if (f == NULL) {
|
||||
perror("Failed to open file");
|
||||
@@ -14,12 +28,30 @@ int main() {
|
||||
|
||||
lexer_set_source(lexer, f);
|
||||
|
||||
#if SCAN
|
||||
Token tok;
|
||||
|
||||
do {
|
||||
tok = lexer_next_token(lexer);
|
||||
print_token(tok);
|
||||
printf("\n");
|
||||
} while(tok.type != EOF_TOKEN && tok.type != ERROR);
|
||||
#endif
|
||||
|
||||
#if PARSE
|
||||
Parser *parser = parser_new(lexer);
|
||||
|
||||
ASTNode *ast_root = parser_parse_program(parser);
|
||||
|
||||
if (parser->flag_error) {
|
||||
printf("Parsing failed due to errors.\n");
|
||||
} else {
|
||||
printf("Parsing succeeded.\n");
|
||||
ast_node_print(ast_root, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
fclose(f);
|
||||
|
||||
|
||||
242
src/parse.c
242
src/parse.c
@@ -2,3 +2,245 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
static void parser_next(Parser *parser);
|
||||
|
||||
static bool parser_expect(Parser *parser, TokenType type);
|
||||
|
||||
Parser *parser_new(Lexer *lexer) {
|
||||
Parser *parser = malloc(sizeof(Parser));
|
||||
if (parser == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
parser->lexer = lexer;
|
||||
parser->flag_error = 0;
|
||||
|
||||
parser_next(parser);
|
||||
parser_next(parser);
|
||||
|
||||
return parser;
|
||||
}
|
||||
|
||||
void parser_free(Parser *parser) {
|
||||
free(parser);
|
||||
}
|
||||
|
||||
static void parser_next(Parser *parser) {
|
||||
parser->current = parser->peek;
|
||||
parser->peek = lexer_next_token(parser->lexer);
|
||||
}
|
||||
|
||||
static bool parser_expect(Parser *parser, TokenType type) {
|
||||
if (parser->current.type == type) {
|
||||
parser_next(parser);
|
||||
return true;
|
||||
} else {
|
||||
parser->flag_error = 1;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
IMPL. PARSER PARSE FUNCTIONS
|
||||
*/
|
||||
|
||||
ASTNode *parser_parse_program(Parser *parser) {
|
||||
ASTNode *root = ast_node_program();
|
||||
|
||||
while (parser->current.type == VAL) {
|
||||
ASTNode *defn_node = parser_parse_defn(parser);
|
||||
|
||||
if (defn_node == NULL) {
|
||||
ast_node_free(root);
|
||||
parser->flag_error = 1;
|
||||
return NULL;
|
||||
}
|
||||
ast_node_add_child(root, defn_node);
|
||||
}
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
ASTNode *parser_parse_defn(Parser *parser) {
|
||||
Token val_tok = parser->current;
|
||||
if (!parser_expect(parser, VAL)) {// must start with VAL
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ASTNode *type_node = parser_parse_type(parser);
|
||||
if (type_node == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
if (parser->current.type != ID) {
|
||||
parser->flag_error = 1;
|
||||
return NULL;
|
||||
}
|
||||
Token id_tok = parser->current;
|
||||
ASTNode *id_node = ast_node_id(id_tok);
|
||||
parser_next(parser);
|
||||
|
||||
ASTNode *expr_node = NULL;
|
||||
if (parser->current.type != SEMI) {
|
||||
expr_node = parser_parse_expr(parser);
|
||||
if (expr_node == NULL) {
|
||||
parser->flag_error = 1;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
if (!parser_expect(parser, SEMI)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ASTNode *defn_node = ast_node_defn(val_tok, type_node, id_node, expr_node);
|
||||
return defn_node;
|
||||
}
|
||||
|
||||
/*
|
||||
PARSING TYPE
|
||||
*/
|
||||
|
||||
ASTNode *parser_parse_type(Parser *parser) {
|
||||
ASTNode *type_node = NULL;
|
||||
if (parser->current.type == ID) {
|
||||
type_node = parser_parse_type_simple(parser);
|
||||
} else if (parser->current.type == LBRACK) {
|
||||
type_node = parser_parse_type_complex(parser);
|
||||
} else {
|
||||
parser->flag_error = 1;
|
||||
return NULL;
|
||||
}
|
||||
return type_node;
|
||||
}
|
||||
|
||||
ASTNode *parser_parse_type_simple(Parser *parser) {
|
||||
Token token = parser->current;
|
||||
if (!parser_expect(parser, ID)) {
|
||||
return NULL;
|
||||
}
|
||||
ASTNode *type_node = ast_node_type_simple(token);
|
||||
while (parser->current.type == STAR) {
|
||||
Token star_tok = parser->current;
|
||||
parser_next(parser);
|
||||
|
||||
ASTNode *type_star = ast_node_type_star(star_tok);
|
||||
ast_node_add_child(type_node, type_star);
|
||||
}
|
||||
|
||||
return type_node;
|
||||
}
|
||||
|
||||
ASTNode *parser_parse_type_complex(Parser *parser) {
|
||||
Token tok = parser->current;
|
||||
parser_next(parser);
|
||||
|
||||
ASTNode *types[256];
|
||||
ASTNode *type_ret = NULL;
|
||||
size_t cnt = 0;
|
||||
|
||||
ASTNode *ret = NULL;
|
||||
|
||||
while (parser->current.type != RBRACK && parser->current.type != ARROW) {
|
||||
ASTNode *type = parser_parse_type(parser);
|
||||
if (type == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
types[cnt++] = type;
|
||||
}
|
||||
|
||||
if (parser->current.type == ARROW) {
|
||||
|
||||
parser_next(parser);
|
||||
|
||||
if (parser->current.type != RBRACK) {
|
||||
type_ret = parser_parse_type(parser);
|
||||
if (type_ret == NULL) return NULL;
|
||||
} else {
|
||||
type_ret = ast_node_type_void(parser);
|
||||
}
|
||||
|
||||
ASTNode *type_param = ast_node_type_param();
|
||||
for (size_t i = 0; i < cnt; i++) {
|
||||
ast_node_add_child(type_param, types[i]);
|
||||
}
|
||||
|
||||
ASTNode *type_out = ast_node_type_out();
|
||||
ast_node_add_child(type_out, type_ret);
|
||||
ret = ast_node_type_complex(tok, type_param, type_out);
|
||||
} else if (parser->current.type == RBRACK) {
|
||||
|
||||
if (cnt >= 2) {
|
||||
parser->flag_error = 1;// too many args
|
||||
return NULL;
|
||||
}
|
||||
if (cnt == 1) {
|
||||
ret = types[0];
|
||||
} else {
|
||||
ret = ast_node_type_void(parser);
|
||||
}
|
||||
} else {
|
||||
parser->flag_error = 1;
|
||||
return NULL;
|
||||
}
|
||||
parser_next(parser);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
PARSING EXPR
|
||||
*/
|
||||
|
||||
ASTNode *parser_parse_expr(Parser *parser) {
|
||||
ASTNode *atoms[256];
|
||||
size_t cnt = 1;
|
||||
ASTNode *atom_head = parser_parse_atom(parser);
|
||||
if (atom_head == NULL) {
|
||||
parser->flag_error = 1;
|
||||
return NULL;
|
||||
}
|
||||
atoms[0] = atom_head;
|
||||
|
||||
ASTNode *atom;
|
||||
while (true) {
|
||||
atom = parser_parse_atom(parser);
|
||||
if (atom == NULL) {
|
||||
break;
|
||||
}
|
||||
atoms[cnt] = atom;
|
||||
cnt++;
|
||||
}
|
||||
|
||||
ASTNode *node = ast_node_expr(atom_head->token);
|
||||
for (size_t i = 0; i < cnt; i++) {
|
||||
ast_node_add_child(node, atoms[i]);
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
ASTNode *parser_parse_atom(Parser *parser) {
|
||||
if (parser->current.type == NUM) {
|
||||
Token num_tok = parser->current;
|
||||
parser_next(parser);
|
||||
return ast_node_num(num_tok);
|
||||
} else if (parser->current.type == ID) {
|
||||
Token id_tok = parser->current;
|
||||
parser_next(parser);
|
||||
return ast_node_id(id_tok);
|
||||
} else if (parser->current.type == STRING_LITERAL) {
|
||||
Token str_tok = parser->current;
|
||||
parser_next(parser);
|
||||
return ast_node_str(str_tok);
|
||||
} else if (parser->current.type == STAR) {
|
||||
Token star_tok = parser->current;
|
||||
parser_next(parser);
|
||||
return ast_node_star(star_tok);
|
||||
} else if (parser->current.type == ANDREF) {
|
||||
Token andref_tok = parser->current;
|
||||
parser_next(parser);
|
||||
return ast_node_andref(andref_tok);
|
||||
}
|
||||
|
||||
else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
@@ -103,5 +103,4 @@ void print_token(Token tok) {
|
||||
if (tok.type == ID || tok.type == NUM || tok.type == STRING_LITERAL) {
|
||||
printf("Data: %s", tok.data.string);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
@@ -4,7 +4,9 @@ val [int->int] fib (int n) {
|
||||
return if eq n 0 {
|
||||
1
|
||||
} else {
|
||||
mul n fib
|
||||
mul n {
|
||||
fib {sub n 1}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
@@ -24,4 +26,4 @@ val [char * int->char]get_char_of(char* s int index) {
|
||||
return * {
|
||||
add s index
|
||||
};
|
||||
}
|
||||
};
|
||||
9
test2.cval
Normal file
9
test2.cval
Normal file
@@ -0,0 +1,9 @@
|
||||
val [->int] main;
|
||||
|
||||
val char* line;
|
||||
|
||||
val size_t line get_line_ptr stdin line;
|
||||
|
||||
val char first *line;
|
||||
|
||||
val [int [int->size_t]->size_t] functor;
|
||||
Reference in New Issue
Block a user