gen-text 0.0.6 → 0.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +64 -35
- data/lib/gen_text/compile.rb +33 -2
- data/lib/gen_text/vm.rb +40 -3
- metadata +2 -2
data/README.md
CHANGED
@@ -9,6 +9,23 @@ Install
|
|
9
9
|
- Install [Ruby](http://ruby-lang.org) 1.9.3 or higher.
|
10
10
|
- `gem install gen-text`
|
11
11
|
|
12
|
+
Example
|
13
|
+
-------
|
14
|
+
|
15
|
+
Simple grammar:
|
16
|
+
|
17
|
+
expr =
|
18
|
+
expr ('+'|'-') expr |
|
19
|
+
expr ('*'|'/') expr |
|
20
|
+
'(' expr ')' |
|
21
|
+
0...1000 ;
|
22
|
+
|
23
|
+
Sample output:
|
24
|
+
|
25
|
+
(914-548*155+131*799)*827
|
26
|
+
|
27
|
+
See more examples in "sample" directory.
|
28
|
+
|
12
29
|
Usage
|
13
30
|
-----
|
14
31
|
|
@@ -69,8 +86,9 @@ You may use the following expressions in the rules' right part:
|
|
69
86
|
<tt>'str'</tt>
|
70
87
|
</td>
|
71
88
|
<td>
|
72
|
-
|
73
|
-
<p
|
89
|
+
Generate a string.
|
90
|
+
<p></p>
|
91
|
+
Following escape sequences are allowed: "\n", "\t", "\e" and "\." where "." is an arbitrary character.
|
74
92
|
</td>
|
75
93
|
</tr>
|
76
94
|
<tr>
|
@@ -78,7 +96,7 @@ You may use the following expressions in the rules' right part:
|
|
78
96
|
<td>Generate an UTF-8 character sequence corresponding to the Unicode code. E. g.: <tt>U+000A</tt> is equivalent to <tt>"\n"</tt>.</td>
|
79
97
|
</tr>
|
80
98
|
<tr>
|
81
|
-
<td><tt>n</tt> (a
|
99
|
+
<td><tt>n</tt> (a number)</td>
|
82
100
|
<td>Generate a number</td>
|
83
101
|
</tr>
|
84
102
|
<tr>
|
@@ -87,7 +105,7 @@ You may use the following expressions in the rules' right part:
|
|
87
105
|
</tr>
|
88
106
|
<tr>
|
89
107
|
<td><tt>nonterm</tt></td>
|
90
|
-
<td
|
108
|
+
<td>—</td>
|
91
109
|
</tr>
|
92
110
|
<tr>
|
93
111
|
<td colspan="2"><center><strong>Combinators</strong></center></td>
|
@@ -104,33 +122,28 @@ You may use the following expressions in the rules' right part:
|
|
104
122
|
</tr>
|
105
123
|
<tr>
|
106
124
|
<td>
|
107
|
-
|
108
|
-
|
109
|
-
| expr
|
110
|
-
</tt>
|
125
|
+
<tt><pre>| expr
|
126
|
+
| expr</pre></tt>
|
111
127
|
</td>
|
112
128
|
<td>Random choice (another form).</td>
|
113
129
|
</tr>
|
114
130
|
<tr>
|
115
131
|
<td>
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
| expr
|
120
|
-
</tt>
|
132
|
+
<tt><pre>| [m%] expr
|
133
|
+
| [n%] expr
|
134
|
+
| expr</pre></tt>
|
121
135
|
</td>
|
122
136
|
<td>
|
123
|
-
|
124
|
-
<p
|
137
|
+
Random choice with specific probabilities.
|
138
|
+
<p></p>
|
139
|
+
If probability is unspecified then it is calculated automatically.
|
125
140
|
</td>
|
126
141
|
</tr>
|
127
142
|
<tr>
|
128
143
|
<td>
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
| expr
|
133
|
-
</tt>
|
144
|
+
<tt><pre>| [0.1] expr
|
145
|
+
| [0.3] expr
|
146
|
+
| expr</pre></tt>
|
134
147
|
</td>
|
135
148
|
<td>
|
136
149
|
The same as above. Probabilities may be specified as floating point numbers between 0.0 and 1.0.
|
@@ -145,7 +158,7 @@ You may use the following expressions in the rules' right part:
|
|
145
158
|
<tt>expr*[m...n]</tt> <br/>
|
146
159
|
</td>
|
147
160
|
<td>
|
148
|
-
|
161
|
+
Repeat <tt>expr</tt> many times:
|
149
162
|
<ul>
|
150
163
|
<li>0 or more times</li>
|
151
164
|
<li>1 or more times</li>
|
@@ -153,17 +166,39 @@ You may use the following expressions in the rules' right part:
|
|
153
166
|
<li>exactly <tt>n</tt> times</li>
|
154
167
|
<li>between <tt>m</tt> and <tt>n</tt> times</li>
|
155
168
|
</ul>
|
156
|
-
<p
|
169
|
+
<p></p>
|
170
|
+
<strong>Note:</strong> you may use <tt>inf</tt> ("infinity") instead of <tt>m</tt> or <tt>n</tt>.
|
171
|
+
</td>
|
172
|
+
</tr>
|
173
|
+
<tr>
|
174
|
+
<td>
|
175
|
+
<tt>n:expr</tt>
|
176
|
+
</td>
|
177
|
+
<td>
|
178
|
+
Capture a string generated by <tt>expr</tt> into variable <tt>n</tt>. The variable may then be used in <a href="#Code_insertions">Ruby code insertions</a>.
|
179
|
+
<p></p>
|
180
|
+
You may also use names like <tt>$n</tt> and <tt>@n</tt>.
|
181
|
+
<p></p>
|
182
|
+
<strong>Note</strong>: presence of this expression turns on backtracking and output buffering and may result in enormous memory usage.
|
157
183
|
</td>
|
158
184
|
</tr>
|
159
185
|
<tr>
|
160
|
-
<td
|
186
|
+
<td>
|
187
|
+
<tt>n := expr</tt>
|
188
|
+
</td>
|
189
|
+
<td>
|
190
|
+
The same as above but the output generated by <tt>expr</tt> is discarded.
|
191
|
+
</td>
|
192
|
+
</tr>
|
193
|
+
<tr>
|
194
|
+
<td colspan="2"><center><strong><a id="Code_insertions"></a>Ruby code insertions</strong></center></td>
|
161
195
|
</tr>
|
162
196
|
<tr>
|
163
197
|
<td><tt>{ code }</tt></td>
|
164
198
|
<td>
|
165
|
-
|
166
|
-
<p
|
199
|
+
Execute the code. Generate nothing.
|
200
|
+
<p></p>
|
201
|
+
<strong>Note</strong>: all code insertions inside a rule share the same scope.
|
167
202
|
</td>
|
168
203
|
</tr>
|
169
204
|
<tr>
|
@@ -173,15 +208,14 @@ You may use the following expressions in the rules' right part:
|
|
173
208
|
<tr>
|
174
209
|
<td><tt>{? code }</tt></td>
|
175
210
|
<td>
|
176
|
-
|
177
|
-
<p
|
211
|
+
Condition. A code which must evaluate to true.
|
212
|
+
<p></p>
|
213
|
+
<strong>Note</strong>: presence of this expression turns on backtracking and output buffering and may result in enormous memory usage.
|
178
214
|
</td>
|
179
215
|
</tr>
|
180
216
|
</tbody>
|
181
217
|
</table>
|
182
218
|
|
183
|
-
TODO: Capture the generated output.
|
184
|
-
|
185
219
|
### Alternate syntax ###
|
186
220
|
|
187
221
|
You may use "<-" instead of "=":
|
@@ -194,13 +228,8 @@ and "/" instead of "|":
|
|
194
228
|
|
195
229
|
`simple choice` <- "a" / "b" ;
|
196
230
|
|
197
|
-
Examples
|
198
|
-
--------
|
199
|
-
|
200
|
-
See them in "sample" directory.
|
201
|
-
|
202
231
|
Links
|
203
232
|
-----
|
204
233
|
|
205
|
-
- [Documentation](http://www.rubydoc.info/gems/gen-text/0.0.
|
234
|
+
- [Documentation](http://www.rubydoc.info/gems/gen-text/0.0.7)
|
206
235
|
- [Source code](https://github.com/LavirtheWhiolet/gen-text)
|
data/lib/gen_text/compile.rb
CHANGED
@@ -256,6 +256,19 @@ module GenText
|
|
256
256
|
|
257
257
|
end
|
258
258
|
|
259
|
+
Capture = ASTNode.new :var_name, :expr, :discard_output do
|
260
|
+
|
261
|
+
def to_vm_code(context)
|
262
|
+
[
|
263
|
+
*generated_from(pos),
|
264
|
+
[:push_pos],
|
265
|
+
*expr.to_vm_code(context),
|
266
|
+
[:capture, context.rule_scope, var_name, discard_output]
|
267
|
+
]
|
268
|
+
end
|
269
|
+
|
270
|
+
end
|
271
|
+
|
259
272
|
Choice = ASTNode.new :alternatives do
|
260
273
|
|
261
274
|
def to_vm_code(context)
|
@@ -372,8 +385,8 @@ module GenText
|
|
372
385
|
end
|
373
386
|
|
374
387
|
rule :seq do
|
375
|
-
e =
|
376
|
-
e2 =
|
388
|
+
e = capture and many {
|
389
|
+
e2 = capture and e = _(Seq[to_seq_subexprs(e) + to_seq_subexprs(e2)])
|
377
390
|
} and
|
378
391
|
e
|
379
392
|
end
|
@@ -385,6 +398,18 @@ module GenText
|
|
385
398
|
end
|
386
399
|
end
|
387
400
|
|
401
|
+
rule :capture do
|
402
|
+
_{
|
403
|
+
n = ruby_var_name and
|
404
|
+
d = (
|
405
|
+
_{ colon_eq and :discard_output } or
|
406
|
+
_{ colon and :do_not_discard_output }
|
407
|
+
) and
|
408
|
+
e = repeat and _(Capture[n, e, (d == :discard_output)])
|
409
|
+
} or
|
410
|
+
_{ repeat }
|
411
|
+
end
|
412
|
+
|
388
413
|
rule :repeat do
|
389
414
|
e = primary and many {
|
390
415
|
_{
|
@@ -456,6 +481,8 @@ module GenText
|
|
456
481
|
token :rbracket, "]"
|
457
482
|
token :dot, "."
|
458
483
|
token :larrow, "<-"
|
484
|
+
token :colon, ":"
|
485
|
+
token :colon_eq, ":="
|
459
486
|
|
460
487
|
# Parses "#{start} #{code_part} } #{whitespace_and_comments}".
|
461
488
|
# Returns the code_part.
|
@@ -479,6 +506,10 @@ module GenText
|
|
479
506
|
}.join
|
480
507
|
end
|
481
508
|
|
509
|
+
token :ruby_var_name, "variable name" do
|
510
|
+
scan(/[\@\$]?[a-z_][a-z_0-9]*/)
|
511
|
+
end
|
512
|
+
|
482
513
|
token :string do
|
483
514
|
_{ string0('"') } or
|
484
515
|
_{ string0("'") } or
|
data/lib/gen_text/vm.rb
CHANGED
@@ -7,12 +7,15 @@ module GenText
|
|
7
7
|
# @return [Boolean] true if +program+ may result in calling
|
8
8
|
# {IO#pos=} and false otherwise.
|
9
9
|
def self.may_set_out_pos?(program)
|
10
|
-
program.any?
|
10
|
+
program.any? do |instruction|
|
11
|
+
[:rescue_, :capture].include? instruction.first
|
12
|
+
end
|
11
13
|
end
|
12
14
|
|
13
15
|
# Executes +program+.
|
14
16
|
#
|
15
|
-
#
|
17
|
+
# If +program+ may result in calling {IO#pos=} (see {VM::may_set_out_pos?}
|
18
|
+
# then after the execution the +out+ may contain garbage after its {IO#pos}.
|
16
19
|
# It is up to the caller to truncate the garbage or to copy the useful data.
|
17
20
|
#
|
18
21
|
# @param program Array of <code>[:method_id, *args]</code>.
|
@@ -165,6 +168,32 @@ module GenText
|
|
165
168
|
@pc += 1
|
166
169
|
end
|
167
170
|
|
171
|
+
# - p := {#pop};
|
172
|
+
# - +binding_+.eval(set variable named +name+ to a substring of {#out} from
|
173
|
+
# p to current position);
|
174
|
+
# - if +discard_output+ is true then set {IO#pos} of {#out} to p.
|
175
|
+
#
|
176
|
+
# @param [Binding] binding_
|
177
|
+
# @param [String] name
|
178
|
+
# @param [Boolean] discard_output
|
179
|
+
# @return [void]
|
180
|
+
def capture(binding_, name, discard_output)
|
181
|
+
capture_start_pos = @stack.pop
|
182
|
+
capture_end_pos = @out.pos
|
183
|
+
captured_string = begin
|
184
|
+
@out.pos = capture_start_pos
|
185
|
+
@out.read(capture_end_pos - capture_start_pos)
|
186
|
+
end
|
187
|
+
@out.pos =
|
188
|
+
if discard_output then
|
189
|
+
capture_start_pos
|
190
|
+
else
|
191
|
+
capture_end_pos
|
192
|
+
end
|
193
|
+
binding_.eval("#{name} = #{captured_string.inspect}")
|
194
|
+
@pc += 1
|
195
|
+
end
|
196
|
+
|
168
197
|
# {#push}(eval(+ruby_code+, +file+, +line+))
|
169
198
|
#
|
170
199
|
# @param [Binding] binding_
|
@@ -177,7 +206,15 @@ module GenText
|
|
177
206
|
@pc += 1
|
178
207
|
end
|
179
208
|
|
180
|
-
# {#push}({#out}'s {IO#pos}
|
209
|
+
# {#push}({#out}'s {IO#pos})
|
210
|
+
#
|
211
|
+
# @return [void]
|
212
|
+
def push_pos
|
213
|
+
@stack.push(@out.pos)
|
214
|
+
@pc += 1
|
215
|
+
end
|
216
|
+
|
217
|
+
# {#push}({#out}'s {IO#pos}, {#pc} as {RescuePoint})
|
181
218
|
#
|
182
219
|
# @param [Integer, nil] pc if specified then it is pushed instead of {#pc}.
|
183
220
|
# @return [void]
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gen-text
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.7
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2016-
|
12
|
+
date: 2016-07-09 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: parse-framework
|