myco 0.1.8 → 0.1.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (89) hide show
  1. checksums.yaml +4 -4
  2. data/lib/myco/bootstrap/instance.rb +13 -3
  3. data/lib/myco/code_tools/AST.my +0 -2
  4. data/lib/myco/code_tools/AST.my.rb +0 -1
  5. data/lib/myco/code_tools/AST/Block.my +15 -4
  6. data/lib/myco/code_tools/AST/Block.my.rb +16 -3
  7. data/lib/myco/code_tools/AST/DeclareMeme.my +44 -64
  8. data/lib/myco/code_tools/AST/DeclareMeme.my.rb +66 -74
  9. data/lib/myco/code_tools/AST/ToRuby.my +17 -20
  10. data/lib/myco/code_tools/AST/ToRuby.my.rb +24 -22
  11. data/lib/myco/code_tools/Parser.my +2 -1
  12. data/lib/myco/code_tools/Parser.my.rb +2 -1
  13. data/lib/myco/code_tools/parser/MycoBuilder.my +2 -2
  14. data/lib/myco/code_tools/parser/MycoBuilder.my.rb +2 -2
  15. data/lib/myco/code_tools/parser/MycoGrammar.my +28 -21
  16. data/lib/myco/code_tools/parser/MycoGrammar.my.rb +94 -56
  17. data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces.my +10 -11
  18. data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces.my.rb +10 -9
  19. data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/BytecodeHelpers.my +25 -3
  20. data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/BytecodeHelpers.my.rb +38 -0
  21. data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/Capture.my +152 -0
  22. data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/Capture.my.rb +189 -0
  23. data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/Common.my +84 -0
  24. data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/Common.my.rb +114 -0
  25. data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/Common/Parser.my +139 -0
  26. data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/{BytecodeParser.my.rb → Common/Parser.my.rb} +17 -36
  27. data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/Composite.my +229 -0
  28. data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/Composite.my.rb +296 -0
  29. data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/Grammar.my +8 -25
  30. data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/Grammar.my.rb +9 -37
  31. data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/Parser.my +139 -37
  32. data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/Parser.my.rb +206 -36
  33. data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/Processor.my +21 -12
  34. data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/Processor.my.rb +45 -24
  35. data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/Stream.my +99 -0
  36. data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/Stream.my.rb +152 -0
  37. data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/Stream/Parser.my +37 -0
  38. data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/Stream/Parser.my.rb +57 -0
  39. data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/String.my +136 -0
  40. data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/String.my.rb +147 -0
  41. data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/String/Parser.my +45 -0
  42. data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/String/Parser.my.rb +85 -0
  43. data/lib/myco/code_tools/parser/pegleromyces/spec/Patterns.test.my +31 -25
  44. data/lib/myco/code_tools/parser/pegleromyces/spec/Patterns.test.my.rb +44 -25
  45. data/lib/myco/code_tools/parser/pegleromyces/spec/Stream/Parser.test.my +49 -0
  46. data/lib/myco/code_tools/parser/pegleromyces/spec/Stream/Parser.test.my.rb +119 -0
  47. data/lib/myco/code_tools/parser/pegleromyces/spec/Stream/Patterns.test.my +131 -0
  48. data/lib/myco/code_tools/parser/pegleromyces/spec/Stream/Patterns.test.my.rb +595 -0
  49. data/lib/myco/code_tools/parser/pegleromyces/spec/{BytecodeParser.test.my → String/Parser.test.my} +41 -2
  50. data/lib/myco/code_tools/parser/pegleromyces/spec/{BytecodeParser.test.my.rb → String/Parser.test.my.rb} +144 -3
  51. data/lib/myco/code_tools/parser/pegleromyces/spec/run.my +4 -10
  52. data/lib/myco/code_tools/parser/pegleromyces/spec/run.my.rb +4 -8
  53. data/lib/myco/core.my +1 -0
  54. data/lib/myco/core.my.rb +1 -0
  55. data/lib/myco/core/BasicObject.my +4 -2
  56. data/lib/myco/core/BasicObject.my.rb +2 -5
  57. data/lib/myco/core/Loop.my +5 -0
  58. data/lib/myco/core/Loop.my.rb +13 -0
  59. data/lib/myco/dev.rb +1 -0
  60. data/lib/myco/dev/profile.rb +12 -0
  61. data/lib/myco/version.rb +3 -3
  62. metadata +54 -59
  63. data/lib/myco/code_tools/AST/DeclareDecorator.my +0 -19
  64. data/lib/myco/code_tools/AST/DeclareDecorator.my.rb +0 -24
  65. data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/Builder.my +0 -4
  66. data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/Builder.my.rb +0 -5
  67. data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/BytecodeInstructions.my +0 -420
  68. data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/BytecodeInstructions.my.rb +0 -415
  69. data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/BytecodeParser.my +0 -147
  70. data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/Constructions.my +0 -183
  71. data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/Constructions.my.rb +0 -370
  72. data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/Instructions.my +0 -139
  73. data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/Instructions.my.rb +0 -284
  74. data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/Machine.my +0 -37
  75. data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/Machine.my.rb +0 -24
  76. data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/Patterns.my +0 -123
  77. data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/Patterns.my.rb +0 -164
  78. data/lib/myco/code_tools/parser/pegleromyces/spec/Builder.test.my +0 -10
  79. data/lib/myco/code_tools/parser/pegleromyces/spec/Builder.test.my.rb +0 -9
  80. data/lib/myco/code_tools/parser/pegleromyces/spec/BytecodeInstructions.test.my +0 -10
  81. data/lib/myco/code_tools/parser/pegleromyces/spec/BytecodeInstructions.test.my.rb +0 -9
  82. data/lib/myco/code_tools/parser/pegleromyces/spec/Constructions.test.my +0 -229
  83. data/lib/myco/code_tools/parser/pegleromyces/spec/Constructions.test.my.rb +0 -663
  84. data/lib/myco/code_tools/parser/pegleromyces/spec/Instructions.test.my +0 -10
  85. data/lib/myco/code_tools/parser/pegleromyces/spec/Instructions.test.my.rb +0 -9
  86. data/lib/myco/code_tools/parser/pegleromyces/spec/Machine.test.my +0 -13
  87. data/lib/myco/code_tools/parser/pegleromyces/spec/Machine.test.my.rb +0 -20
  88. data/lib/myco/code_tools/parser/pegleromyces/spec/Parser.test.my +0 -54
  89. data/lib/myco/code_tools/parser/pegleromyces/spec/Parser.test.my.rb +0 -215
@@ -0,0 +1,84 @@
1
+
2
+ Common < EmptyObject {
3
+ Patterns < EmptyObject {
4
+ Base < BasicObject { var name: parent_meme.name }
5
+ UnaryBase < Base { var inner }
6
+ BinaryBase < Base { var first, var second }
7
+
8
+ UnaryBase << {
9
+ construct: construct_type.new(inner: inner.construct)
10
+ }
11
+
12
+ BinaryBase << {
13
+ construct: construct_type.new(first: first.construct, second: second.construct)
14
+ }
15
+ }
16
+
17
+ Constructions < EmptyObject {
18
+ Base < BasicObject { }
19
+ UnaryBase < Base { var inner }
20
+ BinaryBase < Base { var first, var second }
21
+ }
22
+
23
+ Constructions << {
24
+ Base << { const bytecode_can_capture?: false }
25
+ UnaryBase << { bytecode_can_capture?: inner.bytecode_can_capture? }
26
+ BinaryBase << { bytecode_can_capture?: first.bytecode_can_capture?
27
+ || second.bytecode_can_capture? }
28
+ }
29
+
30
+ Patterns << {
31
+ ##
32
+ # Shorthand methods for creating primitive patterns
33
+
34
+ ShorthandMethods < EmptyObject {
35
+ any: || String::Patterns::AnyCharacter .new
36
+ char: |character| String::Patterns::Character .new(code:character.ord)
37
+ str: |string| String::Patterns::CharacterString.new(codes:string.each_char.map(&:ord))
38
+ set: |string| String::Patterns::CharacterSet .new(codes:string.each_char.map(&:ord))
39
+ range: |start, stop| String::Patterns::CharacterRange .new(start:start.ord, stop:stop.ord)
40
+ r: |pattern, &block| Capture::Patterns::Reduction .new(inner:pattern, block:block)
41
+ si: |*checks| Stream::Patterns::Item .new(checks:checks)
42
+ esi: || Stream::Patterns::End .new
43
+ }
44
+
45
+ ##
46
+ # Operator overloading for combining and modifying patterns.
47
+ #
48
+ # Each operation returns a new Pattern object composed of the operands
49
+ # so that complex grammars can be specified with relatively succint syntax.
50
+
51
+ Base << {
52
+ "!": Composite::Patterns::NegativePredicate .new(inner:self)
53
+ "/": |other| Composite::Patterns::OrderedChoice .new(first:self, second:other)
54
+ "+": |other=false|
55
+ other &? Composite::Patterns::Concatenation .new(first:self, second:other)
56
+ ?? Composite::Patterns::OneOrMore .new(inner:self)
57
+ "-": |other=false|
58
+ other &? raise("binary '-' operator not implemented")
59
+ ?? Composite::Patterns::ZeroOrOne .new(inner:self)
60
+ "*": |other=false|
61
+ other &? raise("binary '*' operator not implemented")
62
+ ?? Composite::Patterns::ZeroOrMore .new(inner:self)
63
+
64
+ "[]": |name| Capture::Patterns::NamedCapture .new(inner:self, name:name)
65
+ text: |name=:text|
66
+ Capture::Patterns::NamedTextCapture .new(inner:self, name:name)
67
+ token: |name|
68
+ Capture::Patterns::NamedTokenCapture .new(inner:self, name:name)
69
+
70
+ [private]
71
+
72
+ # Add |other| to |orig| in a right-associative tree of type |type|
73
+ binary_right_assoc: |orig, other, type| {
74
+ cursor = orig
75
+ loop {
76
+ unless(cursor.second.is_a?(type)) { break }
77
+ cursor = cursor.second
78
+ }
79
+ cursor.second = type.new(first:cursor.second, second:other)
80
+ orig
81
+ }
82
+ }
83
+ }
84
+ }
@@ -0,0 +1,114 @@
1
+
2
+ ::Myco::Component.new([::Myco::FileToplevel], ::Myco.cscope.for_method_definition, __FILE__, __LINE__)
3
+ .tap { |__c__| __c__.__last__ = __c__.component_eval {(::Myco.cscope.for_method_definition::Common = ::Myco::Component.new([::Myco.find_constant(:EmptyObject)], ::Myco.cscope.for_method_definition, __FILE__, __LINE__)
4
+ .tap { |__c__| __c__.__last__ = __c__.component_eval {(
5
+ ::Myco.cscope.for_method_definition::Patterns = ::Myco::Component.new([::Myco.find_constant(:EmptyObject)], ::Myco.cscope.for_method_definition, __FILE__, __LINE__)
6
+ .tap { |__c__| __c__.__last__ = __c__.component_eval {(
7
+ ::Myco.cscope.for_method_definition::Base = ::Myco::Component.new([::Myco.find_constant(:BasicObject)], ::Myco.cscope.for_method_definition, __FILE__, __LINE__)
8
+ .tap { |__c__| __c__.__last__ = __c__.component_eval {(declare_meme(:name, [[:var, []]], nil, ::Myco.cscope.dup) { |*| (self.parent_meme.name)})}}
9
+ .tap { |__c__| __c__.__name__ = :Base }
10
+ ::Myco.cscope.for_method_definition::UnaryBase = ::Myco::Component.new([::Myco.find_constant(:Base)], ::Myco.cscope.for_method_definition, __FILE__, __LINE__)
11
+ .tap { |__c__| __c__.__last__ = __c__.component_eval {(declare_meme(:inner, [[:var, []]], nil, ::Myco.cscope.dup) { |*| nil})}}
12
+ .tap { |__c__| __c__.__name__ = :UnaryBase }
13
+ ::Myco.cscope.for_method_definition::BinaryBase = ::Myco::Component.new([::Myco.find_constant(:Base)], ::Myco.cscope.for_method_definition, __FILE__, __LINE__)
14
+ .tap { |__c__| __c__.__last__ = __c__.component_eval {(
15
+ declare_meme(:first, [[:var, []]], nil, ::Myco.cscope.dup) { |*| nil}
16
+ declare_meme(:second, [[:var, []]], nil, ::Myco.cscope.dup) { |*| nil}
17
+ )}}
18
+ .tap { |__c__| __c__.__name__ = :BinaryBase }
19
+ ::Myco.find_constant(:UnaryBase).component_eval {(declare_meme(:construct, [], nil, ::Myco.cscope.dup) { |*| (self.construct_type.new({:inner => self.inner.construct}))})}
20
+ ::Myco.find_constant(:BinaryBase).component_eval {(declare_meme(:construct, [], nil, ::Myco.cscope.dup) { |*| (self.construct_type.new({
21
+ :first => self.first.construct,
22
+ :second => self.second.construct
23
+ }))})}
24
+ )}}
25
+ .tap { |__c__| __c__.__name__ = :Patterns }
26
+ ::Myco.cscope.for_method_definition::Constructions = ::Myco::Component.new([::Myco.find_constant(:EmptyObject)], ::Myco.cscope.for_method_definition, __FILE__, __LINE__)
27
+ .tap { |__c__| __c__.__last__ = __c__.component_eval {(
28
+ ::Myco.cscope.for_method_definition::Base = ::Myco::Component.new([::Myco.find_constant(:BasicObject)], ::Myco.cscope.for_method_definition, __FILE__, __LINE__)
29
+ .tap { |__c__| __c__.__last__ = __c__.component_eval {nil}}
30
+ .tap { |__c__| __c__.__name__ = :Base }
31
+ ::Myco.cscope.for_method_definition::UnaryBase = ::Myco::Component.new([::Myco.find_constant(:Base)], ::Myco.cscope.for_method_definition, __FILE__, __LINE__)
32
+ .tap { |__c__| __c__.__last__ = __c__.component_eval {(declare_meme(:inner, [[:var, []]], nil, ::Myco.cscope.dup) { |*| nil})}}
33
+ .tap { |__c__| __c__.__name__ = :UnaryBase }
34
+ ::Myco.cscope.for_method_definition::BinaryBase = ::Myco::Component.new([::Myco.find_constant(:Base)], ::Myco.cscope.for_method_definition, __FILE__, __LINE__)
35
+ .tap { |__c__| __c__.__last__ = __c__.component_eval {(
36
+ declare_meme(:first, [[:var, []]], nil, ::Myco.cscope.dup) { |*| nil}
37
+ declare_meme(:second, [[:var, []]], nil, ::Myco.cscope.dup) { |*| nil}
38
+ )}}
39
+ .tap { |__c__| __c__.__name__ = :BinaryBase }
40
+ )}}
41
+ .tap { |__c__| __c__.__name__ = :Constructions }
42
+ ::Myco.find_constant(:Constructions).component_eval {(
43
+ ::Myco.find_constant(:Base).component_eval {(declare_meme(:bytecode_can_capture?, [[:const, []]], nil, ::Myco.cscope.dup) { |*| (false)})}
44
+ ::Myco.find_constant(:UnaryBase).component_eval {(declare_meme(:bytecode_can_capture?, [], nil, ::Myco.cscope.dup) { |*| (self.inner.__send__(:bytecode_can_capture?))})}
45
+ ::Myco.find_constant(:BinaryBase).component_eval {(declare_meme(:bytecode_can_capture?, [], nil, ::Myco.cscope.dup) { |*| (::Myco.branch_op(:"||", self.first.__send__(:bytecode_can_capture?)) {self.second.__send__(:bytecode_can_capture?)})})}
46
+ )}
47
+ ::Myco.find_constant(:Patterns).component_eval {(
48
+ ::Myco.cscope.for_method_definition::ShorthandMethods = ::Myco::Component.new([::Myco.find_constant(:EmptyObject)], ::Myco.cscope.for_method_definition, __FILE__, __LINE__)
49
+ .tap { |__c__| __c__.__last__ = __c__.component_eval {(
50
+ declare_meme(:any, [], nil, ::Myco.cscope.dup) { || (::Myco.find_constant(:String)::Patterns::AnyCharacter.new)}
51
+ declare_meme(:char, [], nil, ::Myco.cscope.dup) { |character| (::Myco.find_constant(:String)::Patterns::Character.new({:code => character.ord}))}
52
+ declare_meme(:str, [], nil, ::Myco.cscope.dup) { |string| (::Myco.find_constant(:String)::Patterns::CharacterString.new({:codes => string.each_char.map(&:ord)}))}
53
+ declare_meme(:set, [], nil, ::Myco.cscope.dup) { |string| (::Myco.find_constant(:String)::Patterns::CharacterSet.new({:codes => string.each_char.map(&:ord)}))}
54
+ declare_meme(:range, [], nil, ::Myco.cscope.dup) { |start, stop| (::Myco.find_constant(:String)::Patterns::CharacterRange.new({
55
+ :start => start.ord,
56
+ :stop => stop.ord
57
+ }))}
58
+ declare_meme(:r, [], nil, ::Myco.cscope.dup) { |pattern, &block| (::Myco.find_constant(:Capture)::Patterns::Reduction.new({
59
+ :inner => pattern,
60
+ :block => block
61
+ }))}
62
+ declare_meme(:si, [], nil, ::Myco.cscope.dup) { |*checks| (::Myco.find_constant(:Stream)::Patterns::Item.new({:checks => checks}))}
63
+ declare_meme(:esi, [], nil, ::Myco.cscope.dup) { || (::Myco.find_constant(:Stream)::Patterns::End.new)}
64
+ )}}
65
+ .tap { |__c__| __c__.__name__ = :ShorthandMethods }
66
+ ::Myco.find_constant(:Base).component_eval {(
67
+ declare_meme(:!, [], nil, ::Myco.cscope.dup) { |*| (::Myco.find_constant(:Composite)::Patterns::NegativePredicate.new({:inner => self}))}
68
+ declare_meme(:/, [], nil, ::Myco.cscope.dup) { |other| (::Myco.find_constant(:Composite)::Patterns::OrderedChoice.new({
69
+ :first => self,
70
+ :second => other
71
+ }))}
72
+ declare_meme(:+, [], nil, ::Myco.cscope.dup) { |other=false| (::Myco.branch_op(:"??", ::Myco.branch_op(:"&?", other) {::Myco.find_constant(:Composite)::Patterns::Concatenation.new({
73
+ :first => self,
74
+ :second => other
75
+ })}) {::Myco.find_constant(:Composite)::Patterns::OneOrMore.new({:inner => self})})}
76
+ declare_meme(:-, [], nil, ::Myco.cscope.dup) { |other=false| (::Myco.branch_op(:"??", ::Myco.branch_op(:"&?", other) {self.raise("binary '-' operator not implemented")}) {::Myco.find_constant(:Composite)::Patterns::ZeroOrOne.new({:inner => self})})}
77
+ declare_meme(:*, [], nil, ::Myco.cscope.dup) { |other=false| (::Myco.branch_op(:"??", ::Myco.branch_op(:"&?", other) {self.raise("binary '*' operator not implemented")}) {::Myco.find_constant(:Composite)::Patterns::ZeroOrMore.new({:inner => self})})}
78
+ declare_meme(:[], [], nil, ::Myco.cscope.dup) { |name| (::Myco.find_constant(:Capture)::Patterns::NamedCapture.new({
79
+ :inner => self,
80
+ :name => name
81
+ }))}
82
+ declare_meme(:text, [], nil, ::Myco.cscope.dup) { |name=:text| (::Myco.find_constant(:Capture)::Patterns::NamedTextCapture.new({
83
+ :inner => self,
84
+ :name => name
85
+ }))}
86
+ declare_meme(:token, [], nil, ::Myco.cscope.dup) { |name| (::Myco.find_constant(:Capture)::Patterns::NamedTokenCapture.new({
87
+ :inner => self,
88
+ :name => name
89
+ }))}
90
+ __category__(:private).component_eval {(declare_meme(:binary_right_assoc, [], nil, ::Myco.cscope.dup) { |orig, other, type| (
91
+ cursor = orig
92
+ self.loop { || (
93
+ self.__send__(
94
+ :unless,
95
+ cursor.second.__send__(
96
+ :is_a?,
97
+ type
98
+ )
99
+ ) { || (self.__send__(:break))}
100
+ cursor = cursor.second
101
+ )}
102
+ cursor.__send__(
103
+ :second=,
104
+ type.new({
105
+ :first => cursor.second,
106
+ :second => other
107
+ })
108
+ )
109
+ orig
110
+ )})}
111
+ )}
112
+ )}
113
+ )}}
114
+ .tap { |__c__| __c__.__name__ = :Common })}}.instance
@@ -0,0 +1,139 @@
1
+
2
+ Common << {
3
+ Parser < BasicObject {
4
+ State < BasicObject {
5
+ var start_idx
6
+ var end_idx
7
+ var rule
8
+ var result
9
+
10
+ var error_idx
11
+
12
+ raise_error: self.error_idx && raise(SyntaxError
13
+ "Syntax error with parser: "self.rule" at index: "self.error_idx""
14
+ )
15
+ }
16
+
17
+ var debug_mode: false
18
+
19
+ var grammar: Grammar.new
20
+ var builder: null
21
+
22
+ new_worker: set_up_worker(prototype.new)
23
+ new_processor: Processor.new(builder: builder)
24
+
25
+ var prototype: compile_prototype
26
+
27
+ refresh: self.prototype = compile_prototype
28
+
29
+ compile_prototype: {
30
+ proto = Component.new
31
+ grammar.construct_all_rules
32
+ grammar.rule_table.each |name, rule| {
33
+ compile_rule_into(proto, name, rule)
34
+ }
35
+ proto
36
+ }
37
+
38
+ compile_rule_into: |proto, name, rule| {
39
+ construct = rule.inner.construct
40
+
41
+ Myco.add_dynamic_method(proto, name, "(compiled parser)") |g| {
42
+ g.extend(BytecodeHelpers)
43
+ g.debug_mode = self.debug_mode
44
+ g.rule_start
45
+ construct.bytecode(g)
46
+ g.rule_finish
47
+ }
48
+ }
49
+
50
+ compile_generator: |name, file, line=1, &block| {
51
+ g = Myco::ToolSet::Generator.new
52
+ g.name = name
53
+ g.file = file
54
+ g.set_line(line)
55
+
56
+ block.call(g)
57
+
58
+ g.ret
59
+ g.close
60
+ g.use_detected
61
+ g
62
+ }
63
+
64
+ compile_code: |name, file, line=1, &block| {
65
+ g = compile_generator(name, file, line, &block)
66
+ g.encode
67
+ g.package(Rubinius::CompiledCode)
68
+ }
69
+
70
+ save_prototype: |filename| {
71
+ code = compile_code(:__script__, :"(snippet)") |g| {
72
+ g.push_cpath_top; g.find_const(:Class)
73
+ g.create_block(compile_generator(:__block__, :"(snippet)") |g| {
74
+ prototype.instance_methods.each |name| {
75
+ code = prototype.instance_method(name).executable
76
+ if(code.is_a?(Rubinius::CompiledCode)) {
77
+ g.push_rubinius
78
+ g.push_literal(name)
79
+ g.push_literal(code)
80
+ g.push_scope
81
+ g.push_variables; g.send(:method_visibility, 0)
82
+ g.send(:add_defn_method, 4)
83
+ }
84
+ }
85
+ })
86
+ g.send_with_block(:new, 0)
87
+ }
88
+
89
+ Myco::ToolSet::CompiledFile.dump(code, filename, Rubinius::Signature, Rubinius::RUBY_LIB_VERSION)
90
+ }
91
+
92
+ load_prototype: |filename| {
93
+ loader = Myco::CodeLoader::BytecodeLoader.new(filename)
94
+ loader.bind_to(call_depth:1)
95
+ self.prototype = loader.load
96
+ }
97
+
98
+ set_up_worker: |worker| {
99
+ worker.__set_ivar__(:"@captures", [])
100
+ worker.__set_ivar__(:"@highest_idx", 0)
101
+ worker
102
+ }
103
+
104
+ captures_of_worker: |worker|
105
+ worker.__get_ivar__(:"@captures")
106
+
107
+ highest_idx_of_worker: |worker|
108
+ worker.__get_ivar__(:"@highest_idx")
109
+
110
+ parse: {
111
+ raise("The parse method is not implemented for "self"")
112
+ }
113
+ # Match and process the given string using the current grammar
114
+ parse: |string, rule:"root", start_idx:0| {
115
+ worker = new_worker
116
+ processor = new_processor
117
+ state = State.new(
118
+ string: string.to_s
119
+ rule: rule.to_sym
120
+ start_idx: start_idx.to_i
121
+ )
122
+
123
+ state.end_idx = worker.__send__(state.rule, state.string, state.start_idx)
124
+
125
+ state.end_idx &? (
126
+ processor.string = state.string
127
+ processor.capture_items = captures_of_worker(worker)
128
+ grammar.?tokenizer && (processor.tokenizer = grammar.tokenizer)
129
+ state.result = processor.process
130
+ ) ?? (
131
+ state.error_idx = highest_idx_of_worker(worker)
132
+ pos = processor.position_of(state.error_idx, state.string)
133
+ state.error_row = pos.first
134
+ state.error_col = pos.last
135
+ )
136
+ state
137
+ }
138
+ }
139
+ }
@@ -1,41 +1,23 @@
1
1
 
2
2
  ::Myco::Component.new([::Myco::FileToplevel], ::Myco.cscope.for_method_definition, __FILE__, __LINE__)
3
- .tap { |__c__| __c__.__last__ = __c__.component_eval {(::Myco.cscope.for_method_definition::BytecodeParser = ::Myco::Component.new([::Myco.find_constant(:BasicObject)], ::Myco.cscope.for_method_definition, __FILE__, __LINE__)
3
+ .tap { |__c__| __c__.__last__ = __c__.component_eval {(::Myco.find_constant(:Common).component_eval {(::Myco.cscope.for_method_definition::Parser = ::Myco::Component.new([::Myco.find_constant(:BasicObject)], ::Myco.cscope.for_method_definition, __FILE__, __LINE__)
4
4
  .tap { |__c__| __c__.__last__ = __c__.component_eval {(
5
5
  ::Myco.cscope.for_method_definition::State = ::Myco::Component.new([::Myco.find_constant(:BasicObject)], ::Myco.cscope.for_method_definition, __FILE__, __LINE__)
6
6
  .tap { |__c__| __c__.__last__ = __c__.component_eval {(
7
- declare_meme(:string, [[:var, []]], nil, ::Myco.cscope.dup) { |*| nil}
8
7
  declare_meme(:start_idx, [[:var, []]], nil, ::Myco.cscope.dup) { |*| nil}
9
8
  declare_meme(:end_idx, [[:var, []]], nil, ::Myco.cscope.dup) { |*| nil}
10
9
  declare_meme(:rule, [[:var, []]], nil, ::Myco.cscope.dup) { |*| nil}
11
10
  declare_meme(:result, [[:var, []]], nil, ::Myco.cscope.dup) { |*| nil}
12
11
  declare_meme(:error_idx, [[:var, []]], nil, ::Myco.cscope.dup) { |*| nil}
13
- declare_meme(:error_row, [[:var, []]], nil, ::Myco.cscope.dup) { |*| nil}
14
- declare_meme(:error_col, [[:var, []]], nil, ::Myco.cscope.dup) { |*| nil}
15
- declare_meme(:error_string, [[:var, []]], nil, ::Myco.cscope.dup) { |*| nil}
16
12
  declare_meme(:raise_error, [], nil, ::Myco.cscope.dup) { |*| (::Myco.branch_op(:"&&", self.error_idx) {self.raise(
17
13
  ::Myco.find_constant(:SyntaxError),
18
- "Unexpected character with parser: #{self.rule} near line: #{self.error_row}, column: #{self.error_col}.\n#{self.string.each_line.to_a.__send__(
19
- :[],
20
- self.error_row.__send__(
21
- :-,
22
- 1
23
- )
24
- )}#{" ".__send__(
25
- :*,
26
- [
27
- self.error_col.__send__(
28
- :-,
29
- 1
30
- ),
31
- 0
32
- ].max
33
- )}^"
14
+ "Syntax error with parser: #{self.rule} at index: #{self.error_idx}"
34
15
  )})}
35
16
  )}}
36
17
  .tap { |__c__| __c__.__name__ = :State }
18
+ declare_meme(:debug_mode, [[:var, []]], nil, ::Myco.cscope.dup) { |*| (false)}
37
19
  declare_meme(:grammar, [[:var, []]], nil, ::Myco.cscope.dup) { |*| (::Myco.find_constant(:Grammar).new)}
38
- declare_meme(:builder, [[:var, []]], nil, ::Myco.cscope.dup) { |*| (::Myco.find_constant(:Builder).new)}
20
+ declare_meme(:builder, [[:var, []]], nil, ::Myco.cscope.dup) { |*| (nil)}
39
21
  declare_meme(:new_worker, [], nil, ::Myco.cscope.dup) { |*| (self.set_up_worker(self.prototype.new))}
40
22
  declare_meme(:new_processor, [], nil, ::Myco.cscope.dup) { |*| (::Myco.find_constant(:Processor).new({:builder => self.builder}))}
41
23
  declare_meme(:prototype, [[:var, []]], nil, ::Myco.cscope.dup) { |*| (self.compile_prototype)}
@@ -54,20 +36,19 @@
54
36
  proto
55
37
  )}
56
38
  declare_meme(:compile_rule_into, [], nil, ::Myco.cscope.dup) { |proto, name, rule| (
57
- construct = rule.construct_rule
39
+ construct = rule.inner.construct
58
40
  ::Myco.find_constant(:Myco).add_dynamic_method(
59
41
  proto,
60
42
  name,
61
43
  "(compiled parser)"
62
44
  ) { |g| (
63
- instructor = ::Myco.find_constant(:BytecodeInstructions).new
64
- instructor.__send__(
65
- :g=,
66
- g
67
- )
68
45
  g.extend(::Myco.find_constant(:BytecodeHelpers))
46
+ g.__send__(
47
+ :debug_mode=,
48
+ self.debug_mode
49
+ )
69
50
  g.rule_start
70
- construct.bytecode(instructor)
51
+ construct.bytecode(g)
71
52
  g.rule_finish
72
53
  )}
73
54
  )}
@@ -165,18 +146,14 @@
165
146
  )}
166
147
  declare_meme(:captures_of_worker, [], nil, ::Myco.cscope.dup) { |worker| (worker.__get_ivar__(:@captures))}
167
148
  declare_meme(:highest_idx_of_worker, [], nil, ::Myco.cscope.dup) { |worker| (worker.__get_ivar__(:@highest_idx))}
149
+ declare_meme(:parse, [], nil, ::Myco.cscope.dup) { |*| (self.raise("The parse method is not implemented for #{self}"))}
168
150
  declare_meme(:parse, [], nil, ::Myco.cscope.dup) { |string, rule:"root", start_idx:0| (
169
151
  worker = self.new_worker
170
152
  processor = self.new_processor
171
153
  state = ::Myco.find_constant(:State).new({
172
154
  :string => string.to_s,
173
155
  :rule => rule.to_sym,
174
- :start_idx => start_idx.to_i,
175
- :error_idx => nil,
176
- :error_row => nil,
177
- :error_col => nil,
178
- :error_string => nil,
179
- :result => nil
156
+ :start_idx => start_idx.to_i
180
157
  })
181
158
  state.__send__(
182
159
  :end_idx=,
@@ -195,6 +172,10 @@
195
172
  :capture_items=,
196
173
  self.captures_of_worker(worker)
197
174
  )
175
+ ::Myco.branch_op(:"&&", (Rubinius::Type.object_respond_to?(self.grammar, :tokenizer).false? ? ::Myco::Void : self.grammar.tokenizer)) {processor.__send__(
176
+ :tokenizer=,
177
+ self.grammar.tokenizer
178
+ )}
198
179
  state.__send__(
199
180
  :result=,
200
181
  processor.process
@@ -220,4 +201,4 @@
220
201
  state
221
202
  )}
222
203
  )}}
223
- .tap { |__c__| __c__.__name__ = :BytecodeParser })}}.instance
204
+ .tap { |__c__| __c__.__name__ = :Parser })})}}.instance
@@ -0,0 +1,229 @@
1
+
2
+ Composite < EmptyObject {
3
+ Patterns < EmptyObject {
4
+ UnaryBase < Common::Patterns::UnaryBase { }
5
+ BinaryBase < Common::Patterns::BinaryBase { }
6
+
7
+ NegativePredicate < UnaryBase { construct_type: Constructions::NegativePredicate }
8
+ PositivePredicate < UnaryBase { construct_type: Constructions::PositivePredicate }
9
+ OneOrMore < UnaryBase { construct_type: Constructions::OneOrMore }
10
+ ZeroOrOne < UnaryBase { construct_type: Constructions::ZeroOrOne }
11
+ ZeroOrMore < UnaryBase { construct_type: Constructions::ZeroOrMore }
12
+ OrderedChoice < BinaryBase { construct_type: Constructions::OrderedChoice }
13
+ Concatenation < BinaryBase { construct_type: Constructions::Concatenation }
14
+ }
15
+
16
+ Constructions < EmptyObject {
17
+ UnaryBase < Common::Constructions::UnaryBase { }
18
+ BinaryBase < Common::Constructions::BinaryBase { }
19
+
20
+ NegativePredicate < UnaryBase { }
21
+ PositivePredicate < UnaryBase { }
22
+ OneOrMore < UnaryBase { var inlaid }
23
+ ZeroOrOne < UnaryBase { }
24
+ ZeroOrMore < UnaryBase { var inlaid }
25
+ OrderedChoice < BinaryBase { }
26
+ Concatenation < BinaryBase { }
27
+ }
28
+
29
+ Patterns << {
30
+ NegativePredicate << {
31
+ # Invert the polarity of the predicate instead of nesting the predicate
32
+ "!": PositivePredicate.new(inner:inner)
33
+ }
34
+
35
+ PositivePredicate << {
36
+ # Invert the polarity of the predicate instead of nesting the predicate
37
+ "!": NegativePredicate.new(inner:inner)
38
+ }
39
+
40
+ OrderedChoice << {
41
+ # Build a right-associative tree if the first operand of another "/"
42
+ "/": |other|
43
+ private.binary_right_assoc(self, other, OrderedChoice)
44
+ }
45
+
46
+ Concatenation << {
47
+ # Build a right-associative tree if the first operand of another "+"
48
+ "+": |other=false|
49
+ other
50
+ &? private.binary_right_assoc(self, other, Concatenation)
51
+ ?? OneOrMore.new(inner:self)
52
+ }
53
+ }
54
+
55
+ Constructions << {
56
+ # Negative matching predicate that consumes no input.
57
+ NegativePredicate << { bytecode: |g| {
58
+ local_fail = g.new_label
59
+ old_fail = g.overall_fail
60
+ g.overall_fail = local_fail
61
+
62
+ # Store index and captures for backtracking
63
+ if(inner.bytecode_can_capture?) { g.push_temp_captures }
64
+ g.push_idx
65
+
66
+ inner.bytecode(g)
67
+
68
+ # Success => Failure, backtrack index and captures
69
+ g.pop_to_set_idx
70
+ if(inner.bytecode_can_capture?) { g.pop_to_reject_captures }
71
+ g.overall_fail = old_fail # reset fail
72
+ g.goto(g.overall_fail)
73
+
74
+ # Failure => Success, backtrack index and cannot keep captures either (incomplete)
75
+ local_fail.set!
76
+ g.pop_to_set_idx
77
+ if(inner.bytecode_can_capture?) { g.pop_to_reject_captures }
78
+ g.overall_fail = old_fail
79
+ }}
80
+
81
+ # Positive matching predicate that consumes no input.
82
+ PositivePredicate << { bytecode: |g| {
83
+ local_done = g.new_label
84
+ local_fail = g.new_label
85
+ old_fail = g.overall_fail
86
+ g.overall_fail = local_fail
87
+
88
+ # Store index and captures for backtracking
89
+ if(inner.bytecode_can_capture?) { g.push_temp_captures }
90
+ g.push_idx
91
+
92
+ inner.bytecode(g)
93
+
94
+ # Success, but do not consume input, so backtrack index but keep captures
95
+ g.pop_to_set_idx
96
+ if(inner.bytecode_can_capture?) { g.pop_to_accept_captures }
97
+ g.overall_fail = old_fail # reset fail
98
+ g.goto(local_done)
99
+
100
+ # Failure, backtrack index and captures
101
+ local_fail.set!
102
+ g.pop_to_set_idx
103
+ if(inner.bytecode_can_capture?) { g.pop_to_reject_captures }
104
+ g.overall_fail = old_fail
105
+ g.goto(g.overall_fail)
106
+
107
+ local_done.set!
108
+ }}
109
+
110
+ # Keep consuming |inner| until it doesn't match; it must match at least one.
111
+ OneOrMore << { bytecode: |g| {
112
+ local_retry = g.new_label
113
+ local_fail = g.new_label
114
+ old_fail = g.overall_fail
115
+ g.overall_fail = local_fail
116
+ # push a false to indicate that no matches have occurred yet
117
+ g.push_false
118
+
119
+ local_retry.set!
120
+
121
+ # Store captures for restoration
122
+ if(inner.bytecode_can_capture?) { g.push_temp_captures }
123
+
124
+ inner.bytecode(g); inlaid.?call
125
+
126
+ # Success, accept captures and try again, popping the last boolean
127
+ # to push a true to indicate at least one match was made.
128
+ if(inner.bytecode_can_capture?) { g.pop_to_accept_captures }
129
+ g.pop; g.push_true
130
+ g.goto(local_retry)
131
+
132
+ # Failure, reject captures and continue
133
+ local_fail.set!
134
+ if(inner.bytecode_can_capture?) { g.pop_to_reject_captures }
135
+ g.overall_fail = old_fail # reset fail
136
+
137
+ # If at least one match was not found, it is an overall failure
138
+ g.goto_if_false(g.overall_fail)
139
+ }}
140
+
141
+ # Optionally match and capture from inner, or still succeed if not.
142
+ ZeroOrOne << { bytecode: |g| {
143
+ local_done = g.new_label
144
+ local_fail = g.new_label
145
+ old_fail = g.overall_fail
146
+ g.overall_fail = local_fail
147
+
148
+ # Store index and captures for backtracking in case of failure
149
+ if(inner.bytecode_can_capture?) { g.push_temp_captures }
150
+ g.push_idx
151
+
152
+ inner.bytecode(g)
153
+
154
+ # Success, throw away backtrack entry
155
+ g.pop # keep idx
156
+ if(inner.bytecode_can_capture?) { g.pop_to_accept_captures }
157
+ g.overall_fail = old_fail # reset fail
158
+ g.goto(local_done)
159
+
160
+ # Failure, backtrack index and captures
161
+ local_fail.set!
162
+ g.pop_to_set_idx
163
+ if(inner.bytecode_can_capture?) { g.pop_to_reject_captures }
164
+ g.overall_fail = old_fail
165
+
166
+ local_done.set!
167
+ }}
168
+
169
+ # Keep consuming |inner| until it doesn't match; it will not cause backtrack.
170
+ ZeroOrMore << { bytecode: |g| {
171
+ local_retry = g.new_label
172
+ local_fail = g.new_label
173
+ old_fail = g.overall_fail
174
+ g.overall_fail = local_fail
175
+
176
+ local_retry.set!
177
+
178
+ # Store captures for restoration
179
+ if(inner.bytecode_can_capture?) { g.push_temp_captures }
180
+
181
+ inner.bytecode(g); inlaid.?call
182
+
183
+ # Success, accept captures and try again
184
+ if(inner.bytecode_can_capture?) { g.pop_to_accept_captures }
185
+ g.goto(local_retry)
186
+
187
+ # Failure, reject captures and continue
188
+ local_fail.set!
189
+ if(inner.bytecode_can_capture?) { g.pop_to_reject_captures }
190
+ g.overall_fail = old_fail # reset fail
191
+ }}
192
+
193
+ # An ordered choice between first and second that matches when one succeeds.
194
+ OrderedChoice << { bytecode: |g| {
195
+ local_done = g.new_label
196
+ local_fail = g.new_label
197
+ old_fail = g.overall_fail
198
+ g.overall_fail = local_fail
199
+
200
+ # Store index and captures for backtracking in case of failure
201
+ if(first.bytecode_can_capture?) { g.push_temp_captures }
202
+ g.push_idx
203
+
204
+ first.bytecode(g)
205
+
206
+ # Success, throw away backtrack entry
207
+ g.pop # keep idx
208
+ if(first.bytecode_can_capture?) { g.pop_to_accept_captures }
209
+ g.overall_fail = old_fail # reset fail
210
+ g.goto(local_done)
211
+
212
+ # Failure, backtrack index and captures
213
+ local_fail.set!
214
+ g.pop_to_set_idx
215
+ if(first.bytecode_can_capture?) { g.pop_to_reject_captures }
216
+ g.overall_fail = old_fail
217
+
218
+ second.bytecode(g)
219
+
220
+ local_done.set!
221
+ }}
222
+
223
+ # Match the first item followed by the second.
224
+ Concatenation << { bytecode: |g| {
225
+ first.bytecode(g)
226
+ second.bytecode(g)
227
+ }}
228
+ }
229
+ }