@@ -15,35 +15,69 @@ private predicate regexpCaptureTwo(string input, string regexp, string capture1,
15
15
capture2 = input .regexpCapture ( regexp , 2 )
16
16
}
17
17
18
- /** Companion module to the `AccessPath` class. */
19
- module AccessPath {
20
- /** A string that should be parsed as an access path. */
21
- abstract class Range extends string {
22
- bindingset [ this ]
23
- Range ( ) { any ( ) }
24
- }
18
+ /**
19
+ * Parses an integer constant `n` or interval `n1..n2` (inclusive) and gets the value
20
+ * of the constant or any value contained in the interval.
21
+ */
22
+ bindingset [ arg]
23
+ int parseInt ( string arg ) {
24
+ result = arg .toInt ( )
25
+ or
26
+ // Match "n1..n2"
27
+ exists ( string lo , string hi |
28
+ regexpCaptureTwo ( arg , "(-?\\d+)\\.\\.(-?\\d+)" , lo , hi ) and
29
+ result = [ lo .toInt ( ) .. hi .toInt ( ) ]
30
+ )
31
+ }
25
32
26
- /**
27
- * Parses an integer constant `n` or interval `n1..n2` (inclusive) and gets the value
28
- * of the constant or any value contained in the interval.
29
- */
30
- bindingset [ arg]
31
- int parseInt ( string arg ) {
32
- result = arg .toInt ( )
33
- or
34
- // Match "n1..n2"
35
- exists ( string lo , string hi |
36
- regexpCaptureTwo ( arg , "(-?\\d+)\\.\\.(-?\\d+)" , lo , hi ) and
37
- result = [ lo .toInt ( ) .. hi .toInt ( ) ]
38
- )
33
+ /**
34
+ * Parses a lower-bounded interval `n..` and gets the lower bound.
35
+ */
36
+ bindingset [ arg]
37
+ int parseLowerBound ( string arg ) { result = arg .regexpCapture ( "(-?\\d+)\\.\\." , 1 ) .toInt ( ) }
38
+
39
+ /**
40
+ * An access part token such as `Argument[1]` or `ReturnValue`.
41
+ */
42
+ class AccessPathTokenBase extends string {
43
+ bindingset [ this ]
44
+ AccessPathTokenBase ( ) { exists ( this ) }
45
+
46
+ bindingset [ this ]
47
+ private string getPart ( int part ) {
48
+ result = this .regexpCapture ( "([^\\[]+)(?:\\[([^\\]]*)\\])?" , part )
39
49
}
40
50
51
+ /** Gets the name of the token, such as `Member` from `Member[x]` */
52
+ bindingset [ this ]
53
+ string getName ( ) { result = this .getPart ( 1 ) }
54
+
41
55
/**
42
- * Parses a lower-bounded interval `n..` and gets the lower bound.
56
+ * Gets the argument list, such as `1,2` from `Member[1,2]`,
57
+ * or has no result if there are no arguments.
43
58
*/
44
- bindingset [ arg]
45
- int parseLowerBound ( string arg ) { result = arg .regexpCapture ( "(-?\\d+)\\.\\." , 1 ) .toInt ( ) }
59
+ bindingset [ this ]
60
+ string getArgumentList ( ) { result = this .getPart ( 2 ) }
61
+
62
+ /** Gets the `n`th argument to this token, such as `x` or `y` from `Member[x,y]`. */
63
+ bindingset [ this ]
64
+ string getArgument ( int n ) { result = this .getArgumentList ( ) .splitAt ( "," , n ) .trim ( ) }
65
+
66
+ /** Gets an argument to this token, such as `x` or `y` from `Member[x,y]`. */
67
+ bindingset [ this ]
68
+ string getAnArgument ( ) { result = this .getArgument ( _) }
69
+
70
+ /** Gets the number of arguments to this token, such as 2 for `Member[x,y]` or zero for `ReturnValue`. */
71
+ bindingset [ this ]
72
+ int getNumArgument ( ) { result = count ( int n | exists ( this .getArgument ( n ) ) ) }
73
+ }
74
+
75
+ final private class AccessPathTokenBaseFinal = AccessPathTokenBase ;
76
+
77
+ signature predicate accessPathRangeSig ( string s ) ;
46
78
79
+ /** Companion module to the `AccessPath` class. */
80
+ module AccessPath< accessPathRangeSig / 1 accessPathRange> {
47
81
/**
48
82
* Parses an integer constant or interval (bounded or unbounded) that explicitly
49
83
* references the arity, such as `N-1` or `N-3..N-1`.
@@ -109,74 +143,78 @@ module AccessPath {
109
143
or
110
144
result = parseIntWithExplicitArity ( arg , arity )
111
145
}
112
- }
113
-
114
- /** Gets the `n`th token on the access path as a string. */
115
- private string getRawToken ( AccessPath path , int n ) {
116
- // Avoid splitting by '.' since tokens may contain dots, e.g. `Field[foo.Bar.x]`.
117
- // Instead use regexpFind to match valid tokens, and supplement with a final length
118
- // check (in `AccessPath.hasSyntaxError`) to ensure all characters were included in a token.
119
- result = path .regexpFind ( "\\w+(?:\\[[^\\]]*\\])?(?=\\.|$)" , n , _)
120
- }
121
-
122
- /**
123
- * A string that occurs as an access path (either identifying or input/output spec)
124
- * which might be relevant for this database.
125
- */
126
- class AccessPath extends string instanceof AccessPath:: Range {
127
- /** Holds if this string is not a syntactically valid access path. */
128
- predicate hasSyntaxError ( ) {
129
- // If the lengths match, all characters must haven been included in a token
130
- // or seen by the `.` lookahead pattern.
131
- this != "" and
132
- not this .length ( ) = sum ( int n | | getRawToken ( this , n ) .length ( ) + 1 ) - 1
133
- }
134
-
135
- /** Gets the `n`th token on the access path (if there are no syntax errors). */
136
- AccessPathToken getToken ( int n ) {
137
- result = getRawToken ( this , n ) and
138
- not this .hasSyntaxError ( )
139
- }
140
146
141
- /** Gets the number of tokens on the path (if there are no syntax errors). */
142
- int getNumToken ( ) {
143
- result = count ( int n | exists ( getRawToken ( this , n ) ) ) and
144
- not this .hasSyntaxError ( )
147
+ /** Gets the `n`th token on the access path as a string. */
148
+ private string getRawToken ( AccessPath path , int n ) {
149
+ // Avoid splitting by '.' since tokens may contain dots, e.g. `Field[foo.Bar.x]`.
150
+ // Instead use regexpFind to match valid tokens, and supplement with a final length
151
+ // check (in `AccessPath.hasSyntaxError`) to ensure all characters were included in a token.
152
+ result = path .regexpFind ( "\\w+(?:\\[[^\\]]*\\])?(?=\\.|$)" , n , _)
145
153
}
146
- }
147
-
148
- /**
149
- * An access part token such as `Argument[1]` or `ReturnValue`, appearing in one or more access paths.
150
- */
151
- class AccessPathToken extends string {
152
- AccessPathToken ( ) { this = getRawToken ( _, _) }
153
154
154
- private string getPart ( int part ) {
155
- result = this .regexpCapture ( "([^\\[]+)(?:\\[([^\\]]*)\\])?" , part )
155
+ /**
156
+ * A string that occurs as an access path (either identifying or input/output spec)
157
+ * which might be relevant for this database.
158
+ */
159
+ final class AccessPath extends string {
160
+ AccessPath ( ) { accessPathRange ( this ) }
161
+
162
+ /** Holds if this string is not a syntactically valid access path. */
163
+ predicate hasSyntaxError ( ) {
164
+ // If the lengths match, all characters must haven been included in a token
165
+ // or seen by the `.` lookahead pattern.
166
+ this != "" and
167
+ not this .length ( ) = sum ( int n | | getRawToken ( this , n ) .length ( ) + 1 ) - 1
168
+ }
169
+
170
+ /** Gets the `n`th token on the access path (if there are no syntax errors). */
171
+ AccessPathToken getToken ( int n ) {
172
+ result = getRawToken ( this , n ) and
173
+ not this .hasSyntaxError ( )
174
+ }
175
+
176
+ /** Gets the number of tokens on the path (if there are no syntax errors). */
177
+ int getNumToken ( ) {
178
+ result = count ( int n | exists ( getRawToken ( this , n ) ) ) and
179
+ not this .hasSyntaxError ( )
180
+ }
156
181
}
157
182
158
- /** Gets the name of the token, such as `Member` from `Member[x]` */
159
- string getName ( ) { result = this .getPart ( 1 ) }
160
-
161
183
/**
162
- * Gets the argument list, such as `1,2` from `Member[1,2]`,
163
- * or has no result if there are no arguments.
184
+ * An access part token such as `Argument[1]` or `ReturnValue`, appearing in one or more access paths.
164
185
*/
165
- string getArgumentList ( ) { result = this .getPart ( 2 ) }
166
-
167
- /** Gets the `n`th argument to this token, such as `x` or `y` from `Member[x,y]`. */
168
- string getArgument ( int n ) { result = this .getArgumentList ( ) .splitAt ( "," , n ) .trim ( ) }
169
-
170
- /** Gets the `n`th argument to this `name` token, such as `x` or `y` from `Member[x,y]`. */
171
- pragma [ nomagic]
172
- string getArgument ( string name , int n ) { name = this .getName ( ) and result = this .getArgument ( n ) }
173
-
174
- /** Gets an argument to this token, such as `x` or `y` from `Member[x,y]`. */
175
- string getAnArgument ( ) { result = this .getArgument ( _) }
176
-
177
- /** Gets an argument to this `name` token, such as `x` or `y` from `Member[x,y]`. */
178
- string getAnArgument ( string name ) { result = this .getArgument ( name , _) }
179
-
180
- /** Gets the number of arguments to this token, such as 2 for `Member[x,y]` or zero for `ReturnValue`. */
181
- int getNumArgument ( ) { result = count ( int n | exists ( this .getArgument ( n ) ) ) }
186
+ class AccessPathToken extends AccessPathTokenBaseFinal {
187
+ AccessPathToken ( ) { this = getRawToken ( _, _) }
188
+
189
+ /** Gets the name of the token, such as `Member` from `Member[x]` */
190
+ pragma [ nomagic]
191
+ string getName ( ) { result = super .getName ( ) }
192
+
193
+ /**
194
+ * Gets the argument list, such as `1,2` from `Member[1,2]`,
195
+ * or has no result if there are no arguments.
196
+ */
197
+ pragma [ nomagic]
198
+ string getArgumentList ( ) { result = super .getArgumentList ( ) }
199
+
200
+ /** Gets the `n`th argument to this token, such as `x` or `y` from `Member[x,y]`. */
201
+ pragma [ nomagic]
202
+ string getArgument ( int n ) { result = super .getArgument ( n ) }
203
+
204
+ /** Gets the `n`th argument to this `name` token, such as `x` or `y` from `Member[x,y]`. */
205
+ pragma [ nomagic]
206
+ string getArgument ( string name , int n ) {
207
+ name = this .getName ( ) and result = this .getArgument ( n )
208
+ }
209
+
210
+ /** Gets an argument to this token, such as `x` or `y` from `Member[x,y]`. */
211
+ string getAnArgument ( ) { result = this .getArgument ( _) }
212
+
213
+ /** Gets an argument to this `name` token, such as `x` or `y` from `Member[x,y]`. */
214
+ string getAnArgument ( string name ) { result = this .getArgument ( name , _) }
215
+
216
+ /** Gets the number of arguments to this token, such as 2 for `Member[x,y]` or zero for `ReturnValue`. */
217
+ pragma [ nomagic]
218
+ int getNumArgument ( ) { result = count ( int n | exists ( this .getArgument ( n ) ) ) }
219
+ }
182
220
}
0 commit comments