Skip to content

Commit 27cde3b

Browse files
committed
Make pcc_ prefix in pcc_ast.peg to be substituted with one specified with %prefix
1 parent 0dbb7d9 commit 27cde3b

File tree

2 files changed

+185
-82
lines changed

2 files changed

+185
-82
lines changed

import/code/README.md

+96-59
Original file line numberDiff line numberDiff line change
@@ -17,99 +17,135 @@ An import file that provides codes to make it easier to build an AST (abstract s
1717
The usage procedure is shown below.
1818

1919
1. Import `code/pcc_ast.peg` **after the last `%header` section** in the PEG file if any.
20-
```
20+
```c
2121
%import "code/pcc_ast.peg"
2222
```
2323
2. Set the designated data types as follows:
24-
```
24+
```c
2525
%value "pcc_ast_node_t *"
2626

2727
%auxil "pcc_ast_manager_t *"
2828
```
29+
30+
If the prefix is set with `%prefix`, all symbols starting with <code><b><i>pcc</i></b>\_</code> are changed to those with the specified prefix as below.
31+
```c
32+
%prefix "my"
33+
34+
%value "my_ast_node_t *"
35+
36+
%auxil "my_ast_manager_t *"
37+
```
2938
3. Create an AST node using either of the following functions in every rule action.
30-
- `pcc_ast_node_t *pcc_ast_node__create_0(void);`
39+
- <code><b><i>pcc</i></b>\_ast_node_t *<b><i>pcc</i></b>\_ast_node__create_0(void);</code>
3140
+ Returns a newly created nullary node.
32-
- `pcc_ast_node_t *pcc_ast_node__create_1(pcc_ast_node_t *node);`
41+
- <code><b><i>pcc</i></b>\_ast_node_t *<b><i>pcc</i></b>\_ast_node__create_0_str(const char *str);</code>
42+
+ Returns a newly created nullary node retaining a copy of the specified string.
43+
+ The string can be accessed using <code>const char *<b><i>pcc</i></b>\_ast_node__get_string(<b><i>pcc</i></b>\_ast_node_t *node)</code>.
44+
- <code><b><i>pcc</i></b>\_ast_node_t *<b><i>pcc</i></b>\_ast_node__create_1(<b><i>pcc</i></b>\_ast_node_t *node);</code>
3345
+ Returns a newly created unary node with one child node specified by the argument `node`.
34-
- `pcc_ast_node_t *pcc_ast_node__create_2(pcc_ast_node_t *node0, pcc_ast_node_t *node1);`
46+
- <code><b><i>pcc</i></b>\_ast_node_t *<b><i>pcc</i></b>\_ast_node__create_2(<b><i>pcc</i></b>\_ast_node_t *node0, <b><i>pcc</i></b>\_ast_node_t *node1);</code>
3547
+ Returns a newly created binary node with two child nodes specified by the argument `node0` and `node1`.
36-
- `pcc_ast_node_t *pcc_ast_node__create_3(pcc_ast_node_t *node0, pcc_ast_node_t *node1, pcc_ast_node_t *node2);`
48+
- <code><b><i>pcc</i></b>\_ast_node_t *<b><i>pcc</i></b>\_ast_node__create_3(<b><i>pcc</i></b>\_ast_node_t *node0, <b><i>pcc</i></b>\_ast_node_t *node1, <b><i>pcc</i></b>\_ast_node_t *node2);</code>
3749
+ Returns a newly created ternary node with three child nodes specified by the argument `node0`, `node1`, and `node2`.
38-
- `pcc_ast_node_t *pcc_ast_node__create_v(void);`
50+
- <code><b><i>pcc</i></b>\_ast_node_t *<b><i>pcc</i></b>\_ast_node__create_v(void);</code>
3951
+ Returns a newly created variadic node initially with no child node.
40-
- `pcc_ast_node_t *pcc_ast_node__add_child(pcc_ast_node_t *obj, pcc_ast_node_t *node);`
52+
- <code><b><i>pcc</i></b>\_ast_node_t *<b><i>pcc</i></b>\_ast_node__add_child(<b><i>pcc</i></b>\_ast_node_t *obj, <b><i>pcc</i></b>\_ast_node_t *node);</code>
4153
+ Adds a child node specified by the argument `node` to the variadic node `obj`.
4254
+ Can be used for `obj` as a variadic node only.
4355

44-
An example is shown below.
45-
```
46-
rule0 <- l:rule1 '+' r:rule1 { $$ = pcc_ast_node__create_2(l, r); }
47-
rule1 <- [0-9]+ { $$ = pcc_ast_node__create_0(); }
56+
As written above, if the prefix is set with `%prefix`, all symbols starting with <code><b><i>pcc</i></b>\_</code> are changed to those with the specified prefix.
57+
58+
There are the variants of the node creation functions that enable setting a label as an `int` value.
59+
The label can be used for specifying node kinds in order to make it easier to analyze the AST in the later parsing steps.
60+
- <code><b><i>pcc</i></b>\_ast_node_t *<b><i>pcc</i></b>\_ast_node__create_0_ext(int label);</code>
61+
- <code><b><i>pcc</i></b>\_ast_node_t *<b><i>pcc</i></b>\_ast_node__create_0_ext_str(int label, const char *str);</code>
62+
- <code><b><i>pcc</i></b>\_ast_node_t *<b><i>pcc</i></b>\_ast_node__create_1_ext(int label, <b><i>pcc</i></b>\_ast_node_t *node);</code>
63+
- <code><b><i>pcc</i></b>\_ast_node_t *<b><i>pcc</i></b>\_ast_node__create_2_ext(int label, <b><i>pcc</i></b>\_ast_node_t *node0, <b><i>pcc</i></b>\_ast_node_t *node1);</code>
64+
- <code><b><i>pcc</i></b>\_ast_node_t *<b><i>pcc</i></b>\_ast_node__create_3_ext(int label, <b><i>pcc</i></b>\_ast_node_t *node0, <b><i>pcc</i></b>\_ast_node_t *node1, <b><i>pcc</i></b>\_ast_node_t *node2);</code>
65+
- <code><b><i>pcc</i></b>\_ast_node_t *<b><i>pcc</i></b>\_ast_node__create_v_ext(int label);</code>
66+
67+
Every AST node retains the rule pattern matching range in the member variable `range`.
68+
Namely, `obj->range.start` and `obj->range.end` memorize `$0s` and `$0e` respectively at the time when the node `obj` was created in a rule action.
69+
70+
A usage example is shown below.
71+
```c
72+
rule0 <- l:rule1 '+' r:rule1 { $$ = my_ast_node__create_2(l, r); }
73+
rule1 <- [0-9]+ { $$ = my_ast_node__create_0(); }
4874
```
4975
4. Call the generated parser API functions as follows:
5076
```c
51-
pcc_ast_manager_t mgr;
52-
pcc_ast_manager__initialize(&mgr);
77+
my_ast_manager_t mgr;
78+
my_ast_manager__initialize(&mgr);
5379
{
54-
pcc_context_t *ctx = pcc_create(&mgr);
55-
pcc_ast_node_t *ast = NULL; /* ast: the root node of the AST */
56-
while (pcc_parse(ctx, &ast)) {
80+
my_context_t *ctx = my_create(&mgr);
81+
my_ast_node_t *ast = NULL; /* ast: the root node of the AST */
82+
while (my_parse(ctx, &ast)) {
5783
/* ... do something needed here */
58-
pcc_ast_node__destroy(ast);
84+
my_ast_node__destroy(ast);
5985
}
60-
pcc_destroy(ctx);
86+
my_destroy(ctx);
6187
}
62-
pcc_ast_manager__finalize(&mgr);
88+
my_ast_manager__finalize(&mgr);
6389
```
6490
This code can be executed safely with no memory leak (if "_do something needed here_" does not bring memory leaks).
6591
6692
#### Customization
6793
6894
To build a meaningful AST, customization of the node is needed.
69-
By defining the macro `PCC_AST_NODE_CUSTOM_DATA_DEFINED` in a `%header` section before `%import "code/pcc_ast.peg"`,
70-
the node member variable `custom` whose data type is `pcc_ast_node_custom_data_t` is enabled for storing node custom data.
95+
By defining the macro <code><b><i>PCC</i></b>\_AST_NODE_CUSTOM_DATA_DEFINED</code> in a `%header` section before `%import "code/pcc_ast.peg"`,
96+
the node member variable `custom` whose data type is <code><b><i>pcc</i></b>\_ast_node_custom_data_t</code> is enabled for storing node custom data.
97+
If the prefix is set with `%prefix`, the macro name <code><b><i>PCC</i></b>\_AST_NODE_CUSTOM_DATA_DEFINED</code> is changed to those with the uppercased prefix as below.
98+
```c
99+
%prefix "my"
100+
101+
%header {
102+
#define MY_AST_NODE_CUSTOM_DATA_DEFINED
103+
...
104+
}
105+
```
106+
71107
The concrete usage procedure is shown below.
72108
73109
1. Define the data type of the node custom data in a PEG file.
74110
```c
75111
%header {
76-
#define PCC_AST_NODE_CUSTOM_DATA_DEFINED /* <-- enables node custom data */
112+
#define MY_AST_NODE_CUSTOM_DATA_DEFINED /* <-- enables node custom data */
77113
78114
typedef struct node_custom_data_tag { /* <-- node custom data type */
79115
/* ... define member variables as needed */
80-
} pcc_ast_node_custom_data_t;
116+
} my_ast_node_custom_data_t;
81117
}
82118
```
83119
An example is as follows.
84120
```c
85121
%header {
86-
#define PCC_AST_NODE_CUSTOM_DATA_DEFINED
122+
#define MY_AST_NODE_CUSTOM_DATA_DEFINED
87123
88124
typedef struct text_data_tag {
89125
char *text;
90-
} pcc_ast_node_custom_data_t;
126+
} my_ast_node_custom_data_t;
91127
}
92128
```
93129
Make sure that this `%header` section is located before `%import "code/pcc_ast.peg"`.
94130
2. Set a node custom data value in every rule action as needed.
95131
An example is as follows.
96132
```c
97-
rule0 <- l:rule1 '+' r:rule1 { $$ = pcc_ast_node__create_2(l, r); $$->custom.text = strdup("+"); }
98-
rule1 <- < [0-9]+ > { $$ = pcc_ast_node__create_0(); $$->custom.text = strdup($1); }
133+
rule0 <- l:rule1 '+' r:rule1 { $$ = my_ast_node__create_2(l, r); $$->custom.text = strdup("+"); }
134+
rule1 <- < [0-9]+ > { $$ = my_ast_node__create_0(); $$->custom.text = strdup($1); }
99135
```
100136
3. Implement the initialization and finalization functions for the node custom data.
101-
- `void pcc_ast_node_custom_data__initialize(pcc_ast_node_custom_data_t *obj);`
137+
- <code>void <b><i>pcc</i></b>\_ast_node_custom_data__initialize(<b><i>pcc</i></b>\_ast_node_custom_data_t *obj);</code>
102138
+ Initializes the node custom data `obj`.
103-
- `void pcc_ast_node_custom_data__finalize(pcc_ast_node_custom_data_t *obj);`
139+
- <code>void <b><i>pcc</i></b>\_ast_node_custom_data__finalize(<b><i>pcc</i></b>\_ast_node_custom_data_t *obj);</code>
104140
+ Finalizes the node custom data `obj`.
105141
106142
An example is as follows.
107143
```c
108-
void pcc_ast_node_custom_data__initialize(pcc_ast_node_custom_data_t *obj) {
144+
void my_ast_node_custom_data__initialize(my_ast_node_custom_data_t *obj) {
109145
obj->text = NULL;
110146
}
111147
112-
void pcc_ast_node_custom_data__finalize(pcc_ast_node_custom_data_t *obj) {
148+
void my_ast_node_custom_data__finalize(my_ast_node_custom_data_t *obj) {
113149
free(obj->text);
114150
}
115151
```
@@ -120,11 +156,12 @@ Some macros are prepared to customize the behavior of memory allocation for AST
120156
The macro definition should be **in `%source` section** in the PEG source.
121157
122158
The following macros are available.
159+
Note that, unlike other symbols, the prefix of these macro names is never changed even when a different prefix is set with `%prefix`.
123160
124161
**`PCC_AST_MALLOC(`**_mgr_**`,`**_size_**`)`**
125162
126163
The function macro to allocate a memory block.
127-
The pointer to the instance of `pcc_ast_manager_t` that was passed to the API function `pcc_create()` can be retrieved from the argument _auxil_.
164+
The pointer to the instance of <code><b><i>pcc</i></b>\_ast_manager_t</code> that was passed to the API function <code><b><i>pcc</i></b>\_create()</code> can be retrieved from the argument _auxil_.
128165
It can be ignored if the instance does not concern memory allocation.
129166
The argument _size_ is the number of bytes to allocate.
130167
This macro must return a pointer to the allocated memory block, or `NULL` if no sufficient memory is available.
@@ -134,7 +171,7 @@ The default is defined as `PCC_MALLOC(mgr, size)`, which is used in the generate
134171
**`PCC_AST_REALLOC(`**_mgr_**`,`**_ptr_**`,`**_size_**`)`**
135172
136173
The function macro to reallocate the existing memory block.
137-
The pointer to the instance of `pcc_ast_manager_t` that was passed to the API function `pcc_create()` can be retrieved from the argument _auxil_.
174+
The pointer to the instance of <code><b><i>pcc</i></b>\_ast_manager_t</code> that was passed to the API function <code><b><i>pcc</i></b>\_create()</code> can be retrieved from the argument _auxil_.
138175
It can be ignored if the instance does not concern memory allocation.
139176
The argument _ptr_ is the pointer to the previously allocated memory block.
140177
The argument _size_ is the new number of bytes to reallocate.
@@ -146,7 +183,7 @@ The default is defined as `PCC_REALLOC(mgr, ptr, size)`, which is used in the ge
146183
**`PCC_AST_FREE(`**_mgr_**`,`**_ptr_**`)`**
147184
148185
The function macro to free the existing memory block.
149-
The pointer to the instance of `pcc_ast_manager_t` that was passed to the API function `pcc_create()` can be retrieved from the argument _auxil_.
186+
The pointer to the instance of <code><b><i>pcc</i></b>\_ast_manager_t</code> that was passed to the API function <code><b><i>pcc</i></b>\_create()</code> can be retrieved from the argument _auxil_.
150187
It can be ignored if the instance does not concern memory allocation.
151188
The argument _ptr_ is the pointer to the previously allocated memory block.
152189
This macro need not return a value.
@@ -167,16 +204,16 @@ This example accepts the same inputs as [*Desktop Calculator*](../../examples/ca
167204
```c
168205
%prefix "calc"
169206
170-
%value "pcc_ast_node_t *" # <-- must be set
207+
%value "calc_ast_node_t *" # <-- must be set
171208
172-
%auxil "pcc_ast_manager_t *" # <-- must be set
209+
%auxil "calc_ast_manager_t *" # <-- must be set
173210
174211
%header {
175-
#define PCC_AST_NODE_CUSTOM_DATA_DEFINED /* <-- enables node custom data */
212+
#define CALC_AST_NODE_CUSTOM_DATA_DEFINED /* <-- enables node custom data */
176213
177214
typedef struct text_data_tag { /* <-- node custom data type */
178215
char *text;
179-
} pcc_ast_node_custom_data_t;
216+
} calc_ast_node_custom_data_t;
180217
}
181218
182219
%source {
@@ -189,19 +226,19 @@ statement <- _ e:expression _ EOL { $$ = e; }
189226
190227
expression <- e:term { $$ = e; }
191228
192-
term <- l:term _ '+' _ r:factor { $$ = pcc_ast_node__create_2(l, r); $$->custom.text = strdup("+"); }
193-
/ l:term _ '-' _ r:factor { $$ = pcc_ast_node__create_2(l, r); $$->custom.text = strdup("-"); }
229+
term <- l:term _ '+' _ r:factor { $$ = calc_ast_node__create_2(l, r); $$->custom.text = strdup("+"); }
230+
/ l:term _ '-' _ r:factor { $$ = calc_ast_node__create_2(l, r); $$->custom.text = strdup("-"); }
194231
/ e:factor { $$ = e; }
195232
196-
factor <- l:factor _ '*' _ r:unary { $$ = pcc_ast_node__create_2(l, r); $$->custom.text = strdup("*"); }
197-
/ l:factor _ '/' _ r:unary { $$ = pcc_ast_node__create_2(l, r); $$->custom.text = strdup("/"); }
233+
factor <- l:factor _ '*' _ r:unary { $$ = calc_ast_node__create_2(l, r); $$->custom.text = strdup("*"); }
234+
/ l:factor _ '/' _ r:unary { $$ = calc_ast_node__create_2(l, r); $$->custom.text = strdup("/"); }
198235
/ e:unary { $$ = e; }
199236
200-
unary <- '+' _ e:unary { $$ = pcc_ast_node__create_1(e); $$->custom.text = strdup("+"); }
201-
/ '-' _ e:unary { $$ = pcc_ast_node__create_1(e); $$->custom.text = strdup("-"); }
237+
unary <- '+' _ e:unary { $$ = calc_ast_node__create_1(e); $$->custom.text = strdup("+"); }
238+
/ '-' _ e:unary { $$ = calc_ast_node__create_1(e); $$->custom.text = strdup("-"); }
202239
/ e:primary { $$ = e; }
203240
204-
primary <- < [0-9]+ > { $$ = pcc_ast_node__create_0(); $$->custom.text = strdup($1); }
241+
primary <- < [0-9]+ > { $$ = calc_ast_node__create_0(); $$->custom.text = strdup($1); }
205242
/ '(' _ e:expression _ ')' { $$ = e; }
206243
207244
_ <- [ \t]*
@@ -210,36 +247,36 @@ EOL <- '\n' / '\r\n' / '\r' / ';'
210247
%import "code/pcc_ast.peg" # <-- provides AST build functions
211248
212249
%%
213-
void pcc_ast_node_custom_data__initialize(pcc_ast_node_custom_data_t *obj) { /* <-- must be implemented when enabling node custom data */
250+
void calc_ast_node_custom_data__initialize(calc_ast_node_custom_data_t *obj) { /* <-- must be implemented when enabling node custom data */
214251
obj->text = NULL;
215252
}
216253
217-
void pcc_ast_node_custom_data__finalize(pcc_ast_node_custom_data_t *obj) { /* <-- must be implemented when enabling node custom data */
254+
void calc_ast_node_custom_data__finalize(calc_ast_node_custom_data_t *obj) { /* <-- must be implemented when enabling node custom data */
218255
free(obj->text);
219256
}
220257
221-
static void dump_ast(const pcc_ast_node_t *obj, int depth) {
258+
static void dump_ast(const calc_ast_node_t *obj, int depth) {
222259
if (obj) {
223260
switch (obj->type) {
224-
case PCC_AST_NODE_TYPE_NULLARY:
261+
case CALC_AST_NODE_TYPE_NULLARY:
225262
printf("%*s%s: \"%s\"\n", 2 * depth, "", "nullary", obj->custom.text);
226263
break;
227-
case PCC_AST_NODE_TYPE_UNARY:
264+
case CALC_AST_NODE_TYPE_UNARY:
228265
printf("%*s%s: \"%s\"\n", 2 * depth, "", "unary", obj->custom.text);
229266
dump_ast(obj->data.unary.node, depth + 1);
230267
break;
231-
case PCC_AST_NODE_TYPE_BINARY:
268+
case CALC_AST_NODE_TYPE_BINARY:
232269
printf("%*s%s: \"%s\"\n", 2 * depth, "", "binary", obj->custom.text);
233270
dump_ast(obj->data.binary.node[0], depth + 1);
234271
dump_ast(obj->data.binary.node[1], depth + 1);
235272
break;
236-
case PCC_AST_NODE_TYPE_TERNARY:
273+
case CALC_AST_NODE_TYPE_TERNARY:
237274
printf("%*s%s: \"%s\"\n", 2 * depth, "", "ternary", obj->custom.text);
238275
dump_ast(obj->data.ternary.node[0], depth + 1);
239276
dump_ast(obj->data.ternary.node[1], depth + 1);
240277
dump_ast(obj->data.ternary.node[2], depth + 1);
241278
break;
242-
case PCC_AST_NODE_TYPE_VARIADIC:
279+
case CALC_AST_NODE_TYPE_VARIADIC:
243280
printf("%*s%s: \"%s\"\n", 2 * depth, "", "variadic", obj->custom.text);
244281
{
245282
size_t i;
@@ -259,18 +296,18 @@ static void dump_ast(const pcc_ast_node_t *obj, int depth) {
259296
}
260297
261298
int main(int argc, char **argv) {
262-
pcc_ast_manager_t mgr;
263-
pcc_ast_manager__initialize(&mgr);
299+
calc_ast_manager_t mgr;
300+
calc_ast_manager__initialize(&mgr);
264301
{
265302
calc_context_t *ctx = calc_create(&mgr);
266-
pcc_ast_node_t *ast = NULL;
303+
calc_ast_node_t *ast = NULL;
267304
while (calc_parse(ctx, &ast)) {
268305
dump_ast(ast, 0);
269-
pcc_ast_node__destroy(ast);
306+
calc_ast_node__destroy(ast);
270307
}
271308
calc_destroy(ctx);
272309
}
273-
pcc_ast_manager__finalize(&mgr);
310+
calc_ast_manager__finalize(&mgr);
274311
return 0;
275312
}
276313
```

0 commit comments

Comments
 (0)