main
This commit is contained in:
parent
a5d9e88f77
commit
c50551dca8
2
lex.c
2
lex.c
@ -141,7 +141,7 @@ void lex_next(struct lexer *lex) {
|
|||||||
|
|
||||||
if (try_constant(lex, "pi", CONST_PI)) return;
|
if (try_constant(lex, "pi", CONST_PI)) return;
|
||||||
if (try_constant(lex, "e", CONST_E)) return;
|
if (try_constant(lex, "e", CONST_E)) return;
|
||||||
if (try_constant(lex, "skibidi", CONST_S)) return;
|
if (try_constant(lex, "skibidi", CONST_S)) return; /* easter egg */
|
||||||
|
|
||||||
if (try_advance_identifier(lex, lex->variable_name)) {
|
if (try_advance_identifier(lex, lex->variable_name)) {
|
||||||
lex->tok.type = TOK_VARIABLE;
|
lex->tok.type = TOK_VARIABLE;
|
||||||
|
|||||||
95
main.c
95
main.c
@ -3,17 +3,83 @@
|
|||||||
#include "lex.h"
|
#include "lex.h"
|
||||||
#include "parser.h"
|
#include "parser.h"
|
||||||
#include "ps_graph.h"
|
#include "ps_graph.h"
|
||||||
|
#include "error_buffer.h"
|
||||||
|
|
||||||
|
static void print_usage(FILE *f, const char *name) {
|
||||||
|
fprintf(f, "Usage: %s <function> <output file> [<range>]\n", name);
|
||||||
|
fprintf(f, " <function> ..... The function to plot the graph of.\n");
|
||||||
|
fprintf(f, " <output file> .. Name of the output PostScript file.\n");
|
||||||
|
fprintf(f, " <range> ........ Ranges of the graph in the format of \"xMin:xMax:yMin:yMax\". Optional.\n");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static int read_double(const char **str, double *out) {
|
||||||
|
char *end;
|
||||||
|
*out = strtod(*str, &end);
|
||||||
|
|
||||||
|
if (*str == end)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
*str = end;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define EXPECT_DOUBLE(str, out) \
|
||||||
|
if (!read_double(&str, out)) \
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
#define EXPECT_CHAR(str, c) \
|
||||||
|
if (*str++ != c) \
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
static int parse_range(const char *str, struct graph_range *range) {
|
||||||
|
EXPECT_DOUBLE(str, &range->xmin);
|
||||||
|
EXPECT_CHAR(str, ':');
|
||||||
|
EXPECT_DOUBLE(str, &range->xmax);
|
||||||
|
EXPECT_CHAR(str, ':');
|
||||||
|
EXPECT_DOUBLE(str, &range->ymin);
|
||||||
|
EXPECT_CHAR(str, ':');
|
||||||
|
EXPECT_DOUBLE(str, &range->ymax);
|
||||||
|
EXPECT_CHAR(str, '\0');
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum error_code export_to_file(const struct expr_node *node, const struct graph_range *range, const char *out_name) {
|
||||||
|
FILE *file;
|
||||||
|
|
||||||
|
if (!(file = fopen(out_name, "w"))) {
|
||||||
|
fprintf(stderr, "Cannot open \"%s\" for writing!\n", out_name);
|
||||||
|
return ERR_INVALID_FILENAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
ps_export_graph(file, node, range);
|
||||||
|
|
||||||
|
fclose(file);
|
||||||
|
return ERR_NO_ERR;
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
|
enum error_code err;
|
||||||
struct parser parser;
|
struct parser parser;
|
||||||
struct expr_node *node;
|
struct expr_node *node;
|
||||||
FILE *file;
|
struct graph_range range;
|
||||||
struct graph_range graph;
|
|
||||||
|
|
||||||
if (argc < 2) {
|
if (argc < 3) {
|
||||||
printf("Usage: %s <expression>\n", argv[0]);
|
print_usage(stderr, argv[0]);
|
||||||
return 1;
|
return ERR_INVALID_ARGS;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argc > 3) {
|
||||||
|
if (!parse_range(argv[3], &range)) {
|
||||||
|
fprintf(stderr, "Invalid format of ranges! The correct format is \"xMin:xMax:yMin:yMax\".\n");
|
||||||
|
return ERR_INVALID_ARGS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
range.xmin = -10.0;
|
||||||
|
range.xmax = 10.0;
|
||||||
|
range.ymin = -10.0;
|
||||||
|
range.ymax = 10.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
node = parser_parse(&parser, argv[1], "x");
|
node = parser_parse(&parser, argv[1], "x");
|
||||||
@ -23,22 +89,13 @@ int main(int argc, char *argv[]) {
|
|||||||
return parser_get_error(&parser);
|
return parser_get_error(&parser);
|
||||||
}
|
}
|
||||||
|
|
||||||
graph.xmin = -10.0;
|
err = export_to_file(node, &range, argv[2]);
|
||||||
graph.xmax = 10.0;
|
|
||||||
graph.ymin = -10.0;
|
|
||||||
graph.ymax = 10.0;
|
|
||||||
graph.step = 0.01;
|
|
||||||
|
|
||||||
file = fopen("out.ps", "w");
|
/* file = fopen("graph.dot", "w");
|
||||||
ps_export_graph(file, node, &graph);
|
|
||||||
fclose(file);
|
|
||||||
|
|
||||||
file = fopen("graph.dot", "w");
|
|
||||||
node_debug_print_gv(node, file);
|
node_debug_print_gv(node, file);
|
||||||
fclose(file);
|
fclose(file); */
|
||||||
|
|
||||||
node_free(node);
|
node_free(node);
|
||||||
|
|
||||||
|
return err;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
@ -69,6 +69,10 @@ static double mf_mod(double *y, const double *args) {
|
|||||||
|
|
||||||
const struct math_function *fns_get(void) {
|
const struct math_function *fns_get(void) {
|
||||||
static const struct math_function fns[] = {
|
static const struct math_function fns[] = {
|
||||||
|
/* +--- název
|
||||||
|
| +--- počet argumentů
|
||||||
|
| | +--- vyhodnocovač
|
||||||
|
| | | */
|
||||||
{ "abs", 1, mf_fabs },
|
{ "abs", 1, mf_fabs },
|
||||||
{ "exp", 1, mf_exp },
|
{ "exp", 1, mf_exp },
|
||||||
{ "ln", 1, mf_log },
|
{ "ln", 1, mf_log },
|
||||||
|
|||||||
@ -7,7 +7,6 @@
|
|||||||
struct graph_range {
|
struct graph_range {
|
||||||
double xmin, xmax;
|
double xmin, xmax;
|
||||||
double ymin, ymax;
|
double ymin, ymax;
|
||||||
double step;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extern void ps_export_graph(FILE *file, const struct expr_node *node, const struct graph_range *range);
|
extern void ps_export_graph(FILE *file, const struct expr_node *node, const struct graph_range *range);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user