//
// tree.c ... 構文木の基本操作
//
#include <stdio.h>
#include <assert.h>
#include "base.h"
// 構文木のデータ構造
typedef enum { NUMBER_TREE, NAME_TREE, LIST_TREE } TreeType;
typedef struct _tree {
TreeType type; // 木の種類
int number; // 節に格納する数
char *name; // 節に格納する名前
struct _tree *head; // 列の先頭
struct _tree *rest; // 残りの列
} Tree;
// 木の節の生成
static Tree *make_node(void) {
Tree *tree = (Tree *) malloc_or_exit(sizeof(Tree));
tree->type = NUMBER_TREE;
tree->number = 0;
tree->name = NULL;
tree->head = NULL;
tree->rest = NULL;
return tree;
}
Tree *make_number_tree(int number) {
Tree *tree = make_node();
tree->type = NUMBER_TREE;
tree->number = number;
return tree;
}
Tree *make_name_tree(char *name) {
assert(name != NULL);
Tree *tree = make_node();
tree->type = NAME_TREE;
tree->name = name;
return tree;
}
Tree *make_list_tree(void) {
Tree *tree = make_node();
tree->type = LIST_TREE;
return tree;
}
// 木の種類の判定
int is_number_tree(Tree *tree) {
assert(tree != NULL);
return tree->type == NUMBER_TREE;
}
int is_name_tree(Tree *tree) {
assert(tree != NULL);
return tree->type == NAME_TREE;
}
int is_list_tree(Tree *tree) {
assert(tree != NULL);
return tree->type == LIST_TREE;
}
// メンバーの取得
int get_number(Tree *tree) {
assert(is_number_tree(tree));
return tree->number;
}
char *get_name(Tree *tree) {
assert(is_name_tree(tree));
return tree->name;
}
// 木の操作
void add_subtree(Tree *tree, Tree *subtree) {
//【課題b1】関数を実装する
}
int num_subtree(Tree *tree) {
//【課題b1】関数を実装する
return 0;
}
Tree *get_subtree(Tree *tree, int n) {
//【課題b1】関数を実装する
return NULL;
}
void show_tree(Tree *tree) {
if (tree == NULL) {
printf("#");
} else {
if (is_number_tree(tree)) {
printf("%d", get_number(tree));
} else if (is_name_tree(tree)) {
printf("\"%s\"", get_name(tree));
} else {
printf("List");
}
putchar('[');
show_tree(tree->head);
putchar(',');
show_tree(tree->rest);
putchar(']');
}
}
void print_tree(Tree *tree) {
if (tree == NULL) return;
if (is_number_tree(tree)) {
printf("%d", tree->number);
} else if (is_name_tree(tree)) {
printf("%s", tree->name);
} else if (is_list_tree(tree)) {
putchar('(');
while (tree->rest != NULL) {
print_tree(tree->head);
tree = tree->rest;
if (tree->rest != NULL) putchar(' ');
}
putchar(')');
} else {
assert(0);
}
}