gv export
This commit is contained in:
parent
c50551dca8
commit
e9beb1c292
1
.gitignore
vendored
1
.gitignore
vendored
@ -6,3 +6,4 @@ build/
|
|||||||
*.png
|
*.png
|
||||||
*.svg
|
*.svg
|
||||||
*.ps
|
*.ps
|
||||||
|
*.pdf
|
||||||
|
|||||||
16
lex.c
16
lex.c
@ -212,19 +212,3 @@ const char *lex_token_str(enum token_type token) {
|
|||||||
default: return "<unknown token>";
|
default: return "<unknown token>";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef LEX_DEBUG
|
|
||||||
|
|
||||||
void lex_debug_print_token(const struct token *tok) {
|
|
||||||
printf("%-20s ", lex_token_str(tok->type));
|
|
||||||
|
|
||||||
if (tok->type == TOK_NUMBER)
|
|
||||||
printf("%.2f\n", tok->val.num);
|
|
||||||
else if (tok->type == TOK_FUNCTION) {
|
|
||||||
printf("%s\n", fns_get()[tok->val.fn_idx].name);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* LEX_DEBUG */
|
|
||||||
|
|||||||
4
lex.h
4
lex.h
@ -114,8 +114,4 @@ const char *lex_get_error_text(const struct lexer *lex);
|
|||||||
*/
|
*/
|
||||||
const char *lex_token_str(enum token_type token);
|
const char *lex_token_str(enum token_type token);
|
||||||
|
|
||||||
#ifdef LEX_DEBUG
|
|
||||||
void lex_debug_print_token(const struct token *tok);
|
|
||||||
#endif /* LEX_DEBUG */
|
|
||||||
|
|
||||||
#endif /* LEX_H */
|
#endif /* LEX_H */
|
||||||
21
main.c
21
main.c
@ -58,6 +58,21 @@ static enum error_code export_to_file(const struct expr_node *node, const struct
|
|||||||
return ERR_NO_ERR;
|
return ERR_NO_ERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef ENABLE_GRAPHVIZ_EXPORT
|
||||||
|
static void export_gv(const struct expr_node *node, const char *out_name) {
|
||||||
|
FILE *file;
|
||||||
|
|
||||||
|
if (!(file = fopen(out_name, "w"))) {
|
||||||
|
fprintf(stderr, "GV: Cannot open \"%s\" for writing!\n", out_name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
node_debug_print_gv(node, file);
|
||||||
|
|
||||||
|
fclose(file);
|
||||||
|
}
|
||||||
|
#endif /* ENABLE_GRAPHVIZ_EXPORT */
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
enum error_code err;
|
enum error_code err;
|
||||||
struct parser parser;
|
struct parser parser;
|
||||||
@ -91,9 +106,9 @@ int main(int argc, char *argv[]) {
|
|||||||
|
|
||||||
err = export_to_file(node, &range, argv[2]);
|
err = export_to_file(node, &range, argv[2]);
|
||||||
|
|
||||||
/* file = fopen("graph.dot", "w");
|
#ifdef ENABLE_GRAPHVIZ_EXPORT
|
||||||
node_debug_print_gv(node, file);
|
export_gv(node, "graph.dot");
|
||||||
fclose(file); */
|
#endif /* ENABLE_GRAPHVIZ_EXPORT */
|
||||||
|
|
||||||
node_free(node);
|
node_free(node);
|
||||||
|
|
||||||
|
|||||||
@ -28,7 +28,7 @@ MAKE_FUNCTION_1_ARG(tanh)
|
|||||||
MAKE_FUNCTION_1_ARG(floor)
|
MAKE_FUNCTION_1_ARG(floor)
|
||||||
MAKE_FUNCTION_1_ARG(ceil)
|
MAKE_FUNCTION_1_ARG(ceil)
|
||||||
|
|
||||||
static double mf_sgn(double *y, const double *args) {
|
static enum eval_result mf_sgn(double *y, const double *args) {
|
||||||
if (args[0] < 0.0)
|
if (args[0] < 0.0)
|
||||||
*y = -1.0;
|
*y = -1.0;
|
||||||
else if (args[0] > 0.0)
|
else if (args[0] > 0.0)
|
||||||
@ -39,7 +39,7 @@ static double mf_sgn(double *y, const double *args) {
|
|||||||
return EVAL_OK;
|
return EVAL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static double mf_min(double *y, const double *args) {
|
static enum eval_result mf_min(double *y, const double *args) {
|
||||||
if (args[0] < args[1])
|
if (args[0] < args[1])
|
||||||
*y = args[0];
|
*y = args[0];
|
||||||
else
|
else
|
||||||
@ -48,7 +48,7 @@ static double mf_min(double *y, const double *args) {
|
|||||||
return EVAL_OK;
|
return EVAL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static double mf_max(double *y, const double *args) {
|
static enum eval_result mf_max(double *y, const double *args) {
|
||||||
if (args[0] > args[1])
|
if (args[0] > args[1])
|
||||||
*y = args[0];
|
*y = args[0];
|
||||||
else
|
else
|
||||||
@ -57,7 +57,7 @@ static double mf_max(double *y, const double *args) {
|
|||||||
return EVAL_OK;
|
return EVAL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static double mf_mod(double *y, const double *args) {
|
static enum eval_result mf_mod(double *y, const double *args) {
|
||||||
errno = 0;
|
errno = 0;
|
||||||
*y = fmod(args[0], args[1]);
|
*y = fmod(args[0], args[1]);
|
||||||
|
|
||||||
|
|||||||
@ -35,7 +35,7 @@ void ps_export_graph(FILE *file, const struct expr_node *node, const struct grap
|
|||||||
/* popisky */
|
/* popisky */
|
||||||
fprintf(file,
|
fprintf(file,
|
||||||
"/Arial findfont\n"
|
"/Arial findfont\n"
|
||||||
"12 scalefont\n"
|
"10 scalefont\n"
|
||||||
"setfont\n"
|
"setfont\n"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
292
tree.c
292
tree.c
@ -75,187 +75,6 @@ struct expr_node *node_create_fn(size_t fn_idx, struct expr_node **args) {
|
|||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
void node_free(struct expr_node *node) {
|
|
||||||
if (!node) return;
|
|
||||||
|
|
||||||
switch (node->type) {
|
|
||||||
case EXPR_ADD:
|
|
||||||
case EXPR_SUB:
|
|
||||||
case EXPR_MULT:
|
|
||||||
case EXPR_DIV:
|
|
||||||
case EXPR_POW:
|
|
||||||
node_free(node->vals.binop.left);
|
|
||||||
node_free(node->vals.binop.right);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case EXPR_NEG:
|
|
||||||
node_free(node->vals.unop);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case EXPR_FN:
|
|
||||||
{
|
|
||||||
size_t i, num_args = fns_get()[node->vals.fn.fn_idx].num_args;
|
|
||||||
for (i = 0; i < num_args; ++i) {
|
|
||||||
node_free(node->vals.fn.args[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
free(node);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void debug_indent(int indent) {
|
|
||||||
int i;
|
|
||||||
for (i = 0; i < indent; ++i)
|
|
||||||
printf(" ");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void debug_print(struct expr_node *node, int indent);
|
|
||||||
|
|
||||||
static void debug_print_binop(struct expr_node *node, const char* name, int indent) {
|
|
||||||
debug_indent(indent); printf("[%s]\n", name);
|
|
||||||
debug_print(node->vals.binop.left, indent + 1);
|
|
||||||
debug_print(node->vals.binop.right, indent + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void debug_print(struct expr_node *node, int indent) {
|
|
||||||
|
|
||||||
switch (node->type) {
|
|
||||||
case EXPR_ADD:
|
|
||||||
debug_print_binop(node, "ADD", indent);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case EXPR_SUB:
|
|
||||||
debug_print_binop(node, "SUB", indent);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case EXPR_MULT:
|
|
||||||
debug_print_binop(node, "MULT", indent);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case EXPR_DIV:
|
|
||||||
debug_print_binop(node, "DIV", indent);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case EXPR_POW:
|
|
||||||
debug_print_binop(node, "POW", indent);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case EXPR_NEG:
|
|
||||||
debug_indent(indent); printf("[NEG]\n");
|
|
||||||
debug_print(node->vals.unop, indent + 1);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case EXPR_CONST:
|
|
||||||
debug_indent(indent); printf("[CONST] %.2f\n", node->vals.num);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case EXPR_X:
|
|
||||||
debug_indent(indent); printf("[X]\n");
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case EXPR_FN:
|
|
||||||
{
|
|
||||||
size_t i;
|
|
||||||
const struct math_function *fn = &fns_get()[node->vals.fn.fn_idx];
|
|
||||||
debug_indent(indent); printf("[FN] %s\n", fn->name);
|
|
||||||
|
|
||||||
for (i = 0; i < fn->num_args; ++i) {
|
|
||||||
debug_print(node->vals.fn.args[i], indent + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void node_debug_print(struct expr_node *node) {
|
|
||||||
debug_print(node, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void debug_print_gv(const struct expr_node *node, FILE *output);
|
|
||||||
|
|
||||||
static void debug_print_binop_gv(const struct expr_node *node, FILE *output, const char *name) {
|
|
||||||
fprintf(output, "node%p [label=\"%s\"]\n", (void*)node, name);
|
|
||||||
debug_print_gv(node->vals.binop.left, output);
|
|
||||||
debug_print_gv(node->vals.binop.right, output);
|
|
||||||
fprintf(output, "node%p -> node%p [label=left]\n", (void*)node, (void*)node->vals.binop.left);
|
|
||||||
fprintf(output, "node%p -> node%p [label=right]\n", (void*)node, (void*)node->vals.binop.right);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void debug_print_gv(const struct expr_node *node, FILE *output) {
|
|
||||||
|
|
||||||
switch (node->type) {
|
|
||||||
case EXPR_ADD:
|
|
||||||
debug_print_binop_gv(node, output, "ADD");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case EXPR_SUB:
|
|
||||||
debug_print_binop_gv(node, output, "SUB");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case EXPR_MULT:
|
|
||||||
debug_print_binop_gv(node, output, "MULT");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case EXPR_DIV:
|
|
||||||
debug_print_binop_gv(node, output, "DIV");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case EXPR_POW:
|
|
||||||
debug_print_binop_gv(node, output, "POW");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case EXPR_NEG:
|
|
||||||
fprintf(output, "node%p [label=\"NEG\"]\n", (void*)node);
|
|
||||||
debug_print_gv(node->vals.unop, output);
|
|
||||||
fprintf(output, "node%p -> node%p [label=unop]\n", (void*)node, (void*)node->vals.unop);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case EXPR_CONST:
|
|
||||||
fprintf(output, "node%p [label=\"CONST: %.2f\"]\n", (void*)node, node->vals.num);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case EXPR_X:
|
|
||||||
fprintf(output, "node%p [label=\"X\"]\n", (void*)node);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case EXPR_FN:
|
|
||||||
{
|
|
||||||
size_t i;
|
|
||||||
const struct math_function *fn = &fns_get()[node->vals.fn.fn_idx];
|
|
||||||
|
|
||||||
fprintf(output, "node%p [label=\"FN: %s\"]\n", (void*)node, fn->name);
|
|
||||||
|
|
||||||
for (i = 0; i < fn->num_args; ++i) {
|
|
||||||
struct expr_node *arg = node->vals.fn.args[i];
|
|
||||||
debug_print_gv(arg, output);
|
|
||||||
fprintf(output, "node%p -> node%p [label=arg%d]\n", (void*)node, (void*)arg, (int)i + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void node_debug_print_gv(const struct expr_node *node, FILE *output) {
|
|
||||||
fprintf(output, "digraph G {\n");
|
|
||||||
debug_print_gv(node, output);
|
|
||||||
fprintf(output, "}\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
#define INF (1.0e256)
|
#define INF (1.0e256)
|
||||||
|
|
||||||
static int is_real(double x) {
|
static int is_real(double x) {
|
||||||
@ -346,3 +165,114 @@ enum eval_result node_eval(const struct expr_node *node, double x, double *y) {
|
|||||||
|
|
||||||
return 0.0;
|
return 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef ENABLE_GRAPHVIZ_EXPORT
|
||||||
|
|
||||||
|
static void debug_print_gv(const struct expr_node *node, FILE *output);
|
||||||
|
|
||||||
|
static void debug_print_binop_gv(const struct expr_node *node, FILE *output, const char *name) {
|
||||||
|
fprintf(output, "node%p [label=\"%s\"]\n", (void*)node, name);
|
||||||
|
debug_print_gv(node->vals.binop.left, output);
|
||||||
|
debug_print_gv(node->vals.binop.right, output);
|
||||||
|
fprintf(output, "node%p -> node%p [label=left]\n", (void*)node, (void*)node->vals.binop.left);
|
||||||
|
fprintf(output, "node%p -> node%p [label=right]\n", (void*)node, (void*)node->vals.binop.right);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void debug_print_gv(const struct expr_node *node, FILE *output) {
|
||||||
|
|
||||||
|
switch (node->type) {
|
||||||
|
case EXPR_ADD:
|
||||||
|
debug_print_binop_gv(node, output, "ADD");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EXPR_SUB:
|
||||||
|
debug_print_binop_gv(node, output, "SUB");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EXPR_MULT:
|
||||||
|
debug_print_binop_gv(node, output, "MULT");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EXPR_DIV:
|
||||||
|
debug_print_binop_gv(node, output, "DIV");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EXPR_POW:
|
||||||
|
debug_print_binop_gv(node, output, "POW");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EXPR_NEG:
|
||||||
|
fprintf(output, "node%p [label=\"NEG\"]\n", (void*)node);
|
||||||
|
debug_print_gv(node->vals.unop, output);
|
||||||
|
fprintf(output, "node%p -> node%p [label=unop]\n", (void*)node, (void*)node->vals.unop);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EXPR_CONST:
|
||||||
|
fprintf(output, "node%p [label=\"CONST: %.2f\"]\n", (void*)node, node->vals.num);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EXPR_X:
|
||||||
|
fprintf(output, "node%p [label=\"X\"]\n", (void*)node);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EXPR_FN:
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
const struct math_function *fn = &fns_get()[node->vals.fn.fn_idx];
|
||||||
|
|
||||||
|
fprintf(output, "node%p [label=\"FN: %s\"]\n", (void*)node, fn->name);
|
||||||
|
|
||||||
|
for (i = 0; i < fn->num_args; ++i) {
|
||||||
|
struct expr_node *arg = node->vals.fn.args[i];
|
||||||
|
debug_print_gv(arg, output);
|
||||||
|
fprintf(output, "node%p -> node%p [label=arg%d]\n", (void*)node, (void*)arg, (int)i + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void node_debug_print_gv(const struct expr_node *node, FILE *output) {
|
||||||
|
fprintf(output, "digraph G {\n");
|
||||||
|
debug_print_gv(node, output);
|
||||||
|
fprintf(output, "}\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* ENABLE_GRAPHVIZ_EXPORT */
|
||||||
|
|
||||||
|
void node_free(struct expr_node *node) {
|
||||||
|
if (!node) return;
|
||||||
|
|
||||||
|
switch (node->type) {
|
||||||
|
case EXPR_ADD:
|
||||||
|
case EXPR_SUB:
|
||||||
|
case EXPR_MULT:
|
||||||
|
case EXPR_DIV:
|
||||||
|
case EXPR_POW:
|
||||||
|
node_free(node->vals.binop.left);
|
||||||
|
node_free(node->vals.binop.right);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EXPR_NEG:
|
||||||
|
node_free(node->vals.unop);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EXPR_FN:
|
||||||
|
{
|
||||||
|
size_t i, num_args = fns_get()[node->vals.fn.fn_idx].num_args;
|
||||||
|
for (i = 0; i < num_args; ++i) {
|
||||||
|
node_free(node->vals.fn.args[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(node);
|
||||||
|
}
|
||||||
|
|||||||
7
tree.h
7
tree.h
@ -115,9 +115,6 @@ struct expr_node *node_create_x(void);
|
|||||||
*/
|
*/
|
||||||
struct expr_node *node_create_fn(size_t fn_idx, struct expr_node **args);
|
struct expr_node *node_create_fn(size_t fn_idx, struct expr_node **args);
|
||||||
|
|
||||||
void node_debug_print(struct expr_node *node);
|
|
||||||
void node_debug_print_gv(const struct expr_node *node, FILE *output);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Vyhodnotí uzel
|
* @brief Vyhodnotí uzel
|
||||||
*
|
*
|
||||||
@ -128,6 +125,10 @@ void node_debug_print_gv(const struct expr_node *node, FILE *output);
|
|||||||
*/
|
*/
|
||||||
enum eval_result node_eval(const struct expr_node *node, double x, double *y);
|
enum eval_result node_eval(const struct expr_node *node, double x, double *y);
|
||||||
|
|
||||||
|
#ifdef ENABLE_GRAPHVIZ_EXPORT
|
||||||
|
void node_debug_print_gv(const struct expr_node *node, FILE *output);
|
||||||
|
#endif /* ENABLE_GRAPHVIZ_EXPORT */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Uvolní uzel
|
* @brief Uvolní uzel
|
||||||
*
|
*
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user