ruby-ll 1.0.0-java
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.yardopts +13 -0
- data/LICENSE +19 -0
- data/README.md +380 -0
- data/bin/ruby-ll +5 -0
- data/doc/DCO.md +25 -0
- data/doc/changelog.md +8 -0
- data/doc/css/common.css +77 -0
- data/ext/c/driver.c +258 -0
- data/ext/c/driver.h +28 -0
- data/ext/c/driver_config.c +209 -0
- data/ext/c/driver_config.h +53 -0
- data/ext/c/extconf.rb +13 -0
- data/ext/c/khash.h +619 -0
- data/ext/c/kvec.h +90 -0
- data/ext/c/libll.c +7 -0
- data/ext/c/libll.h +9 -0
- data/ext/c/macros.h +6 -0
- data/ext/java/Libll.java +12 -0
- data/ext/java/org/libll/Driver.java +247 -0
- data/ext/java/org/libll/DriverConfig.java +193 -0
- data/lib/libll.jar +0 -0
- data/lib/ll/ast/node.rb +13 -0
- data/lib/ll/branch.rb +57 -0
- data/lib/ll/cli.rb +118 -0
- data/lib/ll/code_generator.rb +32 -0
- data/lib/ll/compiled_configuration.rb +35 -0
- data/lib/ll/compiled_grammar.rb +167 -0
- data/lib/ll/configuration_compiler.rb +204 -0
- data/lib/ll/driver.rb +46 -0
- data/lib/ll/driver_config.rb +36 -0
- data/lib/ll/driver_template.erb +51 -0
- data/lib/ll/epsilon.rb +23 -0
- data/lib/ll/erb_context.rb +23 -0
- data/lib/ll/grammar_compiler.rb +359 -0
- data/lib/ll/lexer.rb +582 -0
- data/lib/ll/message.rb +102 -0
- data/lib/ll/parser.rb +280 -0
- data/lib/ll/parser_error.rb +8 -0
- data/lib/ll/rule.rb +53 -0
- data/lib/ll/setup.rb +11 -0
- data/lib/ll/source_line.rb +46 -0
- data/lib/ll/terminal.rb +29 -0
- data/lib/ll/token.rb +30 -0
- data/lib/ll/version.rb +3 -0
- data/lib/ll.rb +26 -0
- data/ruby-ll.gemspec +47 -0
- metadata +217 -0
data/doc/changelog.md
ADDED
data/doc/css/common.css
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
body
|
2
|
+
{
|
3
|
+
font-size: 14px;
|
4
|
+
line-height: 1.6;
|
5
|
+
margin: 0 auto;
|
6
|
+
max-width: 960px;
|
7
|
+
}
|
8
|
+
|
9
|
+
p code, dd code, li code
|
10
|
+
{
|
11
|
+
background: #f9f2f4;
|
12
|
+
color: #c7254e;
|
13
|
+
border-radius: 4px;
|
14
|
+
padding: 2px 4px;
|
15
|
+
}
|
16
|
+
|
17
|
+
pre.code
|
18
|
+
{
|
19
|
+
font-size: 13px;
|
20
|
+
line-height: 1.4;
|
21
|
+
overflow: auto;
|
22
|
+
}
|
23
|
+
|
24
|
+
blockquote
|
25
|
+
{
|
26
|
+
border-left: 5px solid #eee;
|
27
|
+
margin: 0px;
|
28
|
+
padding-left: 15px;
|
29
|
+
}
|
30
|
+
|
31
|
+
/**
|
32
|
+
* YARD uses generic table styles, using a special class means those tables
|
33
|
+
* don't get messed up.
|
34
|
+
*/
|
35
|
+
.table
|
36
|
+
{
|
37
|
+
border: 1px solid #ccc;
|
38
|
+
border-right: none;
|
39
|
+
border-collapse: separate;
|
40
|
+
border-spacing: 0;
|
41
|
+
text-align: left;
|
42
|
+
}
|
43
|
+
|
44
|
+
.table.full
|
45
|
+
{
|
46
|
+
width: 100%;
|
47
|
+
}
|
48
|
+
|
49
|
+
.table .field_name
|
50
|
+
{
|
51
|
+
min-width: 160px;
|
52
|
+
}
|
53
|
+
|
54
|
+
.table thead tr th.no_sort:first-child
|
55
|
+
{
|
56
|
+
width: 25px;
|
57
|
+
}
|
58
|
+
|
59
|
+
.table thead tr th, .table tbody tr td
|
60
|
+
{
|
61
|
+
border-bottom: 1px solid #ccc;
|
62
|
+
border-right: 1px solid #ccc;
|
63
|
+
min-width: 20px;
|
64
|
+
padding: 8px 5px;
|
65
|
+
text-align: left;
|
66
|
+
vertical-align: top;
|
67
|
+
}
|
68
|
+
|
69
|
+
.table tbody tr:last-child td
|
70
|
+
{
|
71
|
+
border-bottom: none;
|
72
|
+
}
|
73
|
+
|
74
|
+
.table tr:nth-child(odd) td
|
75
|
+
{
|
76
|
+
background: #f9f9f9;
|
77
|
+
}
|
data/ext/c/driver.c
ADDED
@@ -0,0 +1,258 @@
|
|
1
|
+
#include "driver.h"
|
2
|
+
|
3
|
+
#define T_EOF -1
|
4
|
+
#define T_RULE 0
|
5
|
+
#define T_TERMINAL 1
|
6
|
+
#define T_EPSILON 2
|
7
|
+
#define T_ACTION 3
|
8
|
+
|
9
|
+
ID id_config_const;
|
10
|
+
ID id_each_token;
|
11
|
+
ID id_send;
|
12
|
+
|
13
|
+
ID id_stack_input_error;
|
14
|
+
ID id_unexpected_input_error;
|
15
|
+
ID id_invalid_terminal_error;
|
16
|
+
|
17
|
+
/**
|
18
|
+
* Releases the memory of the driver's internal state and associated objects.
|
19
|
+
* This function is called automatically when a Driver instance is garbage
|
20
|
+
* collected.
|
21
|
+
*/
|
22
|
+
void ll_driver_free(DriverState *state)
|
23
|
+
{
|
24
|
+
kv_destroy(state->stack);
|
25
|
+
kv_destroy(state->value_stack);
|
26
|
+
|
27
|
+
free(state);
|
28
|
+
}
|
29
|
+
|
30
|
+
/**
|
31
|
+
* Marks the objects stored in the driver's internal state, preventing them from
|
32
|
+
* being garbage collected until the next GC run.
|
33
|
+
*/
|
34
|
+
void ll_driver_mark(DriverState *state)
|
35
|
+
{
|
36
|
+
size_t index;
|
37
|
+
|
38
|
+
FOR(index, kv_size(state->value_stack))
|
39
|
+
{
|
40
|
+
rb_gc_mark(kv_A(state->value_stack, index));
|
41
|
+
}
|
42
|
+
}
|
43
|
+
|
44
|
+
/**
|
45
|
+
* Allocates a new instance of the Driver class and prepares its internal state.
|
46
|
+
*/
|
47
|
+
VALUE ll_driver_allocate(VALUE klass)
|
48
|
+
{
|
49
|
+
DriverState *state = ALLOC(DriverState);
|
50
|
+
VALUE config = rb_const_get(klass, id_config_const);
|
51
|
+
|
52
|
+
Data_Get_Struct(config, DriverConfig, state->config);
|
53
|
+
|
54
|
+
kv_init(state->stack);
|
55
|
+
kv_init(state->value_stack);
|
56
|
+
|
57
|
+
return Data_Wrap_Struct(klass, ll_driver_mark, ll_driver_free, state);
|
58
|
+
}
|
59
|
+
|
60
|
+
/**
|
61
|
+
* Callback function for iterating over every input token and actually parsing
|
62
|
+
* said input.
|
63
|
+
*
|
64
|
+
* @param token An Array containing the token type as a Symbol and its value.
|
65
|
+
* @param self The Driver instance currently in use.
|
66
|
+
*/
|
67
|
+
VALUE ll_driver_each_token(VALUE token, VALUE self)
|
68
|
+
{
|
69
|
+
VALUE method;
|
70
|
+
VALUE action_args;
|
71
|
+
VALUE action_retval;
|
72
|
+
long num_args;
|
73
|
+
long args_i;
|
74
|
+
|
75
|
+
long token_id;
|
76
|
+
|
77
|
+
long rule_i;
|
78
|
+
long production_i;
|
79
|
+
|
80
|
+
long stack_type;
|
81
|
+
long stack_value;
|
82
|
+
|
83
|
+
DriverState *state;
|
84
|
+
|
85
|
+
VALUE type = rb_ary_entry(token, 0);
|
86
|
+
VALUE value = rb_ary_entry(token, 1);
|
87
|
+
|
88
|
+
Data_Get_Struct(self, DriverState, state);
|
89
|
+
|
90
|
+
while ( 1 )
|
91
|
+
{
|
92
|
+
if ( kv_size(state->stack) == 0 )
|
93
|
+
{
|
94
|
+
rb_funcall(self, id_unexpected_input_error, 1, token);
|
95
|
+
}
|
96
|
+
|
97
|
+
stack_value = kv_pop(state->stack);
|
98
|
+
stack_type = kv_pop(state->stack);
|
99
|
+
token_id = 0;
|
100
|
+
|
101
|
+
if ( TYPE(type) == T_SYMBOL )
|
102
|
+
{
|
103
|
+
khint64_t found = kh_get(int64_map, state->config->terminals, type);
|
104
|
+
|
105
|
+
if ( found != kh_end(state->config->terminals) )
|
106
|
+
{
|
107
|
+
token_id = kh_value(state->config->terminals, found);
|
108
|
+
}
|
109
|
+
}
|
110
|
+
|
111
|
+
/* Rule */
|
112
|
+
if ( stack_type == T_RULE )
|
113
|
+
{
|
114
|
+
production_i = state->config->table[stack_value][token_id];
|
115
|
+
|
116
|
+
if ( production_i == T_EOF )
|
117
|
+
{
|
118
|
+
rb_funcall(
|
119
|
+
self,
|
120
|
+
id_stack_input_error,
|
121
|
+
2,
|
122
|
+
INT2NUM(stack_value),
|
123
|
+
token
|
124
|
+
);
|
125
|
+
}
|
126
|
+
else
|
127
|
+
{
|
128
|
+
FOR(rule_i, state->config->rule_lengths[production_i])
|
129
|
+
{
|
130
|
+
kv_push(
|
131
|
+
long,
|
132
|
+
state->stack,
|
133
|
+
state->config->rules[production_i][rule_i]
|
134
|
+
);
|
135
|
+
}
|
136
|
+
}
|
137
|
+
}
|
138
|
+
/* Terminal */
|
139
|
+
else if ( stack_type == T_TERMINAL )
|
140
|
+
{
|
141
|
+
if ( stack_value == token_id )
|
142
|
+
{
|
143
|
+
kv_push(VALUE, state->value_stack, value);
|
144
|
+
|
145
|
+
RB_GC_GUARD(value);
|
146
|
+
|
147
|
+
break;
|
148
|
+
}
|
149
|
+
else
|
150
|
+
{
|
151
|
+
rb_funcall(
|
152
|
+
self,
|
153
|
+
id_invalid_terminal_error,
|
154
|
+
2,
|
155
|
+
INT2NUM(token_id),
|
156
|
+
INT2NUM(stack_value)
|
157
|
+
);
|
158
|
+
}
|
159
|
+
}
|
160
|
+
/* Action */
|
161
|
+
else if ( stack_type == T_ACTION )
|
162
|
+
{
|
163
|
+
method = state->config->action_names[stack_value];
|
164
|
+
num_args = state->config->action_arg_amounts[stack_value];
|
165
|
+
action_args = rb_ary_new2(num_args);
|
166
|
+
args_i = num_args;
|
167
|
+
|
168
|
+
if ( args_i > (long) kv_size(state->value_stack) )
|
169
|
+
{
|
170
|
+
args_i = (long) kv_size(state->value_stack);
|
171
|
+
}
|
172
|
+
|
173
|
+
while ( args_i-- )
|
174
|
+
{
|
175
|
+
if ( kv_size(state->value_stack) > 0 )
|
176
|
+
{
|
177
|
+
rb_ary_store(
|
178
|
+
action_args,
|
179
|
+
args_i,
|
180
|
+
kv_pop(state->value_stack)
|
181
|
+
);
|
182
|
+
}
|
183
|
+
}
|
184
|
+
|
185
|
+
action_retval = rb_funcall(self, id_send, 2, method, action_args);
|
186
|
+
|
187
|
+
kv_push(VALUE, state->value_stack, action_retval);
|
188
|
+
|
189
|
+
RB_GC_GUARD(action_retval);
|
190
|
+
}
|
191
|
+
/* EOF */
|
192
|
+
else if ( stack_type == T_EOF )
|
193
|
+
{
|
194
|
+
break;
|
195
|
+
}
|
196
|
+
}
|
197
|
+
|
198
|
+
return Qnil;
|
199
|
+
}
|
200
|
+
|
201
|
+
/**
|
202
|
+
* Starts the parser.
|
203
|
+
*
|
204
|
+
* @param self The Driver instance the "parse" method was called on.
|
205
|
+
*/
|
206
|
+
VALUE ll_driver_parse(VALUE self)
|
207
|
+
{
|
208
|
+
long index;
|
209
|
+
|
210
|
+
DriverState *state;
|
211
|
+
|
212
|
+
Data_Get_Struct(self, DriverState, state);
|
213
|
+
|
214
|
+
/* EOF rule */
|
215
|
+
kv_push(long, state->stack, T_EOF);
|
216
|
+
kv_push(long, state->stack, T_EOF);
|
217
|
+
|
218
|
+
/* Start rule */
|
219
|
+
FOR(index, state->config->rule_lengths[0])
|
220
|
+
{
|
221
|
+
kv_push(long, state->stack, state->config->rules[0][index]);
|
222
|
+
}
|
223
|
+
|
224
|
+
rb_block_call(
|
225
|
+
self,
|
226
|
+
id_each_token,
|
227
|
+
0,
|
228
|
+
NULL,
|
229
|
+
RUBY_METHOD_FUNC(ll_driver_each_token),
|
230
|
+
self
|
231
|
+
);
|
232
|
+
|
233
|
+
if ( kv_size(state->value_stack) == 0 )
|
234
|
+
{
|
235
|
+
return Qnil;
|
236
|
+
}
|
237
|
+
else
|
238
|
+
{
|
239
|
+
return kv_pop(state->value_stack);
|
240
|
+
}
|
241
|
+
}
|
242
|
+
|
243
|
+
void Init_ll_driver()
|
244
|
+
{
|
245
|
+
VALUE mLL = rb_const_get(rb_cObject, rb_intern("LL"));
|
246
|
+
VALUE cDriver = rb_const_get(mLL, rb_intern("Driver"));
|
247
|
+
|
248
|
+
rb_define_method(cDriver, "parse", ll_driver_parse, 0);
|
249
|
+
|
250
|
+
rb_define_alloc_func(cDriver, ll_driver_allocate);
|
251
|
+
|
252
|
+
id_send = rb_intern("send");
|
253
|
+
id_config_const = rb_intern("CONFIG");
|
254
|
+
id_each_token = rb_intern("each_token");
|
255
|
+
id_stack_input_error = rb_intern("stack_input_error");
|
256
|
+
id_invalid_terminal_error = rb_intern("invalid_terminal_error");
|
257
|
+
id_unexpected_input_error = rb_intern("unexpected_input_error");
|
258
|
+
}
|
data/ext/c/driver.h
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
#ifndef LIBLL_DRIVER_H
|
2
|
+
#define LIBLL_DRIVER_H
|
3
|
+
|
4
|
+
#include <ruby.h>
|
5
|
+
#include "driver_config.h"
|
6
|
+
#include "macros.h"
|
7
|
+
#include "kvec.h"
|
8
|
+
|
9
|
+
/**
|
10
|
+
* Struct containing the internal state of a Driver instance. This struct is
|
11
|
+
* sadly required as rb_block_call() doesn't take any extra, custom arguments
|
12
|
+
* (other than a single VALUE). This means we have to use
|
13
|
+
* Data_Wrap_Struct/Data_Get_Struct instead :<
|
14
|
+
*/
|
15
|
+
typedef struct
|
16
|
+
{
|
17
|
+
DriverConfig *config;
|
18
|
+
|
19
|
+
/* Stack for storing the rules/actions/etc to process */
|
20
|
+
kvec_t(long) stack;
|
21
|
+
|
22
|
+
/* Stack for action return values */
|
23
|
+
kvec_t(VALUE) value_stack;
|
24
|
+
} DriverState;
|
25
|
+
|
26
|
+
extern void Init_ll_driver();
|
27
|
+
|
28
|
+
#endif
|
@@ -0,0 +1,209 @@
|
|
1
|
+
#include "driver_config.h"
|
2
|
+
|
3
|
+
/**
|
4
|
+
* Releases memory of the DriverConfig struct and its members.
|
5
|
+
*/
|
6
|
+
void ll_driver_config_free(DriverConfig *config)
|
7
|
+
{
|
8
|
+
long rindex;
|
9
|
+
|
10
|
+
FOR(rindex, config->rules_count)
|
11
|
+
{
|
12
|
+
free(config->rules[rindex]);
|
13
|
+
}
|
14
|
+
|
15
|
+
FOR(rindex, config->table_count)
|
16
|
+
{
|
17
|
+
free(config->table[rindex]);
|
18
|
+
}
|
19
|
+
|
20
|
+
free(config->rules);
|
21
|
+
free(config->rule_lengths);
|
22
|
+
free(config->table);
|
23
|
+
free(config->action_names);
|
24
|
+
free(config->action_arg_amounts);
|
25
|
+
|
26
|
+
kh_destroy(int64_map, config->terminals);
|
27
|
+
|
28
|
+
free(config);
|
29
|
+
}
|
30
|
+
|
31
|
+
/**
|
32
|
+
* Marks various members of the DriverConfig to ensure they are not garbage
|
33
|
+
* collected until at least the next GC run.
|
34
|
+
*/
|
35
|
+
void ll_driver_config_mark(DriverConfig *config)
|
36
|
+
{
|
37
|
+
long index;
|
38
|
+
|
39
|
+
FOR(index, config->actions_count)
|
40
|
+
{
|
41
|
+
rb_gc_mark(config->action_names[index]);
|
42
|
+
}
|
43
|
+
}
|
44
|
+
|
45
|
+
/**
|
46
|
+
* Allocates a new DriverConfig.
|
47
|
+
*/
|
48
|
+
VALUE ll_driver_config_allocate(VALUE klass)
|
49
|
+
{
|
50
|
+
DriverConfig *config = ALLOC(DriverConfig);
|
51
|
+
|
52
|
+
return Data_Wrap_Struct(
|
53
|
+
klass,
|
54
|
+
ll_driver_config_mark,
|
55
|
+
ll_driver_config_free, config
|
56
|
+
);
|
57
|
+
}
|
58
|
+
|
59
|
+
/**
|
60
|
+
* Stores the terminals of the parser in the DriverConfig struct.
|
61
|
+
*
|
62
|
+
* @param self The current DriverConfig instance.
|
63
|
+
* @param array The terminals to store in the struct.
|
64
|
+
*/
|
65
|
+
VALUE ll_driver_config_set_terminals(VALUE self, VALUE array)
|
66
|
+
{
|
67
|
+
long index;
|
68
|
+
|
69
|
+
int key_ret;
|
70
|
+
khint64_t key;
|
71
|
+
VALUE token;
|
72
|
+
DriverConfig *config;
|
73
|
+
long count = RARRAY_LEN(array);
|
74
|
+
|
75
|
+
Data_Get_Struct(self, DriverConfig, config);
|
76
|
+
|
77
|
+
config->terminals = kh_init(int64_map);
|
78
|
+
|
79
|
+
FOR(index, count)
|
80
|
+
{
|
81
|
+
token = rb_ary_entry(array, index);
|
82
|
+
key = kh_put(int64_map, config->terminals, token, &key_ret);
|
83
|
+
|
84
|
+
kh_value(config->terminals, key) = index;
|
85
|
+
}
|
86
|
+
|
87
|
+
return Qnil;
|
88
|
+
}
|
89
|
+
|
90
|
+
/**
|
91
|
+
* Stores the rules in the DriverConfig struct.
|
92
|
+
*
|
93
|
+
* @param self The DriverConfig instance.
|
94
|
+
* @param array The rules to store.
|
95
|
+
*/
|
96
|
+
VALUE ll_driver_config_set_rules(VALUE self, VALUE array)
|
97
|
+
{
|
98
|
+
long rindex;
|
99
|
+
long cindex;
|
100
|
+
long col_count;
|
101
|
+
DriverConfig *config;
|
102
|
+
VALUE row;
|
103
|
+
long row_count = RARRAY_LEN(array);
|
104
|
+
|
105
|
+
Data_Get_Struct(self, DriverConfig, config);
|
106
|
+
|
107
|
+
config->rules = ALLOC_N(long*, row_count);
|
108
|
+
config->rule_lengths = ALLOC_N(long, row_count);
|
109
|
+
|
110
|
+
FOR(rindex, row_count)
|
111
|
+
{
|
112
|
+
row = rb_ary_entry(array, rindex);
|
113
|
+
col_count = RARRAY_LEN(row);
|
114
|
+
|
115
|
+
config->rules[rindex] = ALLOC_N(long, col_count);
|
116
|
+
|
117
|
+
FOR(cindex, col_count)
|
118
|
+
{
|
119
|
+
config->rules[rindex][cindex] = NUM2INT(rb_ary_entry(row, cindex));
|
120
|
+
}
|
121
|
+
|
122
|
+
config->rule_lengths[rindex] = col_count;
|
123
|
+
}
|
124
|
+
|
125
|
+
config->rules_count = row_count;
|
126
|
+
|
127
|
+
return Qnil;
|
128
|
+
}
|
129
|
+
|
130
|
+
/**
|
131
|
+
* Stores the lookup table in the DriverConfig struct.
|
132
|
+
*
|
133
|
+
* @param self The DriverConfig instance.
|
134
|
+
* @param array The lookup table.
|
135
|
+
*/
|
136
|
+
VALUE ll_driver_config_set_table(VALUE self, VALUE array)
|
137
|
+
{
|
138
|
+
long rindex;
|
139
|
+
long cindex;
|
140
|
+
long col_count;
|
141
|
+
VALUE row;
|
142
|
+
DriverConfig *config;
|
143
|
+
long row_count = RARRAY_LEN(array);
|
144
|
+
|
145
|
+
Data_Get_Struct(self, DriverConfig, config);
|
146
|
+
|
147
|
+
config->table = ALLOC_N(long*, row_count);
|
148
|
+
|
149
|
+
FOR(rindex, row_count)
|
150
|
+
{
|
151
|
+
row = rb_ary_entry(array, rindex);
|
152
|
+
col_count = RARRAY_LEN(row);
|
153
|
+
|
154
|
+
config->table[rindex] = ALLOC_N(long, col_count);
|
155
|
+
|
156
|
+
FOR(cindex, col_count)
|
157
|
+
{
|
158
|
+
config->table[rindex][cindex] = NUM2INT(rb_ary_entry(row, cindex));
|
159
|
+
}
|
160
|
+
}
|
161
|
+
|
162
|
+
config->table_count = row_count;
|
163
|
+
|
164
|
+
return Qnil;
|
165
|
+
}
|
166
|
+
|
167
|
+
/**
|
168
|
+
* Stores the callback actions in the DriverConfig struct.
|
169
|
+
*
|
170
|
+
* @param self The DriverConfig instance.
|
171
|
+
* @param array The callback actions and their arities.
|
172
|
+
*/
|
173
|
+
VALUE ll_driver_config_set_actions(VALUE self, VALUE array)
|
174
|
+
{
|
175
|
+
long rindex;
|
176
|
+
VALUE row;
|
177
|
+
DriverConfig *config;
|
178
|
+
long row_count = RARRAY_LEN(array);
|
179
|
+
|
180
|
+
Data_Get_Struct(self, DriverConfig, config);
|
181
|
+
|
182
|
+
config->action_names = ALLOC_N(ID, row_count);
|
183
|
+
config->action_arg_amounts = ALLOC_N(long, row_count);
|
184
|
+
|
185
|
+
FOR(rindex, row_count)
|
186
|
+
{
|
187
|
+
row = rb_ary_entry(array, rindex);
|
188
|
+
|
189
|
+
config->action_names[rindex] = rb_ary_entry(row, 0);
|
190
|
+
config->action_arg_amounts[rindex] = NUM2INT(rb_ary_entry(row, 1));
|
191
|
+
}
|
192
|
+
|
193
|
+
config->actions_count = row_count;
|
194
|
+
|
195
|
+
return Qnil;
|
196
|
+
}
|
197
|
+
|
198
|
+
void Init_ll_driver_config()
|
199
|
+
{
|
200
|
+
VALUE mLL = rb_const_get(rb_cObject, rb_intern("LL"));
|
201
|
+
VALUE klass = rb_const_get(mLL, rb_intern("DriverConfig"));
|
202
|
+
|
203
|
+
rb_define_alloc_func(klass, ll_driver_config_allocate);
|
204
|
+
|
205
|
+
rb_define_method(klass, "terminals_native=", ll_driver_config_set_terminals, 1);
|
206
|
+
rb_define_method(klass, "rules_native=", ll_driver_config_set_rules, 1);
|
207
|
+
rb_define_method(klass, "table_native=", ll_driver_config_set_table, 1);
|
208
|
+
rb_define_method(klass, "actions_native=", ll_driver_config_set_actions, 1);
|
209
|
+
}
|