-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathparser.c
158 lines (120 loc) · 3.48 KB
/
parser.c
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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "parser.h"
#include <time.h>
#include <ctype.h>
#include <errno.h>
void dynamicAlloc(int);
void freeTERMS(int);
//Parses the input and stores each term as an entry in the array TERMS. Returns the number of elements in TERMS.
int parse(char *input) {
int count = 0;
dynamicAlloc(10);
char *token;
token = strtok(input, " ");
while (token != NULL) {
TERMS[count] = strdup(token);
count++;
token = strtok(NULL, " ");
if (count % 10 == 0) dynamicAlloc(count + 10);
}
dynamicAlloc(count);
return count;
}
//Sets rolls array and parses each term into a cell. Returns number of cells on success and <0 on error.
int set_info(int number) {
rolls = malloc(sizeof(struct INFO) * number); // Allocate enough memory to rolls
int count = 0; //Tracking size of the rolls array
for (int i = 0; i < number; i++) {
char *current = strdup(TERMS[i]);
// x -> axbdc, n -> bdc, d -> dc, w-> axdc c -> c, 0 -> not set
char format = '0';
// Set ARITH if needed
if (*current == '+' || *current == '-') {
rolls[count].ARITH = *current;
current++;
TERMS[i]++; //Get rid of arithmetic sign at the front of the term
if (*current == '\0') continue;
}
if (isdigit(*current) || *current == 'd') {
if (*current == 'd') format = 'd';
else {
while (isdigit(*current)) {current++;} // Run through the number, if needed
if (*current == '\0') {format = 'c';} // Constant
}
while (*current != '\0') {
switch(*current) {
case 'x':
current++;
if (isdigit(*current)) {
format = 'x';
while (isdigit(*current)) {current++;}
}
else {format = 'w';}
break;
case 'd':
current++;
if (isdigit(*current)) {
while (isdigit(*current)) {current++;}
}
else {return -3;}
if (*current != '\0') {return -3;} //Must be ended to be valid
if (format == '0') format = 'n'; //If no format has been set by now, then it's bdc
break;
default:
return -3; //Format Error
}
}
}
else {return -3;} // Error, bad input
int mult = 1, num = 1, sides = 0;
int err;
//Scan into the INFO struct now, based on format
switch (format) {
case 'x':
err = sscanf(TERMS[i], "%dx%dd%d", &mult, &num, &sides);
break;
case 'w':
err = sscanf(TERMS[i], "%dxd%d", &mult, &sides);
break;
case 'n':
err = sscanf(TERMS[i], "%dd%d", &num, &sides);
break;
case 'd':
err = sscanf(TERMS[i], "d%d", &sides);
break;
case 'c':
rolls[count].constant = 'c';
err = sscanf(TERMS[i], "%d", &rolls[count].choice.value);
break;
default:
return -3; //Input error
}
if (sides == 0 && format != 'c') return -5; // Attempt to roll 0-sided die
if (err == EOF){
if (errno == ERANGE) return -4; // Out of range int
else return -3;
}
if (format != 'c') {
rolls[count].constant = 'r';
rolls[count].choice.roll.mult = mult;
rolls[count].choice.roll.num = num;
rolls[count].choice.roll.sides = sides;
}
count++;
}
rolls = realloc(rolls, sizeof(struct INFO) * count);
freeTERMS(number);
return count;
}
void dynamicAlloc(int slots) {
TERMS = (char**)realloc(TERMS, sizeof(char *) * slots);
}
void freeTERMS(int size) {
for (int i = 0; i < size; i++) {
if(strcmp(TERMS[i], "") != 0) free(TERMS[i]); //free(empty string) causes problems
else free(TERMS[i] - 1);
}
free(TERMS);
}