racc 1.4.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (109) hide show
  1. data/.gitattributes +2 -0
  2. data/.gitignore +7 -0
  3. data/COPYING +515 -0
  4. data/ChangeLog +846 -0
  5. data/DEPENDS +4 -0
  6. data/README.en.rdoc +86 -0
  7. data/README.ja.rdoc +96 -0
  8. data/Rakefile +15 -0
  9. data/TODO +5 -0
  10. data/bin/racc +308 -0
  11. data/bin/racc2y +195 -0
  12. data/bin/y2racc +339 -0
  13. data/doc/en/NEWS.en.rdoc +282 -0
  14. data/doc/en/command.en.html +78 -0
  15. data/doc/en/debug.en.rdoc +20 -0
  16. data/doc/en/grammar.en.rdoc +230 -0
  17. data/doc/en/index.en.html +10 -0
  18. data/doc/en/parser.en.rdoc +74 -0
  19. data/doc/en/usage.en.html +92 -0
  20. data/doc/ja/NEWS.ja.rdoc +307 -0
  21. data/doc/ja/command.ja.html +94 -0
  22. data/doc/ja/debug.ja.rdoc +36 -0
  23. data/doc/ja/grammar.ja.rdoc +348 -0
  24. data/doc/ja/index.ja.html +10 -0
  25. data/doc/ja/parser.ja.rdoc +125 -0
  26. data/doc/ja/usage.ja.html +414 -0
  27. data/ext/racc/cparse/MANIFEST +4 -0
  28. data/ext/racc/cparse/cparse.c +824 -0
  29. data/ext/racc/cparse/depend +1 -0
  30. data/ext/racc/cparse/extconf.rb +7 -0
  31. data/fastcache/extconf.rb +2 -0
  32. data/fastcache/fastcache.c +185 -0
  33. data/lib/racc.rb +6 -0
  34. data/lib/racc/compat.rb +40 -0
  35. data/lib/racc/debugflags.rb +59 -0
  36. data/lib/racc/exception.rb +15 -0
  37. data/lib/racc/grammar.rb +1115 -0
  38. data/lib/racc/grammarfileparser.rb +559 -0
  39. data/lib/racc/info.rb +16 -0
  40. data/lib/racc/iset.rb +91 -0
  41. data/lib/racc/logfilegenerator.rb +214 -0
  42. data/lib/racc/parser.rb +439 -0
  43. data/lib/racc/parserfilegenerator.rb +511 -0
  44. data/lib/racc/pre-setup +13 -0
  45. data/lib/racc/sourcetext.rb +34 -0
  46. data/lib/racc/state.rb +971 -0
  47. data/lib/racc/statetransitiontable.rb +316 -0
  48. data/lib/racc/static.rb +5 -0
  49. data/misc/dist.sh +31 -0
  50. data/sample/array.y +67 -0
  51. data/sample/array2.y +59 -0
  52. data/sample/calc-ja.y +66 -0
  53. data/sample/calc.y +65 -0
  54. data/sample/conflict.y +15 -0
  55. data/sample/hash.y +60 -0
  56. data/sample/lalr.y +17 -0
  57. data/sample/lists.y +57 -0
  58. data/sample/syntax.y +46 -0
  59. data/sample/yyerr.y +46 -0
  60. data/setup.rb +1587 -0
  61. data/tasks/doc.rb +12 -0
  62. data/tasks/email.rb +55 -0
  63. data/tasks/file.rb +37 -0
  64. data/tasks/gem.rb +37 -0
  65. data/tasks/test.rb +16 -0
  66. data/test/assets/chk.y +126 -0
  67. data/test/assets/conf.y +16 -0
  68. data/test/assets/digraph.y +29 -0
  69. data/test/assets/echk.y +118 -0
  70. data/test/assets/err.y +60 -0
  71. data/test/assets/expect.y +7 -0
  72. data/test/assets/firstline.y +4 -0
  73. data/test/assets/ichk.y +102 -0
  74. data/test/assets/intp.y +546 -0
  75. data/test/assets/mailp.y +437 -0
  76. data/test/assets/newsyn.y +25 -0
  77. data/test/assets/noend.y +4 -0
  78. data/test/assets/nonass.y +41 -0
  79. data/test/assets/normal.y +27 -0
  80. data/test/assets/norule.y +4 -0
  81. data/test/assets/nullbug1.y +25 -0
  82. data/test/assets/nullbug2.y +15 -0
  83. data/test/assets/opt.y +123 -0
  84. data/test/assets/percent.y +35 -0
  85. data/test/assets/recv.y +97 -0
  86. data/test/assets/rrconf.y +14 -0
  87. data/test/assets/scan.y +72 -0
  88. data/test/assets/syntax.y +50 -0
  89. data/test/assets/unterm.y +5 -0
  90. data/test/assets/useless.y +12 -0
  91. data/test/assets/yyerr.y +46 -0
  92. data/test/bench.y +36 -0
  93. data/test/helper.rb +88 -0
  94. data/test/infini.y +8 -0
  95. data/test/scandata/brace +7 -0
  96. data/test/scandata/gvar +1 -0
  97. data/test/scandata/normal +4 -0
  98. data/test/scandata/percent +18 -0
  99. data/test/scandata/slash +10 -0
  100. data/test/src.intp +34 -0
  101. data/test/start.y +20 -0
  102. data/test/test_chk_y.rb +51 -0
  103. data/test/test_grammar_file_parser.rb +15 -0
  104. data/test/test_racc_command.rb +155 -0
  105. data/test/test_scan_y.rb +51 -0
  106. data/test/testscanner.rb +51 -0
  107. data/web/racc.en.rhtml +42 -0
  108. data/web/racc.ja.rhtml +51 -0
  109. metadata +166 -0
@@ -0,0 +1,60 @@
1
+
2
+ class ErrTestp
3
+
4
+ rule
5
+
6
+ target: lines
7
+ ;
8
+
9
+ lines: line
10
+ | lines line
11
+ ;
12
+
13
+ line: A B C D E
14
+ | error E
15
+ ;
16
+
17
+ end
18
+
19
+ ---- inner
20
+
21
+ def initialize
22
+ @yydebug = false
23
+ @q = [
24
+ [:A, 'a'],
25
+ # [:B, 'b'],
26
+ [:C, 'c'],
27
+ [:D, 'd'],
28
+ [:E, 'e'],
29
+
30
+ [:A, 'a'],
31
+ [:B, 'b'],
32
+ [:C, 'c'],
33
+ [:D, 'd'],
34
+ [:E, 'e'],
35
+
36
+ [:A, 'a'],
37
+ [:B, 'b'],
38
+ # [:C, 'c'],
39
+ [:D, 'd'],
40
+ [:E, 'e'],
41
+ [false, nil]
42
+ ]
43
+ end
44
+
45
+ def next_token
46
+ @q.shift
47
+ end
48
+
49
+ def on_error( t, val, values )
50
+ $stderr.puts "error on token '#{val}'(#{t})"
51
+ end
52
+
53
+ def parse
54
+ do_parse
55
+ end
56
+
57
+ ---- footer
58
+
59
+ p = ErrTestp.new
60
+ p.parse
@@ -0,0 +1,7 @@
1
+ class E
2
+ expect 1
3
+ rule
4
+ list: inlist inlist
5
+ inlist:
6
+ | A
7
+ end
@@ -0,0 +1,4 @@
1
+ class T
2
+ rule
3
+ a: A B C
4
+ end
@@ -0,0 +1,102 @@
1
+ class Calculator
2
+
3
+ prechigh
4
+ left '*' '/'
5
+ left '+' '-'
6
+ preclow
7
+
8
+ convert
9
+ NUMBER 'Number'
10
+ end
11
+
12
+ rule
13
+
14
+ target : exp
15
+ | /* none */ { result = 0 }
16
+
17
+ exp : exp '+' exp { result += val[2]; a = 'plus' }
18
+ | exp '-' exp { result -= val[2]; a = "string test" }
19
+ | exp '*' exp { result *= val[2] }
20
+ | exp '/' exp { result /= val[2] }
21
+ | '(' { $emb = true } exp ')'
22
+ {
23
+ raise 'must not happen' unless $emb
24
+ result = val[2]
25
+ }
26
+ | '-' NUMBER { result = -val[1] }
27
+ | NUMBER
28
+
29
+ ----header
30
+
31
+ class Number
32
+ end
33
+
34
+ ----inner
35
+
36
+ def initialize
37
+ @racc_debug_out = $stdout
38
+ @yydebug = false
39
+ end
40
+
41
+ def validate(expected, src)
42
+ result = parse(src)
43
+ unless result == expected
44
+ raise "test #{@test_number} fail"
45
+ end
46
+ @test_number += 1
47
+ end
48
+
49
+ def parse(src)
50
+ @src = src
51
+ @test_number = 1
52
+ yyparse self, :scan
53
+ end
54
+
55
+ def scan(&block)
56
+ @src.each(&block)
57
+ end
58
+
59
+ ----footer
60
+
61
+ calc = Calculator.new
62
+
63
+ calc.validate(9, [[Number, 9], nil])
64
+
65
+ calc.validate(-3,
66
+ [[Number, 5],
67
+ ['*', '*'],
68
+ [Number, 1],
69
+ ['-', '*'],
70
+ [Number, 1],
71
+ ['*', '*'],
72
+ [Number, 8],
73
+ nil])
74
+
75
+ calc.validate(-1,
76
+ [[Number, 5],
77
+ ['+', '+'],
78
+ [Number, 2],
79
+ ['-', '-'],
80
+ [Number, 5],
81
+ ['+', '+'],
82
+ [Number, 2],
83
+ ['-', '-'],
84
+ [Number, 5],
85
+ nil])
86
+
87
+ calc.validate(-4,
88
+ [['-', 'UMINUS'],
89
+ [Number, 4],
90
+ nil])
91
+
92
+ calc.validate(40,
93
+ [[Number, 7],
94
+ ['*', '*'],
95
+ ['(', '('],
96
+ [Number, 4],
97
+ ['+', '+'],
98
+ [Number, 3],
99
+ [')', ')'],
100
+ ['-', '-'],
101
+ [Number, 9],
102
+ nil])
@@ -0,0 +1,546 @@
1
+ #
2
+ # intp
3
+ #
4
+
5
+ class Intp::Parser
6
+
7
+ prechigh
8
+ nonassoc UMINUS
9
+ left '*' '/'
10
+ left '+' '-'
11
+ nonassoc EQ
12
+ preclow
13
+
14
+ rule
15
+
16
+ program : stmt_list
17
+ {
18
+ result = RootNode.new( val[0] )
19
+ }
20
+
21
+ stmt_list :
22
+ {
23
+ result = []
24
+ }
25
+ | stmt_list stmt EOL
26
+ {
27
+ result.push val[1]
28
+ }
29
+ | stmt_list EOL
30
+
31
+ stmt : expr
32
+ | assign
33
+ | IDENT realprim
34
+ {
35
+ result = FuncallNode.new( @fname, val[0][0],
36
+ val[0][1], [val[1]] )
37
+ }
38
+ | if_stmt
39
+ | while_stmt
40
+ | defun
41
+
42
+ if_stmt : IF stmt THEN EOL stmt_list else_stmt END
43
+ {
44
+ result = IfNode.new( @fname, val[0][0],
45
+ val[1], val[4], val[5] )
46
+ }
47
+
48
+ else_stmt : ELSE EOL stmt_list
49
+ {
50
+ result = val[2]
51
+ }
52
+ |
53
+ {
54
+ result = nil
55
+ }
56
+
57
+ while_stmt: WHILE stmt DO EOL stmt_list END
58
+ {
59
+ result = WhileNode.new(@fname, val[0][0],
60
+ val[1], val[4])
61
+ }
62
+
63
+ defun : DEF IDENT param EOL stmt_list END
64
+ {
65
+ result = DefNode.new(@fname, val[0][0], val[1][1],
66
+ Function.new(@fname, val[0][0], val[2], val[4]))
67
+ }
68
+
69
+ param : '(' name_list ')'
70
+ {
71
+ result = val[1]
72
+ }
73
+ | '(' ')'
74
+ {
75
+ result = []
76
+ }
77
+ |
78
+ {
79
+ result = []
80
+ }
81
+
82
+ name_list : IDENT
83
+ {
84
+ result = [ val[0][1] ]
85
+ }
86
+ | name_list ',' IDENT
87
+ {
88
+ result.push val[2][1]
89
+ }
90
+
91
+ assign : IDENT '=' expr
92
+ {
93
+ result = AssignNode.new(@fname, val[0][0], val[0][1], val[2])
94
+ }
95
+
96
+ expr : expr '+' expr
97
+ {
98
+ result = FuncallNode.new(@fname, val[0].lineno, '+', [val[0], val[2]])
99
+ }
100
+ | expr '-' expr
101
+ {
102
+ result = FuncallNode.new(@fname, val[0].lineno, '-', [val[0], val[2]])
103
+ }
104
+ | expr '*' expr
105
+ {
106
+ result = FuncallNode.new(@fname, val[0].lineno, '*', [val[0], val[2]])
107
+ }
108
+ | expr '/' expr
109
+ {
110
+ result = FuncallNode.new(@fname, val[0].lineno,
111
+ '/', [val[0], val[2]])
112
+ }
113
+ | expr EQ expr
114
+ {
115
+ result = FuncallNode.new(@fname, val[0].lineno, '==', [val[0], val[2]])
116
+ }
117
+ | primary
118
+
119
+ primary : realprim
120
+ | '(' expr ')'
121
+ {
122
+ result = val[1]
123
+ }
124
+ | '-' expr =UMINUS
125
+ {
126
+ result = FuncallNode.new(@fname, val[0][0], '-@', [val[1]])
127
+ }
128
+
129
+ realprim : IDENT
130
+ {
131
+ result = VarRefNode.new(@fname, val[0][0],
132
+ val[0][1])
133
+ }
134
+ | NUMBER
135
+ {
136
+ result = LiteralNode.new(@fname, *val[0])
137
+ }
138
+ | STRING
139
+ {
140
+ result = StringNode.new(@fname, *val[0])
141
+ }
142
+ | TRUE
143
+ {
144
+ result = LiteralNode.new(@fname, *val[0])
145
+ }
146
+ | FALSE
147
+ {
148
+ result = LiteralNode.new(@fname, *val[0])
149
+ }
150
+ | NIL
151
+ {
152
+ result = LiteralNode.new(@fname, *val[0])
153
+ }
154
+ | funcall
155
+
156
+ funcall : IDENT '(' args ')'
157
+ {
158
+ result = FuncallNode.new(@fname, val[0][0], val[0][1], val[2])
159
+ }
160
+ | IDENT '(' ')'
161
+ {
162
+ result = FuncallNode.new(@fname, val[0][0], val[0][1], [])
163
+ }
164
+
165
+ args : expr
166
+ {
167
+ result = val
168
+ }
169
+ | args ',' expr
170
+ {
171
+ result.push val[2]
172
+ }
173
+
174
+ end
175
+
176
+ ---- header
177
+ #
178
+ # intp/parser.rb
179
+ #
180
+
181
+ ---- inner
182
+
183
+ def initialize
184
+ @scope = {}
185
+ end
186
+
187
+ RESERVED = {
188
+ 'if' => :IF,
189
+ 'else' => :ELSE,
190
+ 'while' => :WHILE,
191
+ 'then' => :THEN,
192
+ 'do' => :DO,
193
+ 'def' => :DEF,
194
+ 'true' => :TRUE,
195
+ 'false' => :FALSE,
196
+ 'nil' => :NIL,
197
+ 'end' => :END
198
+ }
199
+
200
+ RESERVED_V = {
201
+ 'true' => true,
202
+ 'false' => false,
203
+ 'nil' => nil
204
+ }
205
+
206
+ def parse(f, fname)
207
+ @q = []
208
+ @fname = fname
209
+ lineno = 1
210
+ f.each do |line|
211
+ line.strip!
212
+ until line.empty?
213
+ case line
214
+ when /\A\s+/, /\A\#.*/
215
+ ;
216
+ when /\A[a-zA-Z_]\w*/
217
+ word = $&
218
+ @q.push [(RESERVED[word] || :IDENT),
219
+ [lineno, RESERVED_V.key?(word) ? RESERVED_V[word] : word.intern]]
220
+ when /\A\d+/
221
+ @q.push [:NUMBER, [lineno, $&.to_i]]
222
+ when /\A"(?:[^"\\]+|\\.)*"/, /\A'(?:[^'\\]+|\\.)*'/
223
+ @q.push [:STRING, [lineno, eval($&)]]
224
+ when /\A==/
225
+ @q.push [:EQ, [lineno, '==']]
226
+ when /\A./
227
+ @q.push [$&, [lineno, $&]]
228
+ else
229
+ raise RuntimeError, 'must not happen'
230
+ end
231
+ line = $'
232
+ end
233
+ @q.push [:EOL, [lineno, nil]]
234
+ lineno += 1
235
+ end
236
+ @q.push [false, '$']
237
+ do_parse
238
+ end
239
+
240
+ def next_token
241
+ @q.shift
242
+ end
243
+
244
+ def on_error(t, v, values)
245
+ if v
246
+ line = v[0]
247
+ v = v[1]
248
+ else
249
+ line = 'last'
250
+ end
251
+ raise Racc::ParseError, "#{@fname}:#{line}: syntax error on #{v.inspect}"
252
+ end
253
+
254
+ ---- footer
255
+ # intp/node.rb
256
+
257
+ module Intp
258
+
259
+ class IntpError < StandardError; end
260
+ class IntpArgumentError < IntpError; end
261
+
262
+ class Core
263
+
264
+ def initialize
265
+ @ftab = {}
266
+ @obj = Object.new
267
+ @stack = []
268
+ @stack.push Frame.new '(toplevel)'
269
+ end
270
+
271
+ def frame
272
+ @stack[-1]
273
+ end
274
+
275
+ def define_function(fname, node)
276
+ raise IntpError, "function #{fname} defined twice" if @ftab.key?(fname)
277
+ @ftab[fname] = node
278
+ end
279
+
280
+ def call_function_or(fname, args)
281
+ call_intp_function_or(fname, args) {
282
+ call_ruby_toplevel_or(fname, args) {
283
+ yield
284
+ }
285
+ }
286
+ end
287
+
288
+ def call_intp_function_or(fname, args)
289
+ if func = @ftab[fname]
290
+ frame = Frame.new(fname)
291
+ @stack.push frame
292
+ func.call self, frame, args
293
+ @stack.pop
294
+ else
295
+ yield
296
+ end
297
+ end
298
+
299
+ def call_ruby_toplevel_or(fname, args)
300
+ if @obj.respond_to? fname, true
301
+ @obj.send fname, *args
302
+ else
303
+ yield
304
+ end
305
+ end
306
+
307
+ end
308
+
309
+ class Frame
310
+
311
+ def initialize(fname)
312
+ @fname = fname
313
+ @lvars = {}
314
+ end
315
+
316
+ attr :fname
317
+
318
+ def lvar?(name)
319
+ @lvars.key? name
320
+ end
321
+
322
+ def [](key)
323
+ @lvars[key]
324
+ end
325
+
326
+ def []=(key, val)
327
+ @lvars[key] = val
328
+ end
329
+
330
+ end
331
+
332
+
333
+ class Node
334
+
335
+ def initialize(fname, lineno)
336
+ @filename = fname
337
+ @lineno = lineno
338
+ end
339
+
340
+ attr_reader :filename
341
+ attr_reader :lineno
342
+
343
+ def exec_list(intp, nodes)
344
+ v = nil
345
+ nodes.each {|i| v = i.evaluate(intp) }
346
+ v
347
+ end
348
+
349
+ def intp_error!(msg)
350
+ raise IntpError, "in #{filename}:#{lineno}: #{msg}"
351
+ end
352
+
353
+ def inspect
354
+ "#{self.class.name}/#{lineno}"
355
+ end
356
+
357
+ end
358
+
359
+
360
+ class RootNode < Node
361
+
362
+ def initialize(tree)
363
+ super nil, nil
364
+ @tree = tree
365
+ end
366
+
367
+ def evaluate
368
+ exec_list Core.new, @tree
369
+ end
370
+
371
+ end
372
+
373
+
374
+ class DefNode < Node
375
+
376
+ def initialize(file, lineno, fname, func)
377
+ super file, lineno
378
+ @funcname = fname
379
+ @funcobj = func
380
+ end
381
+
382
+ def evaluate(intp)
383
+ intp.define_function @funcname, @funcobj
384
+ end
385
+
386
+ end
387
+
388
+ class FuncallNode < Node
389
+
390
+ def initialize(file, lineno, func, args)
391
+ super file, lineno
392
+ @funcname = func
393
+ @args = args
394
+ end
395
+
396
+ def evaluate(intp)
397
+ args = @args.map {|i| i.evaluate intp }
398
+ begin
399
+ intp.call_intp_function_or(@funcname, args) {
400
+ if args.empty? or not args[0].respond_to?(@funcname)
401
+ intp.call_ruby_toplevel_or(@funcname, args) {
402
+ intp_error! "undefined function #{@funcname.id2name}"
403
+ }
404
+ else
405
+ recv = args.shift
406
+ recv.send @funcname, *args
407
+ end
408
+ }
409
+ rescue IntpArgumentError, ArgumentError
410
+ intp_error! $!.message
411
+ end
412
+ end
413
+
414
+ end
415
+
416
+ class Function < Node
417
+
418
+ def initialize(file, lineno, params, body)
419
+ super file, lineno
420
+ @params = params
421
+ @body = body
422
+ end
423
+
424
+ def call(intp, frame, args)
425
+ unless args.size == @params.size
426
+ raise IntpArgumentError,
427
+ "wrong # of arg for #{frame.fname}() (#{args.size} for #{@params.size})"
428
+ end
429
+ args.each_with_index do |v,i|
430
+ frame[@params[i]] = v
431
+ end
432
+ exec_list intp, @body
433
+ end
434
+
435
+ end
436
+
437
+
438
+ class IfNode < Node
439
+
440
+ def initialize(fname, lineno, cond, tstmt, fstmt)
441
+ super fname, lineno
442
+ @condition = cond
443
+ @tstmt = tstmt
444
+ @fstmt = fstmt
445
+ end
446
+
447
+ def evaluate(intp)
448
+ if @condition.evaluate(intp)
449
+ exec_list intp, @tstmt
450
+ else
451
+ exec_list intp, @fstmt if @fstmt
452
+ end
453
+ end
454
+
455
+ end
456
+
457
+ class WhileNode < Node
458
+
459
+ def initialize(fname, lineno, cond, body)
460
+ super fname, lineno
461
+ @condition = cond
462
+ @body = body
463
+ end
464
+
465
+ def evaluate(intp)
466
+ while @condition.evaluate(intp)
467
+ exec_list intp, @body
468
+ end
469
+ end
470
+
471
+ end
472
+
473
+
474
+ class AssignNode < Node
475
+
476
+ def initialize(fname, lineno, vname, val)
477
+ super fname, lineno
478
+ @vname = vname
479
+ @val = val
480
+ end
481
+
482
+ def evaluate(intp)
483
+ intp.frame[@vname] = @val.evaluate(intp)
484
+ end
485
+
486
+ end
487
+
488
+ class VarRefNode < Node
489
+
490
+ def initialize(fname, lineno, vname)
491
+ super fname, lineno
492
+ @vname = vname
493
+ end
494
+
495
+ def evaluate(intp)
496
+ if intp.frame.lvar?(@vname)
497
+ intp.frame[@vname]
498
+ else
499
+ intp.call_function_or(@vname, []) {
500
+ intp_error! "unknown method or local variable #{@vname.id2name}"
501
+ }
502
+ end
503
+ end
504
+
505
+ end
506
+
507
+ class StringNode < Node
508
+
509
+ def initialize(fname, lineno, str)
510
+ super fname, lineno
511
+ @val = str
512
+ end
513
+
514
+ def evaluate(intp)
515
+ @val.dup
516
+ end
517
+
518
+ end
519
+
520
+ class LiteralNode < Node
521
+
522
+ def initialize(fname, lineno, val)
523
+ super fname, lineno
524
+ @val = val
525
+ end
526
+
527
+ def evaluate(intp)
528
+ @val
529
+ end
530
+
531
+ end
532
+
533
+ end # module Intp
534
+
535
+ begin
536
+ tree = nil
537
+ fname = 'src.intp'
538
+ File.open(fname) {|f|
539
+ tree = Intp::Parser.new.parse(f, fname)
540
+ }
541
+ tree.evaluate
542
+ rescue Racc::ParseError, Intp::IntpError, Errno::ENOENT
543
+ raise ####
544
+ $stderr.puts "#{File.basename $0}: #{$!}"
545
+ exit 1
546
+ end