waxeye 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (4) hide show
  1. data/LICENSE +21 -0
  2. data/README +116 -0
  3. data/lib/waxeye.rb +328 -0
  4. metadata +55 -0
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ Waxeye Parser Generator
2
+ www.waxeye.org
3
+ Copyright (C) 2008 Orlando D. A. R. Hill
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
6
+ this software and associated documentation files (the "Software"), to deal in
7
+ the Software without restriction, including without limitation the rights to
8
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
9
+ of the Software, and to permit persons to whom the Software is furnished to do
10
+ so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README ADDED
@@ -0,0 +1,116 @@
1
+
2
+ ============================================
3
+ | Waxeye Parser Generator |
4
+ | v 0.4.0 |
5
+ | www.waxeye.org |
6
+ | Copyright (C) 2008 Orlando D. A. R. Hill |
7
+ ============================================
8
+
9
+
10
+ What is Waxeye?
11
+ ===============
12
+
13
+ Waxeye makes language development easy and fun. With Waxeye, you can rapidly
14
+ explore ideas for the syntax of your language.
15
+
16
+ Whether you are creating a full programming language, a domain-specific
17
+ language or just a simple data format, Waxeye will get you there faster.
18
+
19
+
20
+ Features
21
+ ========
22
+
23
+ * Scanner-less Parsing
24
+
25
+ * Language Independent, Reusable Grammars
26
+
27
+ * Modular, Composable Grammars
28
+
29
+ * Grammar Testing
30
+
31
+ * Automatic AST Generation
32
+
33
+ * Choice of Programming Language
34
+ - Java
35
+ - Ruby
36
+ - Scheme
37
+
38
+
39
+ User Manual
40
+ ===========
41
+
42
+ Waxeye's user manual is in 'docs/manual.html' and 'docs/manual.pdf'.
43
+ The latest version is also online at http://waxeye.org/manual.html.
44
+
45
+
46
+ Installation
47
+ ============
48
+
49
+ Unix, OSX:
50
+ 1. Extract the files of the distribution.
51
+
52
+ 2. Copy the 'waxeye' directory to where you wish to install it.
53
+
54
+ 3. Add the 'bin/waxeye' binary to your search path. e.g. If you have '~/bin' in
55
+ your PATH and installed waxeye to '/usr/local/waxeye' then you might do the
56
+ following. ln -s /usr/local/waxeye/bin/waxeye ~/bin/
57
+
58
+
59
+ Windows:
60
+ 1. Extract the files of the distribution.
61
+
62
+ 2. Copy the 'waxeye' directory to where you wish to install it.
63
+
64
+
65
+ Building
66
+ ========
67
+
68
+ 1. Install MzScheme v372; either with DrScheme or alone.
69
+ http://download.plt-scheme.org
70
+
71
+ 2. Install Waxeye's backend for PLT Scheme.
72
+ Unix, OSX:
73
+ sudo ln -s /usr/local/waxeye/src/scheme/waxeye /usr/local/plt/lib/plt/collects/
74
+
75
+ Windows:
76
+ Copy the dir 'src/scheme/waxeye' into your PLT-Scheme collections directory.
77
+
78
+ 3. Build Waxeye
79
+ Unix, OSX:
80
+ ./build/unix
81
+
82
+ Windows:
83
+ TODO: Translate 'build/unix' to a Windows equivalent.
84
+
85
+
86
+ Running
87
+ =======
88
+
89
+ Unix, OSX:
90
+ Use 'waxeye'.
91
+
92
+ Windows:
93
+ Use a command prompt to run `waxeye.exe`.
94
+
95
+
96
+ License
97
+ =======
98
+
99
+ MIT/X11 - All files (except the user manual) are under the permissive MIT/X11
100
+ license.
101
+
102
+ GNU FDL - Waxeye's user manual is under the GNU Free Documentation License.
103
+ This includes all files in the 'doc/book' directory, 'doc/manual.html' and
104
+ 'doc/manual.pdf'.
105
+
106
+
107
+ Support
108
+ =======
109
+
110
+ Feel free to contact me, if you are having trouble or want to give feedback.
111
+
112
+ Either email me directly:
113
+ orlandodarhill at Gmail.com
114
+
115
+ Or signup and post on the mailing list:
116
+ https://lists.sourceforge.net/lists/listinfo/waxeye-users
data/lib/waxeye.rb ADDED
@@ -0,0 +1,328 @@
1
+ # Waxeye Parser Generator
2
+ # www.waxeye.org
3
+ # Copyright (C) 2008 Orlando D. A. R. Hill
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy of
6
+ # this software and associated documentation files (the "Software"), to deal in
7
+ # the Software without restriction, including without limitation the rights to
8
+ # use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
9
+ # of the Software, and to permit persons to whom the Software is furnished to do
10
+ # so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in all
13
+ # copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ # SOFTWARE.
22
+
23
+
24
+ module Waxeye
25
+
26
+ class Edge
27
+ attr_reader :trans, :state, :voided
28
+ def initialize(trans, state, voided)
29
+ @trans = trans
30
+ @state = state
31
+ @voided = voided
32
+ end
33
+ end
34
+
35
+ class State
36
+ attr_reader :edges, :match
37
+ def initialize(edges, match)
38
+ @edges = edges
39
+ @match = match
40
+ end
41
+ end
42
+
43
+ class Automaton
44
+ attr_reader :type, :states, :voided
45
+ def initialize(type, states, voided)
46
+ @type = type
47
+ @states = states
48
+ @voided = voided
49
+ end
50
+ end
51
+
52
+ class ParseError
53
+ attr_reader :pos, :line, :col
54
+ def initialize(pos, line, col)
55
+ @pos = pos
56
+ @line = line
57
+ @col = col
58
+ end
59
+
60
+ def display()
61
+ print "parse error at pos=#{pos}, line=#{line}, col=#{col}\n"
62
+ end
63
+ end
64
+
65
+ class AST
66
+ attr_reader :type, :children, :pos
67
+ def initialize(type, children, pos)
68
+ @type = type
69
+ @children = children
70
+ @pos = pos
71
+ end
72
+
73
+ def display_sexpr()
74
+ display_sexpr_iter(self)
75
+ print "\n"
76
+ end
77
+
78
+ def display()
79
+ display_iter(self, [0])
80
+ end
81
+
82
+ private
83
+ def display_sexpr_iter(ast)
84
+ print '('
85
+ print ast.type
86
+ ast.children.each do |a|
87
+ print " "
88
+ if a.is_a?(Waxeye::AST)
89
+ display_sexpr_iter(a)
90
+ else
91
+ print a
92
+ end
93
+ end
94
+ print ')'
95
+ end
96
+
97
+ def display_iter(ast, indent)
98
+ (indent[0] - 1).times {|| print ' ' }
99
+ print '-> ' if indent[0] > 0
100
+ print ast.type, "\n"
101
+ indent[0] = indent[0] + 1
102
+ ast.children.each do |a|
103
+ if a.is_a?(Waxeye::AST)
104
+ display_iter(a, indent)
105
+ else
106
+ (indent[0] - 1).times {|| print ' ' }
107
+ print '| ' if indent[0] > 0
108
+ print a, "\n"
109
+ end
110
+ end
111
+ indent[0] = indent[0] - 1
112
+ end
113
+ end
114
+
115
+ class WaxeyeParser
116
+ def initialize(start, eof_check, line_counting, tab_width, automata)
117
+ @start = start
118
+ @eof_check = eof_check
119
+ @line_counting = line_counting
120
+ @tab_width = tab_width
121
+ @automata = automata
122
+ end
123
+
124
+ def parse(input)
125
+ InnerParser.new(@start, @eof_check, @line_counting, @tab_width, @automata, input).parse()
126
+ end
127
+
128
+ class InnerParser
129
+ def initialize(start, eof_check, line_counting, tab_width, automata, input)
130
+ @start = start
131
+ @eof_check = eof_check
132
+ @line_counting = line_counting
133
+ @tab_width = tab_width
134
+ @automata = automata
135
+ @states_stack = []
136
+ @cache = {}
137
+ @input = input
138
+ @input_len = input.length
139
+ @input_pos = 0
140
+ @line = 0
141
+ @column = 0
142
+ @last_cr = false
143
+ @error_pos = 0
144
+ @error_line = 0
145
+ @error_col = 0
146
+ end
147
+
148
+ def parse()
149
+ eof_check(match_automaton(@start))
150
+ end
151
+
152
+ private
153
+
154
+ def match_automaton(index)
155
+ start_pos = @input_pos
156
+ key = [index, start_pos]
157
+
158
+ if (@cache.has_key?(key))
159
+ cachedItem = @cache.fetch(key)
160
+ restore_pos(cachedItem[1], cachedItem[2], cachedItem[3], cachedItem[4])
161
+ return cachedItem[0]
162
+ end
163
+
164
+ start_line = @line
165
+ start_col = @column
166
+ start_cr = @last_cr
167
+ automaton = @automata[index]
168
+ type = automaton.type
169
+ states = automaton.states
170
+ voided = automaton.voided
171
+
172
+ @states_stack.push(states)
173
+ res = match_state(0)
174
+ @states_stack.pop()
175
+
176
+ value = if type == :_and
177
+ restore_pos(start_pos, start_line, start_col, start_cr)
178
+ not not res
179
+ elsif type == :_not
180
+ restore_pos(start_pos, start_line, start_col, start_cr)
181
+ if res
182
+ update_error()
183
+ false
184
+ else
185
+ true
186
+ end
187
+ else
188
+ if res
189
+ (voided ? true : AST.new(type, res, :pos))
190
+ else
191
+ update_error()
192
+ false
193
+ end
194
+ end
195
+
196
+ @cache.store(key, [value, @input_pos, @line, @column, @last_cr])
197
+ return value
198
+ end
199
+
200
+ def match_state(index)
201
+ state = @states_stack.last[index]
202
+ res = match_edges(state.edges)
203
+ res ? res : (state.match and [])
204
+ end
205
+
206
+ def match_edges(edges)
207
+ if edges == []
208
+ false
209
+ else
210
+ res = match_edge(edges[0])
211
+ res ? res : match_edges(edges[1..-1])
212
+ end
213
+ end
214
+
215
+ def match_edge(edge)
216
+ start_pos = @input_pos
217
+ start_line = @line
218
+ start_col = @column
219
+ start_cr = @last_cr
220
+ t = edge.trans
221
+ res = if t == :_wild
222
+ @input_pos < @input_len ? mv() : (update_error(); false)
223
+ elsif t.is_a?(String)
224
+ @input_pos < @input_len and t[0] == @input[@input_pos] ? mv() : (update_error(); false)
225
+ elsif t.is_a?(Array)
226
+ @input_pos < @input_len and within_set?(t, @input[@input_pos]) ? mv() : (update_error(); false)
227
+ elsif t.is_a?(Integer)
228
+ match_automaton(t)
229
+ else
230
+ false
231
+ end
232
+
233
+ if res
234
+ tran_res = match_state(edge.state)
235
+ if tran_res
236
+ if edge.voided or res == true
237
+ tran_res
238
+ else
239
+ [res] + tran_res
240
+ end
241
+ else
242
+ restore_pos(start_pos, start_line, start_col, start_cr)
243
+ false
244
+ end
245
+ else
246
+ false
247
+ end
248
+ end
249
+
250
+ def restore_pos(pos, line, col, cr)
251
+ @input_pos = pos
252
+ @line = line
253
+ @column = col
254
+ @last_cr = cr
255
+ end
256
+
257
+ def update_error()
258
+ if @error_pos < @input_pos
259
+ @error_pos = @input_pos
260
+ @error_line = @line
261
+ @error_col = @column
262
+ end
263
+ end
264
+
265
+ def mv()
266
+ ch = @input[@input_pos].chr()
267
+ @input_pos = @input_pos + 1
268
+
269
+ if ch == '\r'
270
+ @line = @line + 1
271
+ @column = 0
272
+ @last_cr = true
273
+ else
274
+ if ch == '\n'
275
+ if not @last_cr
276
+ @line = @line + 1
277
+ @column = 0
278
+ end
279
+ else
280
+ @column = @column + 1
281
+ end
282
+ @last_cr = false
283
+ end
284
+
285
+ return ch
286
+ end
287
+
288
+ def eof_check(res)
289
+ if res
290
+ if @eof_check and @input_pos < @input_len
291
+ # Create a parse error - Not all input consumed
292
+ ParseError.new(@error_pos, @error_line, @error_col)
293
+ else
294
+ res
295
+ end
296
+ else
297
+ # Create a parse error
298
+ ParseError.new(@error_pos, @error_line, @error_col)
299
+ end
300
+ end
301
+
302
+ def within_set?(set, c)
303
+ if set == []
304
+ false
305
+ else
306
+ aa = set[0]
307
+
308
+ if aa.is_a?(String)
309
+ if aa[0] == c
310
+ true
311
+ else
312
+ aa[0] < c ? within_set?(set[1..-1], c) : false
313
+ end
314
+ else
315
+ # If not a String then must be a range
316
+ if aa.include?(c)
317
+ true
318
+ else
319
+ aa.max < c ? within_set?(set[1..-1], c) : false
320
+ end
321
+ end
322
+ end
323
+ end
324
+ end
325
+
326
+ end
327
+
328
+ end
metadata ADDED
@@ -0,0 +1,55 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: waxeye
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.4.0
5
+ platform: ruby
6
+ authors:
7
+ - Orlando D. A. R. Hill
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2008-08-07 00:00:00 +02:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description:
17
+ email: orlandodarhill Gmail.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files: []
23
+
24
+ files:
25
+ - README
26
+ - LICENSE
27
+ - lib/waxeye.rb
28
+ has_rdoc: false
29
+ homepage: http://waxeye.org
30
+ post_install_message:
31
+ rdoc_options: []
32
+
33
+ require_paths:
34
+ - lib
35
+ required_ruby_version: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: "0"
40
+ version:
41
+ required_rubygems_version: !ruby/object:Gem::Requirement
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ version: "0"
46
+ version:
47
+ requirements: []
48
+
49
+ rubyforge_project:
50
+ rubygems_version: 1.1.1
51
+ signing_key:
52
+ specification_version: 2
53
+ summary: The Ruby runtime for Waxeye parsers
54
+ test_files: []
55
+