ruco-cpp 0.2.1

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.
Files changed (80) hide show
  1. checksums.yaml +7 -0
  2. data/Rakefile +17 -0
  3. data/bin/console +14 -0
  4. data/bin/ruco +30 -0
  5. data/bin/setup +7 -0
  6. data/data/ruco/Parser.frame +359 -0
  7. data/data/ruco/Scanner.frame +896 -0
  8. data/data/ruco/picojson/Changes +14 -0
  9. data/data/ruco/picojson/LICENSE +25 -0
  10. data/data/ruco/picojson/Makefile +8 -0
  11. data/data/ruco/picojson/README.mkdn +183 -0
  12. data/data/ruco/picojson/examples/github-issues.cc +110 -0
  13. data/data/ruco/picojson/examples/iostream.cc +70 -0
  14. data/data/ruco/picojson/examples/streaming.cc +76 -0
  15. data/data/ruco/picojson/picojson.h +1299 -0
  16. data/ext/cocor/Action.cpp +81 -0
  17. data/ext/cocor/Action.h +59 -0
  18. data/ext/cocor/ArrayList.cpp +79 -0
  19. data/ext/cocor/ArrayList.h +52 -0
  20. data/ext/cocor/BitArray.cpp +156 -0
  21. data/ext/cocor/BitArray.h +68 -0
  22. data/ext/cocor/CharClass.cpp +42 -0
  23. data/ext/cocor/CharClass.h +48 -0
  24. data/ext/cocor/CharSet.cpp +166 -0
  25. data/ext/cocor/CharSet.h +68 -0
  26. data/ext/cocor/Coco.atg +528 -0
  27. data/ext/cocor/Coco.cpp +173 -0
  28. data/ext/cocor/Comment.cpp +45 -0
  29. data/ext/cocor/Comment.h +51 -0
  30. data/ext/cocor/Copyright.frame +27 -0
  31. data/ext/cocor/DFA.cpp +865 -0
  32. data/ext/cocor/DFA.h +132 -0
  33. data/ext/cocor/Generator.cpp +182 -0
  34. data/ext/cocor/Generator.h +61 -0
  35. data/ext/cocor/Graph.h +59 -0
  36. data/ext/cocor/HashTable.cpp +115 -0
  37. data/ext/cocor/HashTable.h +84 -0
  38. data/ext/cocor/Makefile +11 -0
  39. data/ext/cocor/Melted.cpp +39 -0
  40. data/ext/cocor/Melted.h +51 -0
  41. data/ext/cocor/Node.cpp +69 -0
  42. data/ext/cocor/Node.h +86 -0
  43. data/ext/cocor/Parser.cpp +925 -0
  44. data/ext/cocor/Parser.frame +326 -0
  45. data/ext/cocor/Parser.h +153 -0
  46. data/ext/cocor/ParserGen.cpp +486 -0
  47. data/ext/cocor/ParserGen.h +99 -0
  48. data/ext/cocor/Position.cpp +37 -0
  49. data/ext/cocor/Position.h +46 -0
  50. data/ext/cocor/README.md +12 -0
  51. data/ext/cocor/Scanner.cpp +833 -0
  52. data/ext/cocor/Scanner.frame +897 -0
  53. data/ext/cocor/Scanner.h +291 -0
  54. data/ext/cocor/Sets.h +84 -0
  55. data/ext/cocor/SortedList.cpp +141 -0
  56. data/ext/cocor/SortedList.h +68 -0
  57. data/ext/cocor/State.cpp +77 -0
  58. data/ext/cocor/State.h +55 -0
  59. data/ext/cocor/StringBuilder.cpp +88 -0
  60. data/ext/cocor/StringBuilder.h +29 -0
  61. data/ext/cocor/Symbol.cpp +61 -0
  62. data/ext/cocor/Symbol.h +70 -0
  63. data/ext/cocor/Tab.cpp +1248 -0
  64. data/ext/cocor/Tab.h +245 -0
  65. data/ext/cocor/Target.cpp +41 -0
  66. data/ext/cocor/Target.h +48 -0
  67. data/ext/cocor/build.bat +3 -0
  68. data/ext/cocor/build.sh +4 -0
  69. data/ext/cocor/coc.bat +1 -0
  70. data/ext/cocor/coc.sh +2 -0
  71. data/ext/cocor/cocor_ruby_ext.cpp +124 -0
  72. data/ext/cocor/cygBuild.bat +1 -0
  73. data/ext/cocor/extconf.rb +5 -0
  74. data/ext/cocor/mingwbuild.bat +2 -0
  75. data/ext/cocor/mkmf.log +57 -0
  76. data/ext/cocor/zipsources.bat +1 -0
  77. data/lib/cocor.rb +14 -0
  78. data/lib/ruco/version.rb +3 -0
  79. data/lib/ruco.rb +728 -0
  80. metadata +195 -0
data/lib/ruco.rb ADDED
@@ -0,0 +1,728 @@
1
+ require "ruco/version"
2
+ require 'active_support/inflector'
3
+ require 'tsort'
4
+
5
+ module Ruco
6
+
7
+ class TsortableHash < Hash
8
+ include TSort
9
+ alias tsort_each_node each_key
10
+ def tsort_each_child(node, &block)
11
+ fetch(node).each(&block)
12
+ end
13
+ end
14
+
15
+ class LitString
16
+ attr_accessor :str
17
+ def initialize(str, prodset)
18
+ @str = str
19
+ end
20
+
21
+ def generate(indent=0)
22
+ "#{("\t"*indent)}\"#{str}\""
23
+ end
24
+ end
25
+
26
+ class Identifier
27
+ attr_accessor :name, :prodset
28
+ def initialize(name)
29
+ @name = name
30
+ @prodset = prodset
31
+ end
32
+
33
+ def generate(indent=0)
34
+
35
+ code = "production->#{name.downcase} = #{name.downcase};"
36
+ if @prodset[name][:count] > 1
37
+ code = "production->#{name.downcase.pluralize}.push_back(#{name.downcase});"
38
+ end
39
+ "#{("\t"*indent)}#{name}<#{name.downcase}> (. #{code} .)"
40
+ end
41
+ end
42
+
43
+ class Token
44
+ attr_accessor :name
45
+ def initialize(name, prodset)
46
+ @name = name
47
+ end
48
+
49
+ def generate(indent=0)
50
+ "#{("\t"*indent)}#{name} (. production->content = t->val; .)"
51
+ end
52
+ end
53
+
54
+ class Sync
55
+ def generate(indent=0)
56
+ "#{("\t"*indent)}SYNC"
57
+ end
58
+ end
59
+
60
+ class Variation < Identifier
61
+
62
+ def generate(indent=0)
63
+ code = "production = #{name.downcase};"
64
+ "#{("\t"*indent)}#{name}<#{name.downcase}> (. #{code} .)"
65
+ end
66
+ end
67
+
68
+ class Group
69
+ def initialize(type=:normal, prodset={})
70
+ @type = type
71
+ @prodset = prodset
72
+ @stuff = []
73
+ end
74
+
75
+ def Object.const_missing(m)
76
+ return Identifier.new("#{m}")
77
+ end
78
+
79
+ def convert_thing(thing)
80
+ if thing.is_a? String
81
+ return LitString.new(thing, @prodset)
82
+ end
83
+
84
+ if thing.is_a? Identifier or thing.is_a? Variation
85
+
86
+ thing.prodset = @prodset
87
+
88
+ if !@prodset[thing.name]
89
+ @prodset[thing.name] = {count: 0, type: :id}
90
+ end
91
+ @prodset[thing.name][:count] += 1
92
+ @prodset[thing.name][:count] += 1 unless @type == :normal or @type == :either
93
+ end
94
+
95
+ if thing.is_a? Token
96
+ if !@prodset[thing.name]
97
+ @prodset[thing.name] = {count: 0, type: :token}
98
+ end
99
+ @prodset[thing.name][:count] += 1
100
+ @prodset[thing.name][:count] += 1 unless @type == :normal or @type == :either
101
+ end
102
+
103
+ return thing
104
+ end
105
+
106
+ def sync
107
+ @stuff << Sync.new
108
+ end
109
+
110
+ def one(thing)
111
+ thing = convert_thing(thing)
112
+ @stuff << thing
113
+ end
114
+
115
+ def either(*args)
116
+ g = Group.new :either, @prodset
117
+
118
+ g.instance_eval do
119
+ args.each do |x|
120
+ one x
121
+ end
122
+ end
123
+ one g
124
+ end
125
+
126
+ def maybe(thing)
127
+ g = Group.new :maybe, @prodset
128
+ g.instance_eval do
129
+ one thing
130
+ end
131
+ one g
132
+ end
133
+
134
+ def many(thing, options=nil)
135
+ one thing
136
+ maybemany thing, options
137
+ end
138
+
139
+ def maybemany(thing, options=nil)
140
+ g = Group.new :multiple, @prodset
141
+ g.instance_eval do
142
+ if options[:separator].is_a? String
143
+ one options[:separator]
144
+ else
145
+ puts "Separator needs to be a simple string"
146
+ end if options
147
+ one thing
148
+ end
149
+ one g
150
+ end
151
+
152
+ def group(&block)
153
+ g = Group.new :normal, @prodset
154
+ g.instance_eval(&block)
155
+ g
156
+ end
157
+
158
+ def generate(indent=0)
159
+
160
+ result = []
161
+
162
+ @stuff.each do |x|
163
+ result << "#{x.generate(indent+1)}"
164
+ end
165
+
166
+ openbrace = "("
167
+ closebrace = ")"
168
+ divider = ""
169
+
170
+ openbrace = "[" if @type == :maybe
171
+ closebrace = "]" if @type == :maybe
172
+
173
+ openbrace = "{" if @type == :multiple
174
+ closebrace = "}" if @type == :multiple
175
+
176
+
177
+ divider = "|" if @type == :either
178
+
179
+ ("\t"*indent) + openbrace + "\n" + result.join("#{divider}\n") + "\n" + ("\t"*indent) + closebrace
180
+ end
181
+
182
+ end
183
+
184
+ class Production < Group
185
+
186
+ attr_accessor :prodset, :prodtype
187
+
188
+ def initialize(name, prodtype=:normal)
189
+
190
+ @prodtype = prodtype
191
+ @name = name
192
+ super()
193
+ end
194
+
195
+ end
196
+
197
+ class Ruco < Production
198
+ def initialize(grammar_name, &block)
199
+ @name = grammar_name
200
+ super(grammar_name)
201
+ @productions = {grammar_name => self}
202
+ instance_eval(&block)
203
+ end
204
+
205
+ def grammar(name, &block)
206
+ p = Production.new(name, &block)
207
+ p.instance_eval(&block)
208
+ @productions[name] = p
209
+ end
210
+
211
+ def variation(name, *args)
212
+ p = Production.new(name, :variation)
213
+ p.instance_eval do
214
+ g = Group.new :either, @prodset
215
+ g.instance_eval do
216
+ args.each do |x|
217
+ if x.is_a? Identifier
218
+ one Variation.new(x.name)
219
+ else
220
+ puts "Variation needs to be a grammar"
221
+ end
222
+ end
223
+ end
224
+ one g
225
+ end
226
+ @productions[name] = p
227
+ end
228
+
229
+ def token(name, type)
230
+ p = Production.new(name)
231
+ case type
232
+ when :pascal_case
233
+ p.instance_eval do
234
+ one Token.new("pascalcase", @prodset)
235
+ end
236
+ when :camel_case
237
+ p.instance_eval do
238
+ one Token.new("camelcase", @prodset)
239
+ end
240
+ when :hex_integer
241
+ p.instance_eval do
242
+ one Token.new("hexinteger", @prodset)
243
+ end
244
+ when :integer
245
+ p.instance_eval do
246
+ one Token.new("integer", @prodset)
247
+ end
248
+ end
249
+ @productions[name] = p
250
+ end
251
+
252
+ def generate_header()
253
+
254
+ classlist = []
255
+
256
+ parent_map = {}
257
+
258
+ dependency_hash = TsortableHash.new
259
+
260
+ @productions.each do |prodname, prod|
261
+
262
+ if prod.prodtype == :normal
263
+
264
+ prod.prodset.each do |key, prodinfo|
265
+
266
+ if prodinfo[:type] == :id
267
+ if !dependency_hash[prodname]
268
+ dependency_hash[prodname] = []
269
+ end
270
+ dependency_hash[prodname] << "#{key}"
271
+ end
272
+ end
273
+
274
+ elsif prod.prodtype == :variation
275
+
276
+ prod.prodset.each do |key, prodinfo|
277
+
278
+ if prodinfo[:type] == :id
279
+ if !dependency_hash[key]
280
+ dependency_hash[key] = []
281
+ end
282
+ dependency_hash[key] << "#{prodname}"
283
+
284
+ if !parent_map[key]
285
+ parent_map[key] = []
286
+ end
287
+ parent_map[key] << "#{prodname}"
288
+
289
+ end
290
+
291
+ end
292
+
293
+ end
294
+
295
+ end
296
+
297
+ # remaining productions
298
+ @productions.each do |prodname, prod|
299
+ if !dependency_hash[prodname]
300
+ dependency_hash[prodname] = []
301
+ end
302
+ end
303
+
304
+ #puts "Dependency Chain:"
305
+ #p dependency_hash
306
+
307
+ dependency_hash.tsort.each do |prodname|
308
+
309
+ prod = @productions[prodname]
310
+
311
+
312
+ memberlist = []
313
+ if prod.prodtype == :normal
314
+
315
+ prod.prodset.each do |key, prodinfo|
316
+ name = "#{key}"
317
+
318
+ if prodinfo[:type] == :id
319
+
320
+ #puts "#{name} -> #{prodinfo[:count]}"
321
+
322
+ if prodinfo[:count] > 1
323
+ memberlist << "#{name}Array #{name.downcase.pluralize};"
324
+ else
325
+ memberlist << "#{name}Ptr #{name.downcase};"
326
+ end
327
+
328
+ elsif prodinfo[:type] == :token
329
+
330
+ memberlist << "std::wstring content;"
331
+ end
332
+
333
+ end
334
+
335
+ elsif prod.prodtype == :variation
336
+
337
+ enumeration_list = []
338
+ prod.prodset.each do |key, prodinfo|
339
+ enumeration_list << "\t#{key.upcase}_#{prodname.upcase}"
340
+ end
341
+
342
+ enumerations = enumeration_list.join ",\n"
343
+
344
+
345
+ classlist << <<-TYPE_ENUM_CONTENT
346
+ enum #{prodname}Type
347
+ {
348
+ #{enumerations}
349
+ };
350
+ TYPE_ENUM_CONTENT
351
+
352
+ memberlist << "virtual #{prodname}Type get_#{prodname.downcase}_type() const = 0;"
353
+
354
+ else
355
+ puts "UNKNOWN PRODUCTION TYPE: #{prod.prodtype}"
356
+ end
357
+
358
+ parent_declaration = ""
359
+ parent_impl = ""
360
+
361
+ if parent_map[prodname]
362
+ list = parent_map[prodname].map{|x| "public #{x}"}.join ", "
363
+ parent_declaration = ": #{list}"
364
+
365
+ parent_map[prodname].each do |parent|
366
+ memberlist << <<-PARENTDECL
367
+ virtual #{parent}Type get_#{parent.downcase}_type() const
368
+ {
369
+ return #{prodname.upcase}_#{parent.upcase};
370
+ }
371
+ PARENTDECL
372
+ end
373
+
374
+ end
375
+
376
+ members = memberlist.map {|x| "\t#{x}"}.join "\n"
377
+
378
+ classlist << <<-CLASSCONTENT
379
+ class #{prodname} #{parent_declaration}
380
+ {
381
+ public:
382
+ #{members}
383
+ };
384
+ typedef std::shared_ptr<#{prodname}> #{prodname}Ptr;
385
+ typedef std::vector<#{prodname}Ptr> #{prodname}Array;
386
+ CLASSCONTENT
387
+ end
388
+
389
+ classes = classlist.join "\n"
390
+
391
+ header = <<-HEADEREND
392
+
393
+ #ifndef #{@name.upcase}_HPP
394
+ #define #{@name.upcase}_HPP
395
+
396
+ /*
397
+ WARNING: This file is generated using ruco. Please modify the .ruco file if you wish to change anything
398
+ https://github.com/davidsiaw/ruco
399
+ */
400
+
401
+ #include <string>
402
+ #include <memory>
403
+ #include <vector>
404
+
405
+ namespace #{@name}
406
+ {
407
+
408
+ #{classes}
409
+
410
+ }
411
+
412
+ #endif // #{@name.upcase}_HPP
413
+
414
+ HEADEREND
415
+
416
+ header
417
+
418
+ end
419
+
420
+ def generate_libhpp()
421
+ <<-HPPCONTENT
422
+
423
+ #ifndef PARSE_#{@name.upcase}_HPP
424
+ #define PARSE_#{@name.upcase}_HPP
425
+
426
+ /*
427
+ WARNING: This file is generated using ruco. Please modify the .ruco file if you wish to change anything
428
+ https://github.com/davidsiaw/ruco
429
+ */
430
+
431
+ #include <iostream>
432
+ #include <memory>
433
+ #include <fstream>
434
+ #include <sstream>
435
+ #include <string>
436
+ #include <vector>
437
+ #include <set>
438
+
439
+ #include "Scanner.h"
440
+ #include "Parser.h"
441
+
442
+ #include "picojson.hpp"
443
+
444
+ namespace #{@name}
445
+ {
446
+ /**
447
+ * Parses a source file into the data structure of #{@name}
448
+ */
449
+ #{@name}Ptr Parse(std::string sourceFile);
450
+
451
+ /**
452
+ * Transforms the data structure of #{@name} to an abstract syntax tree in JSON format
453
+ */
454
+ picojson::value Jsonify(#{@name}Ptr parseResult);
455
+ }
456
+
457
+ #endif // PARSE_#{@name.upcase}_HPP
458
+
459
+ HPPCONTENT
460
+ end
461
+
462
+ def write_jsonify_function(prodname, prod)
463
+
464
+ pset = <<-PSETEND
465
+ object[L"_type"] = picojson::value(L"#{prodname}");
466
+ PSETEND
467
+
468
+ if prod.prodtype == :variation
469
+
470
+ switchladder = ""
471
+
472
+ prod.prodset.each do |key, prodinfo|
473
+
474
+ switchladder += <<-LADDEREND
475
+ case #{key.upcase}_#{prodname.upcase}:
476
+ {
477
+ content = Compile#{key}(std::dynamic_pointer_cast<#{key}>(pointer));
478
+ break;
479
+ }
480
+ LADDEREND
481
+
482
+ end
483
+
484
+ pset += <<-PSETEND
485
+ picojson::object content;
486
+ switch(pointer->get_#{prodname.downcase}_type())
487
+ {
488
+ #{switchladder}
489
+ }
490
+
491
+ object[L"_content"] = picojson::value(content);
492
+ PSETEND
493
+
494
+
495
+ elsif prod.prodtype == :normal
496
+
497
+ members_code = ""
498
+
499
+ prod.prodset.each do |key, prodinfo|
500
+
501
+ members_code += <<-MEMBERCODEEND
502
+ // #{prodinfo}
503
+ MEMBERCODEEND
504
+
505
+ if prodinfo[:count] == 1
506
+
507
+ if prodinfo[:type] == :token
508
+
509
+ members_code += <<-PSETEND
510
+ object[L"_token"] = picojson::value(pointer->content);
511
+ PSETEND
512
+
513
+ elsif prodinfo[:type] == :id
514
+ members_code += <<-PSETEND
515
+
516
+ picojson::object #{key.downcase};
517
+
518
+ #{key.downcase} = Compile#{key}(pointer->#{key.downcase});
519
+
520
+ object[L"#{key.downcase}"] = picojson::value(#{key.downcase});
521
+ PSETEND
522
+ end
523
+
524
+ else
525
+
526
+ if prodinfo[:type] == :token
527
+ raise "Unimplemented"
528
+
529
+ elsif prodinfo[:type] == :id
530
+ members_code += <<-PSETEND
531
+
532
+ picojson::array #{key.downcase}s;
533
+
534
+ for(unsigned i=0; i<pointer->#{key.downcase}s.size(); i++)
535
+ {
536
+ #{key.downcase}s.push_back(picojson::value(Compile#{key}(pointer->#{key.downcase}s[i])));
537
+ }
538
+
539
+ object[L"#{key.downcase}s"] = picojson::value(#{key.downcase}s);
540
+ PSETEND
541
+ end
542
+
543
+ end
544
+
545
+ end
546
+
547
+ pset += <<-PSETEND
548
+
549
+
550
+ #{members_code}
551
+
552
+
553
+ PSETEND
554
+
555
+ end
556
+
557
+ funcname = "picojson::object Compile#{prodname}(#{prodname}Ptr pointer)"
558
+
559
+ funcdef = <<-FUNCTIONEND
560
+ #{funcname}
561
+ {
562
+ picojson::object object;
563
+
564
+ // #{prod.prodtype}
565
+ #{pset}
566
+ return object;
567
+ }
568
+
569
+ FUNCTIONEND
570
+
571
+ {name: funcname, definition: funcdef}
572
+
573
+ end
574
+
575
+ def generate_libcpp()
576
+
577
+ functions = ""
578
+ function_declarations = ""
579
+
580
+ @productions.each do |prodname, prod|
581
+
582
+ f = write_jsonify_function(prodname, prod)
583
+ functions += f[:definition]
584
+ function_declarations += <<-FUNCDECLEND
585
+ #{f[:name]};
586
+ FUNCDECLEND
587
+ end
588
+
589
+ <<-CPPCONTENT
590
+
591
+ #include "parse_#{@name.downcase}.hpp"
592
+
593
+ /*
594
+ WARNING: This file is generated using ruco. Please modify the .ruco file if you wish to change anything
595
+ https://github.com/davidsiaw/ruco
596
+ */
597
+
598
+ namespace #{@name}
599
+ {
600
+ #{@name}Ptr Parse(std::string sourceFile)
601
+ {
602
+ std::shared_ptr<FILE> fp (fopen(sourceFile.c_str(), "r"), fclose);
603
+ std::shared_ptr<Scanner> scanner (new Scanner(fp.get()));
604
+ std::shared_ptr<Parser> parser (new Parser(scanner.get()));
605
+ parser->Parse();
606
+
607
+ return parser->#{@name.downcase};
608
+ }
609
+
610
+ #{function_declarations}
611
+ #{functions}
612
+
613
+ picojson::value Jsonify(SerialistPtr parseResult)
614
+ {
615
+ return picojson::value(CompileSerialist(parseResult));
616
+ }
617
+
618
+ }
619
+
620
+ CPPCONTENT
621
+ end
622
+
623
+ def generate_atg()
624
+
625
+ productionlist = []
626
+ productiondecl = []
627
+
628
+
629
+ @productions.each do |prodname, prod|
630
+
631
+ decllist = []
632
+
633
+ prod.prodset.each do |key, prodinfo|
634
+ if prodinfo[:type] == :id
635
+ decllist << "(. #{key}Ptr #{key.downcase}; .)"
636
+ end
637
+ end
638
+
639
+ declarations = decllist.join "\n"
640
+
641
+ attributes = "<#{prodname}Ptr& production>" unless prodname == @name
642
+
643
+ constructor = ""
644
+
645
+ constructor = "(. production = std::make_shared<class #{prodname}>(); .)" if prod.prodtype == :normal
646
+
647
+ production_string = <<-PRODUCTION
648
+ #{prodname}#{attributes} = #{constructor}
649
+ #{declarations}
650
+ #{prod.generate}
651
+ .
652
+ PRODUCTION
653
+
654
+ production_string.gsub!(/production/, @name.downcase) if prodname == @name
655
+
656
+ productionlist << production_string
657
+ end
658
+
659
+ productions = productionlist.join("\n")
660
+
661
+ <<-FRAMEEND
662
+
663
+ #include <iostream>
664
+ #include <memory>
665
+ #include "#{@name}.hpp"
666
+
667
+ /*
668
+ WARNING: This file is generated using ruco. Please modify the .ruco file if you wish to change anything
669
+ https://github.com/davidsiaw/ruco
670
+ */
671
+
672
+ COMPILER #{@name}
673
+
674
+ #{@name}Ptr #{@name.downcase};
675
+
676
+ CHARACTERS
677
+ bigletter = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".
678
+ letter = "abcdefghijklmnopqrstuvwxyz".
679
+ underscore = "_".
680
+ digit = "0123456789".
681
+ cr = '\\r'.
682
+ lf = '\\n'.
683
+ tab = '\\t'.
684
+ stringCh = ANY - '"' - '\\\\' - cr - lf.
685
+ charCh = ANY - '\\'' - '\\\\' - cr - lf.
686
+ printable = '\\u0020' .. '\\u007e'.
687
+ hex = "0123456789abcdef".
688
+
689
+ TOKENS
690
+ pascalcase = bigletter { bigletter | letter | digit }.
691
+ camelcase = letter { bigletter | letter | digit }.
692
+
693
+ integer = digit { digit }.
694
+ hexinteger = '0' 'x' hex { hex }.
695
+
696
+ string = '"' { stringCh | '\\\\' printable } '"'.
697
+ badString = '"' { stringCh | '\\\\' printable } (cr | lf).
698
+ char = '\\'' ( charCh | '\\\\' printable { hex } ) '\\''.
699
+ endOfLine = cr | lf.
700
+
701
+ PRAGMAS
702
+ ddtSym = '$' { digit | letter }.
703
+ optionSym = '$' letter { letter } '='
704
+ { digit | letter
705
+ | '-' | '.' | ':'
706
+ }.
707
+
708
+
709
+ COMMENTS FROM "/*" TO "*/" NESTED
710
+ COMMENTS FROM "//" TO lf
711
+
712
+ IGNORE tab + cr + lf
713
+
714
+ /*-------------------------------------------------------------------------*/
715
+
716
+ PRODUCTIONS
717
+
718
+ #{productions}
719
+
720
+
721
+ END #{@name}.
722
+
723
+ FRAMEEND
724
+
725
+ end
726
+ end
727
+ end
728
+