blob: 55346b85b519cbf706ab7c596f39d5309053575d (
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
|
/* gramble - grammar ramble
* production engine for grammar derivations
*
* -scut
*/
/* we use a pushdown ntm like construct to generate valid derivations of the
* original grammar.
*/
/* terminal structure
*
* a simple word consisting of characters
*/
typedef struct {
unsigned int word_len; /* length, not including NUL */
unsigned char * word; /* if word_Len > 0: must be non-NULL */
} terminal;
/* nonterminal structure
*
* contains 'plist', a pointer to a production list of that nonterminal
*/
typedef struct {
unsigned int pcount; /* number of productions for that nterm */
symbol ** plist; /* list of productions for that nonterminal */
} nonterminal;
/* symbol structure
*
* shared linked list of symbols consisting of terminals and nonterminals.
* `next' being NULL marks the end of the derivation. `prev' being NULL marks
* the first.
* exactly one of `term' or `nterm' has to be non-NULL and point to a valid
* structure.
*/
typedef struct symbol {
symbol * prev;
symbol * next;
terminal * term;
nonterminal * nterm;
} symbol;
/* prod_genstatement
*
* derive a nonterminal completely to nonterminals. stop when the output
* buffer `obuf' has been filled with `obuf_len' bytes or when there are
* no more nonterminals to derive. start to derive from nonterminal `step'.
*
* return number of terminal characters derived on success
* return -1 on failure
*/
unsigned int
prod_genstatement (nonterminal *step,
unsigned char *obuf, unsigned long int obuf_len)
{
unsigned int produced = 0,
sub_produced = 0;
unsigned int psel; /* production selector */
symbol * prod; /* production to use */
if (obuf_len == 0)
return (0);
/* TODO: choose a more custom selection over a random pick
*/
psel = random_get (0, step->pcount - 1);
for (prod = start->plist[psel] ; prod != NULL ; prod = prod->next) {
/* terminals */
if (prod->term != NULL) {
if (prod->term->word_len < obuf_len) {
memcpy (obuf, prod->term->word,
prod->term->word_len);
obuf += prod->term->word_len;
obuf_len -= prod->term->word_len;
produced += prod->term->word_len;
} else /* no room left :-( */
return (produced);
/* non-terminals */
} else if (prod->nterm != NULL) {
sub_produced = prod_genstatement (prod->nterm,
obuf, obuf_len);
obuf += sub_produced;
obuf_len -= sub_produced;
}
}
/* finished deriving */
return (produced);
}
|