summaryrefslogtreecommitdiff
path: root/parser.c
blob: 9bbc50b88b1d5e7fd9bd0b9d3e185610a9936de4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <ctype.h>
#include "stack.h"
#include "parser.h"
#include "eval.h"

static unsigned int jumpdist;

static char *readexpr(char *expr){
	char *out = malloc(strlen(expr+1));
	char *c = expr;	
	stack *s = push(NULL, *c);
	int i;

	for (i = 0; s->len != 0; i++){
		out[i] = *c;
		c++;
		if (*c == '(') s = push(s, '(');
		else if (*c == ')' && peek(s) == '(') pop(s);
	}
	cleanstack(s);

	out[i] = ')';
	out[i+1] = 0;
	out = realloc(out, strlen(out));
	jumpdist = i+1;
	return out;
}

static char *readval(char *expr){
	char *out = strdup(expr);
	char *gap = strchr(out, ' ');
	if (gap == NULL) gap = strchr(out, ')');
	jumpdist = (gap - out)+1;
	*gap = 0;
	out = realloc(out, strlen(out));
	return out;
}

static luckyval *readargs(char *expr){
	luckyval *head = malloc(sizeof(luckyval));

	if (*expr != ')' && expr[0] != 0){
		if (expr[0] == '(' ){ // nested function
			char *subexpr = readexpr(expr);
			expr += jumpdist + 1;
			head->tree = parse(subexpr);
			head->type = LUCKYTREE;
			free(subexpr);
		}
		else if (strchr(expr, '.') != NULL){ // float
			char *val = readval(expr);
			expr += jumpdist;
			head->f = atof(val);
			head->type = LUCKYFLOAT;
			free(val);
		}
		else if (isdigit(expr[0])){ // int
			char *val = readval(expr);
			expr += jumpdist;
			head->i = atoi(val);
			head->type = LUCKYINT;
			free(val);
		} 
		else { // var name
			char *val = readval(expr);
			expr += jumpdist;
			head->var = strdup(val);
			head->type = LUCKYVAR;
		}
	} else return NULL;

	head->nextelement = readargs(expr);
	return head;
}

luckytree *parse(char *expr){
	char *c = expr;	
	stack *s = push(NULL, *c);
	while (*c != 0){
		c++;
		if (*c == '(') s = push(s, '(');
		else if (*c == ')' && peek(s) == '(') pop(s);
	}
	if (s->len != 0){
		printf("%s\n", expr);
		for (int i = 0; i < (c - expr) - 1; i++) printf(" ");
		printf("^\n");
		printf("bracket mismatch!\n");
		exit(1);
	}
	cleanstack(s);

	luckytree *tree = malloc(sizeof(luckytree));

	int funcnamelen;
	if (strchr(expr+1, ' ') == NULL) 
		funcnamelen = (strchr(expr+1, ')') - expr) - 1;
	else
		funcnamelen = (strchr(expr+1, ' ') - expr) - 1;

	tree->function = malloc(funcnamelen + 1);

	memcpy(tree->function, expr + 1, funcnamelen);
	tree->function[funcnamelen] = 0;

	expr += funcnamelen + 2;

	tree->arguments = readargs(expr);

	return tree;
}