summaryrefslogtreecommitdiff
path: root/src/grammar.c
blob: 9265ef5333494407a91960fdefe082d53770fd56 (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
#include "grammar.h"

struct TNT_s {
  int type;                     /* 0 => T and NT otherwise */
  union { T t; NT nt; } data;
};

struct Rule_s {
  NT left;
  List *right;
};

TNT *new_tnt(int type, ...)
{
  va_list args;
  va_start(args, type);

  TNT *result = MYALLOC(TNT, 1);
  result->type = type;

  if (type) result->data.nt = va_arg(args, NT);
  else result->data.t = va_arg(args, T);

  va_end(args);

  return result;
}

Rule *new_rule(NT left, List *right)
{
  if (!right) return NULL;
  
  Rule *rule = MYALLOC(Rule, 1);

  rule->left = left;
  rule->right = right;

  return rule;
}

void print_tnt(void *element)
{
  TNT *tnt = (TNT*) element;

  if (tnt->type)
    printf("NT %u, ", tnt->data.nt);
  else
    printf("T %lu, ", tnt->data.t);
}

void print_rule(void *r)
{
  Rule *rule = (Rule *)r;
  printf("Rule: NT %u => ", rule->left);
  
  map_list(rule->right, print_tnt);

  printf("\n");
}

void print_grammar(Grammar g)
{
  printf("Printing a grammar:\n");
  map_list(g, print_rule);
  printf("\n");
}

List *new_tnt_string(char *format, int format_len, ...)
{
  /* FORMAT_LEN does not include the terminating null byte, so it
     should be > 0. */
  
  if (format_len <= 0) return NULL;
  
  List *result = new_list();
  
  va_list args;
  va_start(args, format_len);
  
  for (int point = 0; point < format_len; point++) {
    switch (*(format+point)) {
    case 'n':
      add_to_list(result, new_tnt(1, va_arg(args, NT)));
      break;
    case 't':
      add_to_list(result, new_tnt(0, va_arg(args, T)));
      break;
    default:
      eprintf("Wront character: %c\n", *(format+point));
      destroy_list(result, 1);
      va_end(args);
      return NULL;
      break;
    }
  }

  va_end(args);

  return result;
}

void destroy_rule(Rule *rule)
{
  destroy_list(rule->right, 1);
  free(rule);
}