#include <stdlib.h>
#include <stdio.h>
typedef enum {
E_OK = 0,
E_WRONG = -1,
E_MEMORY = -2,
} error;
typedef enum {
FIRST,
SECOND
} choice;
#define CHECK(err) if (err) return (err)
#define FIELD(ptr, num) (&((ptr)->_##num))
#define DECLARE_SEQ(name, parser1, parser2) \
typedef struct result_##name { \
result_##parser1 _1; \
result_##parser2 _2; \
} result_##name; \
error name(const char ** data, result_##name * result) \
{ \
error err = parser1(data, &(result->_1)); \
CHECK(err); \
err = parser2(data, &(result->_2)); \
CHECK(err); \
return E_OK; \
} \
#define DECLARE_SEQ3(name, parser1, parser2, parser3) \
typedef struct result_##name { \
result_##parser1 _1; \
result_##parser2 _2; \
result_##parser3 _3; \
} result_##name; \
error name(const char ** data, result_##name * result) \
{ \
error err = parser1(data, &(result->_1)); \
CHECK(err); \
err = parser2(data, &(result->_2)); \
CHECK(err); \
err = parser3(data, &(result->_3)); \
CHECK(err); \
return E_OK; \
} \
#define DECLARE_ALT(name, parser1, parser2) \
typedef struct result_##name { \
choice choice; \
union { \
result_##parser1 _1; \
result_##parser2 _2; \
} value; \
} result_##name; \
error name(const char ** data, result_##name * result) \
{ \
error err = parser1(data, &(result->value._1)); \
if (err) { \
result->choice = SECOND; \
return parser2(data, &(result->value._2)); \
} else { \
result->choice = FIRST; \
return E_OK; \
} \
} \
#define DECLARE_STAR(name, parser) \
typedef struct result_##name { \
size_t num; \
result_##parser * items; \
} result_##name; \
error name(const char ** data, result_##name * result) \
{ \
result->items = NULL; \
size_t rec_size = sizeof(result_##parser); \
size_t num = 0; \
error err = E_OK; \
while (!err) { \
result_##parser * tmp = realloc(result->items, \
rec_size * (num + 1)); \
if (tmp == NULL) { \
free(result->items); \
result->items = NULL; \
result->num = 0; \
return E_MEMORY; \
} else { \
result->items = tmp; \
err = parser(data, result->items + num); \
num++; \
} \
} \
result->num = num - 1; \
return E_OK; \
} \
#define DECLARE_GET(name, var, condition) \
typedef char result_##name; \
error name(const char ** data, result_##name * result) \
{ \
char var; \
var = **data; \
if (condition) { \
*result = var; \
(*data)++; \
return E_OK; \
} else { \
return E_WRONG; \
} \
} \
#define PREDECLARE_REC(name) \
typedef void * result_##name; \
error name(const char ** data, result_##name * result); \
#define DECLARE_REC(name, parser) \
error name(const char ** data, result_##name * result) \
{ \
*result = malloc(sizeof(result_##parser)); \
if (*result == NULL) \
return E_MEMORY; \
return parser(data, (result_##parser *)(*result)); \
} \
DECLARE_GET(left, c, c=='(')
DECLARE_GET(right, c, c==')')
DECLARE_GET(letter, c, 'a' <= c && c <= 'z')
DECLARE_GET(addop, c, c == '+' || c == '-')
DECLARE_GET(mulop, c, c == '*' || c == '/')
DECLARE_GET(eoinp, c, c == '\0')
PREDECLARE_REC(expr_rec)
DECLARE_SEQ3(bracketed, left, expr_rec, right)
DECLARE_ALT(element, letter, bracketed)
DECLARE_SEQ(opelement, mulop, element)
DECLARE_STAR(elements, opelement)
DECLARE_SEQ(summand, element, elements)
DECLARE_SEQ(opsummand, addop, summand)
DECLARE_STAR(summands, opsummand)
DECLARE_SEQ(expr, summand, summands)
DECLARE_REC(expr_rec, expr)
DECLARE_SEQ(final, expr, eoinp)
void process_expr(result_expr * result);
void process_element(result_element * result)
{
if (result->choice == FIRST) {
printf("%c", result->value._1);
} else {
result_expr * subexpr = (result_expr *)result->value._2._2;
process_expr(subexpr);
}
}
void process_summand(result_summand * result)
{
result_element * first = FIELD(result, 1);
result_elements * rest = FIELD(result, 2);
if (rest->num == 0) {
process_element(first);
} else {
for (int i = rest->num - 1; i >= 0; i--) {
if (rest->items[i]._1 == '*') {
printf("MUL(");
} else {
printf("DIV(");
}
}
process_element(first);
for (int i = 0; i < rest->num; i++) {
printf(", ");
process_element(FIELD(rest->items + i, 2));
printf(")");
}
}
}
void process_expr(result_expr * result)
{
result_summand * first = FIELD(result, 1);
result_summands * rest = FIELD(result, 2);
if (rest->num == 0) {
process_summand(first);
} else {
for (int i = rest->num - 1; i >= 0; i--) {
if (rest->items[i]._1 == '+') {
printf("ADD(");
} else {
printf("SUB(");
}
}
process_summand(first);
for (int i = 0; i < rest->num; i++) {
printf(", ");
process_summand(FIELD(rest->items + i, 2));
printf(")");
}
}
}
void process(result_final * result)
{
process_expr(FIELD(result, 1));
printf("\n");
}
int main() {
result_final result;
char * input = "(a-b-c*d/(a-b))*(a+b*(c-d*e+h)/g)";
const char * ptr = input;
error err = final(&ptr, &result);
process(&result);
fflush(stdout);
return 0;
}