myco 0.1.4 → 0.1.5
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.
- checksums.yaml +4 -4
- data/lib/myco/bootstrap/find_constant.rb +4 -11
- data/lib/myco/code_loader.rb +2 -1
- data/lib/myco/code_tools/AST/ConstantAccess.my +47 -3
- data/lib/myco/code_tools/AST/ConstantAccess.my.rb +13 -9
- data/lib/myco/code_tools/AST/ConstantAssignment.my +1 -5
- data/lib/myco/code_tools/AST/ConstantAssignment.my.rb +3 -9
- data/lib/myco/code_tools/AST/ToRuby.my +5 -2
- data/lib/myco/code_tools/AST/ToRuby.my.rb +7 -3
- data/lib/myco/code_tools/AST.my +1 -0
- data/lib/myco/code_tools/AST.my.rb +9 -1
- data/lib/myco/code_tools/Parser.my +24 -0
- data/lib/myco/code_tools/Parser.my.rb +25 -0
- data/lib/myco/code_tools/parser/MycoBuilder.my +67 -0
- data/lib/myco/code_tools/parser/MycoBuilder.my.rb +99 -0
- data/lib/myco/code_tools/parser/MycoCharacterClasses.my +20 -0
- data/lib/myco/code_tools/parser/MycoCharacterClasses.my.rb +56 -0
- data/lib/myco/code_tools/parser/MycoGrammar.my +564 -0
- data/lib/myco/code_tools/parser/MycoGrammar.my.rb +1851 -0
- data/lib/myco/code_tools/parser/MycoTokens.my +78 -0
- data/lib/myco/code_tools/parser/MycoTokens.my.rb +170 -0
- data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/Builder.my +4 -0
- data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/Builder.my.rb +5 -0
- data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/BytecodeHelpers.my +142 -0
- data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/BytecodeHelpers.my.rb +181 -0
- data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/BytecodeInstructions.my +420 -0
- data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/BytecodeInstructions.my.rb +415 -0
- data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/BytecodeParser.my +137 -0
- data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/BytecodeParser.my.rb +237 -0
- data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/Constructions.my +183 -0
- data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/Constructions.my.rb +370 -0
- data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/Grammar.my +65 -0
- data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/Grammar.my.rb +83 -0
- data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/Instructions.my +139 -0
- data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/Instructions.my.rb +284 -0
- data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/Machine.my +37 -0
- data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/Machine.my.rb +24 -0
- data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/Parser.my +42 -0
- data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/Parser.my.rb +52 -0
- data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/Patterns.my +123 -0
- data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/Patterns.my.rb +164 -0
- data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/Processor.my +236 -0
- data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/Processor.my.rb +339 -0
- data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces.my +15 -0
- data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces.my.rb +14 -0
- data/lib/myco/code_tools.rb +1 -1
- data/lib/myco/version.rb +1 -1
- data/lib/myco.rb +2 -0
- metadata +44 -25
- data/lib/myco/code_tools/parser/peg_parser.rb +0 -7182
- data/lib/myco/code_tools/parser.rb +0 -39
@@ -0,0 +1,164 @@
|
|
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.const_set(:Patterns, ::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.const_set(:Base, ::Myco::Component.new([::Myco.find_constant(:BasicObject)], ::Myco.cscope.for_method_definition, __FILE__, __LINE__)
|
6
|
+
.tap { |__c__| __c__.__last__ = __c__.component_eval {(declare_meme(:name, [[:var, []]], nil, ::Myco.cscope.dup) { |*| (self.parent_meme.name)})}})
|
7
|
+
.tap { |__c__| __c__.__name__ = :Base }
|
8
|
+
::Myco.cscope.for_method_definition.const_set(:UnaryBase, ::Myco::Component.new([::Myco.find_constant(:Base)], ::Myco.cscope.for_method_definition, __FILE__, __LINE__)
|
9
|
+
.tap { |__c__| __c__.__last__ = __c__.component_eval {(declare_meme(:inner, [[:var, []]], nil, ::Myco.cscope.dup) { |*| nil})}})
|
10
|
+
.tap { |__c__| __c__.__name__ = :UnaryBase }
|
11
|
+
::Myco.cscope.for_method_definition.const_set(:BinaryBase, ::Myco::Component.new([::Myco.find_constant(:Base)], ::Myco.cscope.for_method_definition, __FILE__, __LINE__)
|
12
|
+
.tap { |__c__| __c__.__last__ = __c__.component_eval {(
|
13
|
+
declare_meme(:first, [[:var, []]], nil, ::Myco.cscope.dup) { |*| nil}
|
14
|
+
declare_meme(:second, [[:var, []]], nil, ::Myco.cscope.dup) { |*| nil}
|
15
|
+
)}})
|
16
|
+
.tap { |__c__| __c__.__name__ = :BinaryBase }
|
17
|
+
::Myco.cscope.for_method_definition.const_set(:AnyCharacter, ::Myco::Component.new([::Myco.find_constant(:Base)], ::Myco.cscope.for_method_definition, __FILE__, __LINE__)
|
18
|
+
.tap { |__c__| __c__.__last__ = __c__.component_eval {nil}})
|
19
|
+
.tap { |__c__| __c__.__name__ = :AnyCharacter }
|
20
|
+
::Myco.cscope.for_method_definition.const_set(:Character, ::Myco::Component.new([::Myco.find_constant(:Base)], ::Myco.cscope.for_method_definition, __FILE__, __LINE__)
|
21
|
+
.tap { |__c__| __c__.__last__ = __c__.component_eval {(declare_meme(:code, [[:var, []]], nil, ::Myco.cscope.dup) { |*| nil})}})
|
22
|
+
.tap { |__c__| __c__.__name__ = :Character }
|
23
|
+
::Myco.cscope.for_method_definition.const_set(:CharacterString, ::Myco::Component.new([::Myco.find_constant(:Base)], ::Myco.cscope.for_method_definition, __FILE__, __LINE__)
|
24
|
+
.tap { |__c__| __c__.__last__ = __c__.component_eval {(declare_meme(:codes, [[:var, []]], nil, ::Myco.cscope.dup) { |*| nil})}})
|
25
|
+
.tap { |__c__| __c__.__name__ = :CharacterString }
|
26
|
+
::Myco.cscope.for_method_definition.const_set(:CharacterSet, ::Myco::Component.new([::Myco.find_constant(:Base)], ::Myco.cscope.for_method_definition, __FILE__, __LINE__)
|
27
|
+
.tap { |__c__| __c__.__last__ = __c__.component_eval {(declare_meme(:codes, [[:var, []]], nil, ::Myco.cscope.dup) { |*| nil})}})
|
28
|
+
.tap { |__c__| __c__.__name__ = :CharacterSet }
|
29
|
+
::Myco.cscope.for_method_definition.const_set(:CharacterRange, ::Myco::Component.new([::Myco.find_constant(:Base)], ::Myco.cscope.for_method_definition, __FILE__, __LINE__)
|
30
|
+
.tap { |__c__| __c__.__last__ = __c__.component_eval {(
|
31
|
+
declare_meme(:start, [[:var, []]], nil, ::Myco.cscope.dup) { |*| nil}
|
32
|
+
declare_meme(:stop, [[:var, []]], nil, ::Myco.cscope.dup) { |*| nil}
|
33
|
+
)}})
|
34
|
+
.tap { |__c__| __c__.__name__ = :CharacterRange }
|
35
|
+
::Myco.cscope.for_method_definition.const_set(:NegativePredicate, ::Myco::Component.new([::Myco.find_constant(:UnaryBase)], ::Myco.cscope.for_method_definition, __FILE__, __LINE__)
|
36
|
+
.tap { |__c__| __c__.__last__ = __c__.component_eval {nil}})
|
37
|
+
.tap { |__c__| __c__.__name__ = :NegativePredicate }
|
38
|
+
::Myco.cscope.for_method_definition.const_set(:PositivePredicate, ::Myco::Component.new([::Myco.find_constant(:UnaryBase)], ::Myco.cscope.for_method_definition, __FILE__, __LINE__)
|
39
|
+
.tap { |__c__| __c__.__last__ = __c__.component_eval {nil}})
|
40
|
+
.tap { |__c__| __c__.__name__ = :PositivePredicate }
|
41
|
+
::Myco.cscope.for_method_definition.const_set(:OneOrMore, ::Myco::Component.new([::Myco.find_constant(:UnaryBase)], ::Myco.cscope.for_method_definition, __FILE__, __LINE__)
|
42
|
+
.tap { |__c__| __c__.__last__ = __c__.component_eval {nil}})
|
43
|
+
.tap { |__c__| __c__.__name__ = :OneOrMore }
|
44
|
+
::Myco.cscope.for_method_definition.const_set(:ZeroOrOne, ::Myco::Component.new([::Myco.find_constant(:UnaryBase)], ::Myco.cscope.for_method_definition, __FILE__, __LINE__)
|
45
|
+
.tap { |__c__| __c__.__last__ = __c__.component_eval {nil}})
|
46
|
+
.tap { |__c__| __c__.__name__ = :ZeroOrOne }
|
47
|
+
::Myco.cscope.for_method_definition.const_set(:ZeroOrMore, ::Myco::Component.new([::Myco.find_constant(:UnaryBase)], ::Myco.cscope.for_method_definition, __FILE__, __LINE__)
|
48
|
+
.tap { |__c__| __c__.__last__ = __c__.component_eval {nil}})
|
49
|
+
.tap { |__c__| __c__.__name__ = :ZeroOrMore }
|
50
|
+
::Myco.cscope.for_method_definition.const_set(:OrderedChoice, ::Myco::Component.new([::Myco.find_constant(:BinaryBase)], ::Myco.cscope.for_method_definition, __FILE__, __LINE__)
|
51
|
+
.tap { |__c__| __c__.__last__ = __c__.component_eval {nil}})
|
52
|
+
.tap { |__c__| __c__.__name__ = :OrderedChoice }
|
53
|
+
::Myco.cscope.for_method_definition.const_set(:Concatenation, ::Myco::Component.new([::Myco.find_constant(:BinaryBase)], ::Myco.cscope.for_method_definition, __FILE__, __LINE__)
|
54
|
+
.tap { |__c__| __c__.__last__ = __c__.component_eval {nil}})
|
55
|
+
.tap { |__c__| __c__.__name__ = :Concatenation }
|
56
|
+
::Myco.cscope.for_method_definition.const_set(:NamedCapture, ::Myco::Component.new([::Myco.find_constant(:UnaryBase)], ::Myco.cscope.for_method_definition, __FILE__, __LINE__)
|
57
|
+
.tap { |__c__| __c__.__last__ = __c__.component_eval {nil}})
|
58
|
+
.tap { |__c__| __c__.__name__ = :NamedCapture }
|
59
|
+
::Myco.cscope.for_method_definition.const_set(:NamedTextCapture, ::Myco::Component.new([::Myco.find_constant(:UnaryBase)], ::Myco.cscope.for_method_definition, __FILE__, __LINE__)
|
60
|
+
.tap { |__c__| __c__.__last__ = __c__.component_eval {nil}})
|
61
|
+
.tap { |__c__| __c__.__name__ = :NamedTextCapture }
|
62
|
+
::Myco.cscope.for_method_definition.const_set(:NamedTokenCapture, ::Myco::Component.new([::Myco.find_constant(:UnaryBase)], ::Myco.cscope.for_method_definition, __FILE__, __LINE__)
|
63
|
+
.tap { |__c__| __c__.__last__ = __c__.component_eval {nil}})
|
64
|
+
.tap { |__c__| __c__.__name__ = :NamedTokenCapture }
|
65
|
+
::Myco.cscope.for_method_definition.const_set(:Reduction, ::Myco::Component.new([::Myco.find_constant(:UnaryBase)], ::Myco.cscope.for_method_definition, __FILE__, __LINE__)
|
66
|
+
.tap { |__c__| __c__.__last__ = __c__.component_eval {(
|
67
|
+
declare_meme(:block, [[:var, []]], nil, ::Myco.cscope.dup) { |*| nil}
|
68
|
+
declare_meme(:args, [[:var, []]], nil, ::Myco.cscope.dup) { |*| ([])}
|
69
|
+
)}})
|
70
|
+
.tap { |__c__| __c__.__name__ = :Reduction }
|
71
|
+
::Myco.cscope.for_method_definition.const_set(:ShorthandMethods, ::Myco::Component.new([::Myco.find_constant(:EmptyObject)], ::Myco.cscope.for_method_definition, __FILE__, __LINE__)
|
72
|
+
.tap { |__c__| __c__.__last__ = __c__.component_eval {(
|
73
|
+
declare_meme(:any, [], nil, ::Myco.cscope.dup) { |*| (::Myco.find_constant(:AnyCharacter).new)}
|
74
|
+
declare_meme(:char, [], nil, ::Myco.cscope.dup) { |character| (::Myco.find_constant(:Character).new({:code => character.ord}))}
|
75
|
+
declare_meme(:str, [], nil, ::Myco.cscope.dup) { |string| (::Myco.find_constant(:CharacterString).new({:codes => string.each_char.map(&:ord)}))}
|
76
|
+
declare_meme(:set, [], nil, ::Myco.cscope.dup) { |string| (::Myco.find_constant(:CharacterSet).new({:codes => string.each_char.map(&:ord)}))}
|
77
|
+
declare_meme(:range, [], nil, ::Myco.cscope.dup) { |start, stop| (::Myco.find_constant(:CharacterRange).new({
|
78
|
+
:start => start.ord,
|
79
|
+
:stop => stop.ord
|
80
|
+
}))}
|
81
|
+
declare_meme(:r, [], nil, ::Myco.cscope.dup) { |pattern, &block| (::Myco.find_constant(:Reduction).new({
|
82
|
+
:inner => pattern,
|
83
|
+
:block => block
|
84
|
+
}))}
|
85
|
+
)}})
|
86
|
+
.tap { |__c__| __c__.__name__ = :ShorthandMethods }
|
87
|
+
::Myco.find_constant(:Base).component_eval {(
|
88
|
+
declare_meme(:!, [], nil, ::Myco.cscope.dup) { |*| (::Myco.find_constant(:NegativePredicate).new({:inner => self}))}
|
89
|
+
declare_meme(:/, [], nil, ::Myco.cscope.dup) { |other| (::Myco.find_constant(:OrderedChoice).new({
|
90
|
+
:first => self,
|
91
|
+
:second => other
|
92
|
+
}))}
|
93
|
+
declare_meme(:+, [], nil, ::Myco.cscope.dup) { |other=false| (::Myco.branch_op(:"??", ::Myco.branch_op(:"&?", other) {::Myco.find_constant(:Concatenation).new({
|
94
|
+
:first => self,
|
95
|
+
:second => other
|
96
|
+
})}) {::Myco.find_constant(:OneOrMore).new({:inner => self})})}
|
97
|
+
declare_meme(:-, [], nil, ::Myco.cscope.dup) { |other=false| (::Myco.branch_op(:"??", ::Myco.branch_op(:"&?", other) {::Myco.find_constant(:ErrorCondition).new}) {::Myco.find_constant(:ZeroOrOne).new({:inner => self})})}
|
98
|
+
declare_meme(:*, [], nil, ::Myco.cscope.dup) { |other=false| (::Myco.branch_op(:"??", ::Myco.branch_op(:"&?", other) {::Myco.find_constant(:ErrorCondition).new}) {::Myco.find_constant(:ZeroOrMore).new({:inner => self})})}
|
99
|
+
declare_meme(:[], [], nil, ::Myco.cscope.dup) { |name| (::Myco.find_constant(:NamedCapture).new({
|
100
|
+
:inner => self,
|
101
|
+
:name => name
|
102
|
+
}))}
|
103
|
+
declare_meme(:text, [], nil, ::Myco.cscope.dup) { |name=:text| (::Myco.find_constant(:NamedTextCapture).new({
|
104
|
+
:inner => self,
|
105
|
+
:name => name
|
106
|
+
}))}
|
107
|
+
declare_meme(:token, [], nil, ::Myco.cscope.dup) { |name| (::Myco.find_constant(:NamedTokenCapture).new({
|
108
|
+
:inner => self,
|
109
|
+
:name => name
|
110
|
+
}))}
|
111
|
+
__category__(:private).component_eval {(declare_meme(:binary_right_assoc, [], nil, ::Myco.cscope.dup) { |orig, other, type| (
|
112
|
+
cursor = orig
|
113
|
+
self.loop { || (
|
114
|
+
self.__send__(
|
115
|
+
:unless,
|
116
|
+
cursor.second.__send__(
|
117
|
+
:is_a?,
|
118
|
+
type
|
119
|
+
)
|
120
|
+
) { || (self.__send__(:break))}
|
121
|
+
cursor = cursor.second
|
122
|
+
)}
|
123
|
+
cursor.__send__(
|
124
|
+
:second=,
|
125
|
+
type.new({
|
126
|
+
:first => cursor.second,
|
127
|
+
:second => other
|
128
|
+
})
|
129
|
+
)
|
130
|
+
orig
|
131
|
+
)})}
|
132
|
+
)}
|
133
|
+
::Myco.find_constant(:NegativePredicate).component_eval {(declare_meme(:!, [], nil, ::Myco.cscope.dup) { |*| (::Myco.find_constant(:PositivePredicate).new({:inner => self.inner}))})}
|
134
|
+
::Myco.find_constant(:PositivePredicate).component_eval {(declare_meme(:!, [], nil, ::Myco.cscope.dup) { |*| (::Myco.find_constant(:NegativePredicate).new({:inner => self.inner}))})}
|
135
|
+
::Myco.find_constant(:OrderedChoice).component_eval {(declare_meme(:/, [], nil, ::Myco.cscope.dup) { |other| (self.private.binary_right_assoc(
|
136
|
+
self,
|
137
|
+
other,
|
138
|
+
::Myco.find_constant(:OrderedChoice)
|
139
|
+
))})}
|
140
|
+
::Myco.find_constant(:Concatenation).component_eval {(declare_meme(:+, [], nil, ::Myco.cscope.dup) { |other=false| (::Myco.branch_op(:"??", ::Myco.branch_op(:"&?", other) {self.private.binary_right_assoc(
|
141
|
+
self,
|
142
|
+
other,
|
143
|
+
::Myco.find_constant(:Concatenation)
|
144
|
+
)}) {::Myco.find_constant(:OneOrMore).new({:inner => self})})})}
|
145
|
+
::Myco.find_constant(:Reduction).component_eval {(
|
146
|
+
::Myco.cscope.for_method_definition.const_set(:Environment, ::Myco::Component.new([
|
147
|
+
::Myco.find_constant(:EmptyObject),
|
148
|
+
::Myco.find_constant(:BasicDecorators)
|
149
|
+
], ::Myco.cscope.for_method_definition, __FILE__, __LINE__)
|
150
|
+
.tap { |__c__| __c__.__last__ = __c__.component_eval {(
|
151
|
+
declare_meme(:captures, [[:var, []]], nil, ::Myco.cscope.dup) { |*| nil}
|
152
|
+
declare_meme(:builder, [[:var, []]], nil, ::Myco.cscope.dup) { |*| nil}
|
153
|
+
declare_meme(:method_missing, [], nil, ::Myco.cscope.dup) { |name, *args, &block| (self.captures.fetch(name) { || (self.builder.send(
|
154
|
+
name,
|
155
|
+
*args,
|
156
|
+
&block
|
157
|
+
))})}
|
158
|
+
declare_meme(:!, [], nil, ::Myco.cscope.dup) { |*| (nil)}
|
159
|
+
)}})
|
160
|
+
.tap { |__c__| __c__.__name__ = :Environment }
|
161
|
+
declare_meme(:code, [], nil, ::Myco.cscope.dup) { |*| (self.block.block.compiled_code)}
|
162
|
+
)}
|
163
|
+
)}})
|
164
|
+
.tap { |__c__| __c__.__name__ = :Patterns })}}.instance
|
@@ -0,0 +1,236 @@
|
|
1
|
+
|
2
|
+
Processor < BasicObject {
|
3
|
+
var string: "" # The source string to be processed
|
4
|
+
var capture_items: [] # The stream of capture tokens to be processed
|
5
|
+
var builder: null # The AST Builder to use in the reduction environment
|
6
|
+
|
7
|
+
# Process the inputs and return the final captures layer
|
8
|
+
process: setup; process_each; validate_state; final_captures
|
9
|
+
|
10
|
+
# A lightweight class used for string captures in the reduction environment
|
11
|
+
Token < BasicObject {
|
12
|
+
var type
|
13
|
+
var text
|
14
|
+
var row
|
15
|
+
var col
|
16
|
+
|
17
|
+
inspect: [type, text, row, col].inspect
|
18
|
+
to_s: [type, text, row, col].inspect
|
19
|
+
|
20
|
+
line: row # alias
|
21
|
+
|
22
|
+
sym: text.to_sym
|
23
|
+
float: text.to_f
|
24
|
+
integer: |base=0| text.to_inum(base, true)
|
25
|
+
}
|
26
|
+
|
27
|
+
# The environment for performing reduction actions to build an AST in the PEG.
|
28
|
+
# It gives implicit access to both local captures and AST builder methods.
|
29
|
+
var reduction_env:
|
30
|
+
Patterns::Reduction::Environment { }
|
31
|
+
var reduction_env_cscope:
|
32
|
+
::Rubinius::ConstantScope.new(Patterns::Reduction::Environment) # TODO: fix
|
33
|
+
|
34
|
+
var cidx_stack: [] # A FILO stack of start indices for captures
|
35
|
+
var sidx_stack: [] # A FILO stack of start indices for string captures
|
36
|
+
var tidx_stack: [] # A FILO stack of start indices for token captures
|
37
|
+
var midx_stack: [] # A FILO stack of start indices for multiplicit captures
|
38
|
+
var ridx_stack: [] # A FILO stack of start indices for reductions
|
39
|
+
var capt_stack: [] # A FILO stack of Hashes with capture names, values
|
40
|
+
|
41
|
+
# Given a string, return a map of indices of newline positions to line numbers
|
42
|
+
memoize line_map_for: |string| {
|
43
|
+
idx_hash = ::Hash.new
|
44
|
+
idx_hash[0] = 0
|
45
|
+
count = 0
|
46
|
+
idx = 0
|
47
|
+
loop {
|
48
|
+
idx = string.index("\n", idx + 1)
|
49
|
+
idx || break
|
50
|
+
count = count + 1
|
51
|
+
idx_hash[idx] = count
|
52
|
+
}
|
53
|
+
idx_hash
|
54
|
+
}
|
55
|
+
|
56
|
+
# Given an index and string, return the row (line) and column numbers
|
57
|
+
position_of: |idx, string| {
|
58
|
+
nl_idx = string.rindex("\n", idx) || 0
|
59
|
+
row = line_map_for(string).fetch(nl_idx) + 1
|
60
|
+
col = idx - nl_idx
|
61
|
+
[row, col]
|
62
|
+
}
|
63
|
+
|
64
|
+
# Push or pop a layer to/from the capture stack
|
65
|
+
push_layer: capt_stack.push(::Hash.new)
|
66
|
+
pop_layer: capt_stack.pop
|
67
|
+
|
68
|
+
setup:
|
69
|
+
push_layer
|
70
|
+
|
71
|
+
final_captures:
|
72
|
+
pop_layer
|
73
|
+
.select |k,v| { k.is_a?(::Symbol) }
|
74
|
+
.map |k,v| { [k,v.last] }
|
75
|
+
.to_h
|
76
|
+
|
77
|
+
process_each: capture_items.each |idx, metadata| {
|
78
|
+
type = metadata[0]
|
79
|
+
captargs = metadata[1] || []
|
80
|
+
send(type, idx, *captargs)
|
81
|
+
}
|
82
|
+
|
83
|
+
validate_state: {
|
84
|
+
cidx_stack.empty? || raise("unbalanced cidx_stack: "cidx_stack"")
|
85
|
+
sidx_stack.empty? || raise("unbalanced sidx_stack: "sidx_stack"")
|
86
|
+
tidx_stack.empty? || raise("unbalanced tidx_stack: "tidx_stack"")
|
87
|
+
midx_stack.empty? || raise("unbalanced midx_stack: "midx_stack"")
|
88
|
+
ridx_stack.empty? || raise("unbalanced ridx_stack: "ridx_stack"")
|
89
|
+
}
|
90
|
+
|
91
|
+
# Start of a named capture
|
92
|
+
c_start: |idx| {
|
93
|
+
# Note the starting index of the capture
|
94
|
+
cidx_stack.push(idx)
|
95
|
+
}
|
96
|
+
|
97
|
+
# End of a named capture
|
98
|
+
c_end: |idx, name| {
|
99
|
+
captures = capt_stack.last
|
100
|
+
start_idx = cidx_stack.pop
|
101
|
+
|
102
|
+
# Pick up the captured reduction, if its start and end
|
103
|
+
# indices are within the bounds we are looking for.
|
104
|
+
use_reduction = false
|
105
|
+
value = captures[idx]
|
106
|
+
value &? (
|
107
|
+
loc = value.first
|
108
|
+
value = value.last
|
109
|
+
((loc.first>=start_idx) && (loc.last<=idx)) &? (
|
110
|
+
use_reduction = true
|
111
|
+
) ?? (
|
112
|
+
value = null
|
113
|
+
)
|
114
|
+
)
|
115
|
+
|
116
|
+
# If the reduction is not found and the string length is not zero
|
117
|
+
# slice the string with the given indices to get a text value.
|
118
|
+
!use_reduction && !(start_idx==idx) && (
|
119
|
+
value = string.slice(start_idx, idx-start_idx)
|
120
|
+
)
|
121
|
+
|
122
|
+
store_value = [[start_idx, idx], value]
|
123
|
+
captures.store(idx, store_value)
|
124
|
+
captures.store(name, store_value)
|
125
|
+
}
|
126
|
+
|
127
|
+
# Start of a named text capture
|
128
|
+
s_start: |idx| {
|
129
|
+
# Note the starting index of the text capture
|
130
|
+
sidx_stack.push(idx)
|
131
|
+
}
|
132
|
+
|
133
|
+
# End of a named text capture
|
134
|
+
s_end: |idx, name| {
|
135
|
+
captures = capt_stack.last
|
136
|
+
start_idx = sidx_stack.pop
|
137
|
+
|
138
|
+
value = string.slice(start_idx, idx-start_idx)
|
139
|
+
store_value = [[start_idx, idx], value]
|
140
|
+
captures.store(idx, store_value)
|
141
|
+
captures.store(name, store_value)
|
142
|
+
}
|
143
|
+
|
144
|
+
# Start of a named token capture
|
145
|
+
t_start: |idx| {
|
146
|
+
# Note the starting index of the text capture
|
147
|
+
tidx_stack.push(idx)
|
148
|
+
}
|
149
|
+
|
150
|
+
# End of a named token capture
|
151
|
+
t_end: |idx, name| {
|
152
|
+
captures = capt_stack.last
|
153
|
+
start_idx = tidx_stack.pop
|
154
|
+
pos = position_of(start_idx, string)
|
155
|
+
|
156
|
+
value = Token.new(
|
157
|
+
type: name
|
158
|
+
text: string.slice(start_idx, idx - start_idx)
|
159
|
+
row: pos.first
|
160
|
+
col: pos.last
|
161
|
+
)
|
162
|
+
store_value = [[start_idx, idx], value]
|
163
|
+
captures.store(idx, store_value)
|
164
|
+
captures.store(name, store_value)
|
165
|
+
}
|
166
|
+
|
167
|
+
# Start of a multiplicit capture
|
168
|
+
m_start: |idx| {
|
169
|
+
midx_stack.push(idx)
|
170
|
+
c_start(idx)
|
171
|
+
}
|
172
|
+
|
173
|
+
# Split of a multiplicit capture
|
174
|
+
m_split: |idx, name| {
|
175
|
+
c_end(idx, name)
|
176
|
+
c_start(idx)
|
177
|
+
}
|
178
|
+
|
179
|
+
# End of a multiplicit capture
|
180
|
+
m_end: |idx, name| {
|
181
|
+
captures = capt_stack.last
|
182
|
+
start_idx = midx_stack.pop
|
183
|
+
cidx_stack.pop # Discard cidx pushed by m_start/end calling c_start
|
184
|
+
|
185
|
+
# Try to find a group of "anonymous" captures by index first
|
186
|
+
value = []
|
187
|
+
captures.each |k,v| {
|
188
|
+
(k.is_a?(::Fixnum) && k<=idx && k>start_idx) && (
|
189
|
+
loc = v.first
|
190
|
+
(loc.first>=start_idx) && (
|
191
|
+
value.push(v.last)
|
192
|
+
)
|
193
|
+
)
|
194
|
+
}
|
195
|
+
|
196
|
+
# If the group is empty and the string length is not zero
|
197
|
+
# slice the string with the given indices to get a text value
|
198
|
+
(value.empty? && !(start_idx==idx)) && (
|
199
|
+
value = string.slice(start_idx, idx-start_idx)
|
200
|
+
)
|
201
|
+
|
202
|
+
store_value = [[start_idx, idx], value]
|
203
|
+
captures.store(idx, store_value)
|
204
|
+
captures.store(name, store_value)
|
205
|
+
}
|
206
|
+
|
207
|
+
# Start of a reduction
|
208
|
+
r_start: |idx| (
|
209
|
+
# Push a new layer of reduction context onto the stack
|
210
|
+
push_layer
|
211
|
+
ridx_stack.push(idx)
|
212
|
+
)
|
213
|
+
|
214
|
+
# End of a reduction
|
215
|
+
r_end: |idx, code, *args| {
|
216
|
+
captures = pop_layer
|
217
|
+
start_idx = ridx_stack.pop
|
218
|
+
|
219
|
+
# Set up the reduction environment
|
220
|
+
code.scope = reduction_env_cscope
|
221
|
+
reduction_env.builder = builder
|
222
|
+
reduction_env.captures = captures.map |k,v| { [k,v.last] }.to_h
|
223
|
+
|
224
|
+
# Invoke the reduction action to get a value
|
225
|
+
# Store with the string index as the key so the value can be recaptured
|
226
|
+
value = code.invoke(
|
227
|
+
code.name,
|
228
|
+
Patterns::Reduction::Environment,
|
229
|
+
reduction_env,
|
230
|
+
[],
|
231
|
+
null,
|
232
|
+
)
|
233
|
+
store_value = [[start_idx, idx], value]
|
234
|
+
capt_stack.last.store(idx, store_value)
|
235
|
+
}
|
236
|
+
}
|