maccro 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,100 @@
1
+ require_relative "node"
2
+
3
+ module Maccro
4
+ module DSL
5
+ class MultiAssignment < Node
6
+ def type; :MASGN; end
7
+ def self.match?(node); node.type == :MASGN ; end
8
+ end
9
+
10
+ class LocalVariableAssignment < Node
11
+ def type; :LASGN; end
12
+ def self.match?(node); node.type == :LASGN ; end
13
+ end
14
+
15
+ class DynamicVariableAssignmentOutOfScope < Node
16
+ # x = 1; 1.times{ x = 1 }
17
+ def type; :DASGN; end
18
+ def self.match?(node); node.type == :DASGN ; end
19
+ end
20
+
21
+ class DynamicVariableAssignmentCurrentScope < Node
22
+ # 1.times{ x = 1 }
23
+ def type; :DASGN_CUPR; end
24
+ def self.match?(node); node.type == :DASGN_CUPR ; end
25
+ end
26
+
27
+ class InstanceVariableAssignment < Node
28
+ def type; :IASGN; end
29
+ def self.match?(node); node.type == :IASGN ; end
30
+ end
31
+
32
+ class ClassVariableAssignment < Node
33
+ def type; :CVASGN; end
34
+ def self.match?(node); node.type == :CVASGN ; end
35
+ end
36
+
37
+ class GlobalVariableAssignment < Node
38
+ def type; :GASGN; end
39
+ def self.match?(node); node.type == :GASGN ; end
40
+ end
41
+
42
+ class AttributeAssignment < Node
43
+ # x[1] = 1
44
+ # x.a = 1
45
+ def type; :ATTRASGN; end
46
+ def self.match?(node); node.type == :ATTRASGN ; end
47
+ end
48
+
49
+ class ArrayAssignmentWithOperator < Node
50
+ # x[1] += 1
51
+ def type; :OP_ASGN1; end
52
+ def self.match?(node); node.type == :OP_ASGN1 ; end
53
+ end
54
+
55
+ class AttributeAssignmentWithOperator < Node
56
+ # x.a += 1
57
+ def type; :OP_ASGN2; end
58
+ def self.match?(node); node.type == :OP_ASGN2 ; end
59
+ end
60
+
61
+ class AndAssignment < Node
62
+ # x &&= y
63
+ def type; :OP_ASGN_AND; end
64
+ def self.match?(node); node.type == :OP_ASGN_AND ; end
65
+ end
66
+
67
+ class OrAssignment < Node
68
+ # x ||= y
69
+ def type; :OP_ASGN_OR; end
70
+ def self.match?(node); node.type == :OP_ASGN_OR ; end
71
+ end
72
+
73
+ class ConstantDeclaration < Node
74
+ def type; :CDECL; end
75
+ def self.match?(node); node.type == :CDECL ; end
76
+ end
77
+
78
+ class ConstantDeclarationWithOperator < Node
79
+ # A::B ||= 1
80
+ # A::B += 1
81
+ def type; :OP_CDECL; end
82
+ def self.match?(node); node.type == :OP_CDECL ; end
83
+ end
84
+
85
+ class Assignment < Node
86
+ SUB_TYPES = [
87
+ MultiAssignment, LocalVariableAssignment,
88
+ DynamicVariableAssignmentOutOfScope, DynamicVariableAssignmentCurrentScope,
89
+ InstanceVariableAssignment, ClassVariableAssignment, GlobalVariableAssignment,
90
+ AttributeAssignment, ArrayAssignmentWithOperator, AttributeAssignmentWithOperator,
91
+ AndAssignment, OrAssignment,
92
+ ConstantDeclaration, ConstantDeclarationWithOperator,
93
+ ].freeze
94
+
95
+ def self.match?(node)
96
+ SUB_TYPES.any?{|s| s.match?(node) }
97
+ end
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,166 @@
1
+ require_relative "node"
2
+ require_relative "value"
3
+ require_relative "assign"
4
+
5
+ module Maccro
6
+ module DSL
7
+ class IfExp < Node
8
+ def type; :IF; end
9
+ def self.match?(node); node.type == :IF; end
10
+ end
11
+
12
+ class UnlessExp < Node
13
+ def type; :UNLESS; end
14
+ def self.match?(node); node.type == :UNLESS; end
15
+ end
16
+
17
+ class CaseExp < Node
18
+ def type; :MACCRO_CASE; end
19
+ def self.match?(node)
20
+ node.type == :CASE || node.type == :CASE2
21
+ end
22
+ end
23
+
24
+ # class BeginExp < Node
25
+ # # TODO: getting source of begin node DOES drop the beggining "begin" and tailing "end"
26
+ # def type; :"BEGIN"; end
27
+ # def self.match?(node); node.type == :"BEGIN"; end
28
+ # end
29
+
30
+ # class RescueExp < Node
31
+ # # TODO: getting source of rescue node DOES drop the beggining "begin" and tailing "end"
32
+ # def type; :"RESCUE"; end
33
+ # def self.match?(node); node.type == :"RESCUE"; end
34
+ # end
35
+
36
+ class AndExp < Node
37
+ def type; :AND; end
38
+ def self.match?(node); node.type == :AND; end
39
+ end
40
+
41
+ class OrExp < Node
42
+ def type; :OR; end
43
+ def self.match?(node); node.type == :OR; end
44
+ end
45
+
46
+ class CallExp < Node
47
+ def type; :CALL; end
48
+ def self.match?(node); node.type == :CALL; end
49
+ end
50
+
51
+ class OperatorCallExp < Node
52
+ def type; :OPCALL; end
53
+ def self.match?(node); node.type == :OPCALL; end
54
+ end
55
+
56
+ class SafeCallExp < Node
57
+ # x&.foo(1)
58
+ def type; :QCALL; end
59
+ def self.match?(node); node.type == :QCALL; end
60
+ end
61
+
62
+ class FunctionCallExp < Node
63
+ def type; :FCALL; end
64
+ def self.match?(node); node.type == :FCALL; end
65
+ end
66
+
67
+ class VCallExp < Node
68
+ # function call without arguments
69
+ def type; :VCALL; end
70
+ def self.match?(node); node.type == :VCALL; end
71
+ end
72
+
73
+ class SuperExp < Node
74
+ # super or super without arguments
75
+ def type; :MACCRO_SUPER; end
76
+ def self.match?(node)
77
+ node.type == :SUPER || node.type == :ZSUPER
78
+ end
79
+ end
80
+
81
+ class YieldExp < Node
82
+ def type; :YIELD; end
83
+ def self.match?(node); node.type == :YIELD; end
84
+ end
85
+
86
+ class MatchExp < Node
87
+ # MATCH: /.../ without `=~` (matches to $_ implicitly)
88
+ # MATCH2: /.../ =~ "..." (left side)
89
+ # MATCH3: "..." =~ /.../ (right side)
90
+ def type; :MACCRO_MATCH; end
91
+ def self.match?(node)
92
+ t = node.type
93
+ t == :MATCH || t == :MATCH2 || t == :MATCH3
94
+ end
95
+ end
96
+
97
+ class DefineMethod < Node
98
+ def type; :DEFN; end
99
+ def self.match?(node); node.type == :DEFN; end
100
+ end
101
+
102
+ class DefineSingletonMethod < Node
103
+ def type; :DEFS; end
104
+ def self.match?(node); node.type == :DEFS; end
105
+ end
106
+
107
+ class Colon2Exp < Node
108
+ def type; :COLON2; end
109
+ def self.match?(node); node.type == :COLON2; end
110
+ end
111
+
112
+ class Colon3Exp < Node
113
+ # top level reference (::A)
114
+ def type; :COLON3; end
115
+ def self.match?(node); node.type == :COLON3; end
116
+ end
117
+
118
+ class Dot2Exp < Node
119
+ # range constructor (inclusive)
120
+ def type; :DOT2; end
121
+ def self.match?(node); node.type == :DOT2; end
122
+ end
123
+
124
+ class Dot3Exp < Node
125
+ # range constructor (exclusive)
126
+ def type; :DOT3; end
127
+ def self.match?(node); node.type == :DOT3; end
128
+ end
129
+
130
+ class Flip2Exp < Node
131
+ # flip-flop (inclusive)
132
+ def type; :FLIP2; end
133
+ def self.match?(node); node.type == :FLIP2; end
134
+ end
135
+
136
+ class Flip3Exp < Node
137
+ # flip-flop (exclusive)
138
+ def type; :FLIP3; end
139
+ def self.match?(node); node.type == :FLIP3; end
140
+ end
141
+
142
+ class DefinedExp < Node
143
+ def type; :DEFINED; end
144
+ def self.match?(node); node.type == :DEFINED; end
145
+ end
146
+
147
+ class Expression < Node
148
+ SUB_TYPES = [
149
+ Value, Assignment,
150
+ IfExp, UnlessExp, CaseExp,
151
+ # BeginExp, RescueExp,
152
+ AndExp, OrExp,
153
+ CallExp, OperatorCallExp, SafeCallExp, FunctionCallExp, VCallExp,
154
+ SuperExp, YieldExp,
155
+ MatchExp,
156
+ DefineMethod, DefineSingletonMethod,
157
+ Colon2Exp, Colon3Exp, Dot2Exp, Dot3Exp, Flip2Exp, Flip3Exp,
158
+ DefinedExp,
159
+ ].freeze
160
+
161
+ def self.match?(node)
162
+ SUB_TYPES.any?{|s| s.match?(node) }
163
+ end
164
+ end
165
+ end
166
+ end
@@ -0,0 +1,121 @@
1
+ require_relative "node"
2
+
3
+ module Maccro
4
+ module DSL
5
+ class Literal < Node
6
+ # integer, float, symbol, regex, ...
7
+ def type; :LIT; end
8
+ def self.match?(node); node.type == :LIT; end
9
+ end
10
+
11
+ class DSymbol < Node
12
+ # symbol with string interpolation
13
+ def type; :DSYM; end
14
+ def self.match?(node); node.type == :DSYM; end
15
+ end
16
+
17
+ class Symbol < Node
18
+ def type; :LIT; end
19
+ def self.match?(node)
20
+ (node.type == :LIT && node.children[0].is_a?(::Symbol)) || DSymbol.match?(node)
21
+ end
22
+ end
23
+
24
+ class Number < Node
25
+ def type; :LIT; end
26
+ def self.match?(node)
27
+ node.type == :LIT && node.children[0].is_a?(::Numeric)
28
+ end
29
+ end
30
+
31
+ class RegexpCompiledOnce < Node
32
+ # regex with RE_OPTION_ONCE (see new_regexp() in parse.y)
33
+ def type; :ONCE; end
34
+ def self.match?(node); node.type == :ONCE; end
35
+ end
36
+
37
+ class DRegexp < Node
38
+ # regex with string interpolation
39
+ def type; :DREGX; end
40
+ def self.match?(node); node.type == :DREGX; end
41
+ end
42
+
43
+ class RegularExpression < Node
44
+ def type; :LIT; end
45
+ def self.match?(node)
46
+ node.type == :LIT && node.children[0].is_a?(Regexp)
47
+ end
48
+ end
49
+
50
+ class FString < Node
51
+ # string literal without interpolation
52
+ def type; :STR; end
53
+ def self.match?(node); node.type == :STR; end
54
+ end
55
+
56
+ class DString < Node
57
+ # string literal with interpolation ?
58
+ def type; :DSTR; end
59
+ def self.match?(node); node.type == :DSTR; end
60
+ end
61
+
62
+ class XString < Node
63
+ # string from back quote: `...`
64
+ # is it a literal?
65
+ def type; :XSTR; end
66
+ def self.match?(node); node.type == :XSTR; end
67
+ end
68
+
69
+ class DXString < Node
70
+ # string from back quote with string interpolation: `... #{..} ...`
71
+ # is it a literal?
72
+ def type; :DXSTR; end
73
+ def self.match?(node); node.type == :DXSTR; end
74
+ end
75
+
76
+ class String < Node
77
+ SUB_TYPES = [FString, DString, XString, DXString].freeze
78
+
79
+ def type; :MACCRO_STRING; end
80
+
81
+ def self.match?(node)
82
+ SUB_TYPES.any?{|s| s.match?(node) }
83
+ end
84
+ end
85
+
86
+ class NilValue < Node
87
+ def type; :NIL; end
88
+ def self.match?(node); node.type == :NIL; end
89
+ end
90
+
91
+ class TrueValue < Node
92
+ def type; :TRUE; end
93
+ def self.match?(node); node.type == :TRUE; end
94
+ end
95
+
96
+ class FalseValue < Node
97
+ def type; :FALSE; end
98
+ def self.match?(node); node.type == :FALSE; end
99
+ end
100
+
101
+ class Lambda < Node
102
+ def type; :LAMBDA; end
103
+ def self.match?(node); node.type == :LAMBDA; end
104
+ end
105
+
106
+ class Array < Node
107
+ # ARRAY and ZARRAY
108
+ def type; :MACCRO_ARRAY; end
109
+ def self.match?(node)
110
+ node.type == :ARRAY || node.type == :ZARRAY
111
+ end
112
+ end
113
+
114
+ class Hash < Node
115
+ # HASH may be a hash literal, or keyword argument assignment `"a: 1" of f(a: 1)`
116
+ # HASH(nd_alen == 0) is a keyword argument assignment, but no way to get it via AST::Node
117
+ def type; :HASH; end
118
+ def self.match?(node); node.type == :HASH; end
119
+ end
120
+ end
121
+ end
@@ -0,0 +1,89 @@
1
+ require_relative '../code_range'
2
+
3
+ module Maccro
4
+ module DSL
5
+ module ASTNodeWrapper
6
+ def children
7
+ @child_nodes ||= super
8
+ end
9
+
10
+ def to_code_range
11
+ CodeRange.from_node(self)
12
+ end
13
+
14
+ def match?(node)
15
+ return false unless node.is_a?(ASTNodeWrapper)
16
+ return false if node.type != self.type
17
+ self.children.each_with_index do |c, i|
18
+ if c.is_a?(ASTNodeWrapper)
19
+ return false unless c.match?(node.children[i])
20
+ else
21
+ return false unless c == node.children[i]
22
+ end
23
+ end
24
+ # same type, all children match with others
25
+ true
26
+ end
27
+
28
+ def capture(ast, placeholders)
29
+ self.children.each_with_index do |c, i|
30
+ if c.is_a?(ASTNodeWrapper)
31
+ c.capture(ast.children[i], placeholders)
32
+ end
33
+ end
34
+ end
35
+ end
36
+
37
+ class Node
38
+ attr_reader :name, :first_lineno, :first_column, :last_lineno, :last_column
39
+
40
+ include ASTNodeWrapper
41
+
42
+ def initialize(name, code_range)
43
+ @name = name
44
+ @code_range = code_range
45
+ @first_lineno = code_range.first_lineno
46
+ @first_column = code_range.first_column
47
+ @last_lineno = code_range.last_lineno
48
+ @last_column = code_range.last_column
49
+ end
50
+
51
+ def to_code_range
52
+ @code_range
53
+ end
54
+
55
+ def type
56
+ :MACCRO_NODE
57
+ end
58
+
59
+ def children
60
+ []
61
+ end
62
+
63
+ def match?(node)
64
+ # literals are not Node in any cases
65
+ return false unless node.respond_to?(:type)
66
+
67
+ if self.class.respond_to?(:match?)
68
+ self.class.match?(node)
69
+ else
70
+ super
71
+ end
72
+ end
73
+
74
+ def capture(ast, placeholders)
75
+ placeholders[@name] = ast.to_code_range
76
+ end
77
+ end
78
+
79
+ class AnyNode < Node
80
+ def match?(node)
81
+ true
82
+ end
83
+
84
+ def capture(ast, placeholders)
85
+ placeholders[:__target__] = ast
86
+ end
87
+ end
88
+ end
89
+ end