@@ -20,12 +20,15 @@ import java.io.File;
20
20
import java. util. ArrayList;
21
21
import java. util. Arrays;
22
22
import java. util. List;
23
+ import java. util. EmptyStackException;
24
+ import java. util. Stack;
23
25
24
26
import org. eclipse. core. runtime. Path;
25
27
26
28
import fr. cnes. analysis. tools. analyzer. datas. AbstractChecker;
27
29
import fr. cnes. analysis. tools. analyzer. datas. CheckResult;
28
30
import fr. cnes. analysis. tools. analyzer. exception. JFlexException;
31
+ import fr. cnes. analysis. tools. shell. metrics. Function;
29
32
30
33
% %
31
34
@@ -40,21 +43,44 @@ import fr.cnes.analysis.tools.analyzer.exception.JFlexException;
40
43
%type List<CheckResult>
41
44
42
45
43
- %state COMMENT , NAMING , WRITE , STRING , FORLOOP , READ
46
+ %state COMMENT , NAMING , WRITE , STRING , FORLOOP , READ , BEGINFUNC
44
47
45
48
COMMENT_WORD = \#
46
- FUNC = "function"
47
- SPACE = [ \ \r\t\f]
48
- VAR = [ a- zA- Z][ a- zA- Z0- 9\_ ] *
49
+ FUNCT = {FNAME}{SPACE} * [ \( ] {SPACE} * [ \) ]
50
+ FUNCTION = "function"
51
+ FNAME = [ a- zA- Z0- 9\.\!\-\_\@\?\+ ] +
52
+ NAME = [ a- zA- Z\_ ][ a- zA- Z0- 9\_ ] *
53
+ SPACE = [ \ \r\t\f\s pace]
54
+ SHELL_VAR = ( [ 0- 9] +| [ \-\@\?\#\!\_\*\$ ] )
55
+ EXPANDED_VAR = [ \$ ][ \{ ] (( [ \: ] {SPACE} * [ \- ] )| [ a- zA- Z0- 9\_\:\%\=\+\?\/\!\-\,\^\#\*\@ ] |( [ \[ ] (( [ \: ] {SPACE} * [ \- ] )| [ a- zA- Z0- 9\_\/\:\%\=\+\?\!\$\-\,\^\#\*\@\[\]\{\} ] )+ [ \] ] ))+ [ \} ]
56
+ VAR = {NAME} | {EXPANDED_VAR} |( [ \$ ] ( {NAME} | {SHELL_VAR} ))
57
+
58
+ FUNCSTART = \{ | \( | \(\( | \[\[ | "if" | "select" | "for" | "while" | "until"
59
+ FUNCEND = \} | \) | \)\) | \]\] | "fi" | "done"
60
+
61
+
49
62
FILEEXIST = \[ {SPACE} + {OPTION}{SPACE} +( \" )?( \{ )? \$ ( \{ )? {VAR} ( \} )?( \" )?
50
63
OPTION = \- ( "a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "k" |
51
64
"p" | "r" | "s" | "u" | "w" | "x" | "O" | "G" | "L" |
52
65
"N" | "S" | "z" | "n" )
53
66
54
67
55
68
%{
56
- String location = " MAIN PROGRAM" ;
57
- List<String > variables = new ArrayList<String > ();
69
+ /* MAINPROGRAM: constant for main program localisation */
70
+ private static final String MAINPROGRAM = " MAIN PROGRAM" ;
71
+
72
+ /* FunctionWithVariables is used here with only initialized variables in locals and glabals */
73
+ private Stack<FunctionWithVariables > functionStack = new Stack<> ();
74
+
75
+ /* location: the current function name, or main program, that is the initial value */
76
+ private String location = MAINPROGRAM ;
77
+ /* functionLine: the beginning line of the function */
78
+ int functionLine = 0 ;
79
+
80
+ /* parsedFileName: name of the current file */
81
+ private String parsedFileName;
82
+
83
+ List<String > globalVariables = new ArrayList<String > ();
58
84
59
85
public COMDATAInitialisation() {
60
86
/* * Initialize list with system variables **/
@@ -64,15 +90,80 @@ OPTION = \- ("a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "k" |
64
90
" MACHTYPE" , " OLDPWD" , " OSTYPE" , " PATH" , " PIPESTATUS" , " PPID" , " PROMPT_COMMAND" ,
65
91
" PS1" , " PS2" , " PS3" , " PS4" , " PWD" , " REPLY" , " SECONDS" , " SHELLOPTS" , " SHLVL" , " TMOUT" ,
66
92
" UID" };
67
- variables . addAll(Arrays . asList(systemVariables));
93
+ globalVariables . addAll(Arrays . asList(systemVariables));
68
94
}
69
95
70
96
@Override
71
97
public void setInputFile(final File file) throws FileNotFoundException {
72
98
super . setInputFile(file);
99
+ this . parsedFileName = file. toString();
73
100
this . zzReader = new FileReader (new Path (file. getAbsolutePath()). toOSString());
74
101
}
75
-
102
+
103
+ private void endLocation() throws JFlexException {
104
+ try {
105
+ Function functionFinished = functionStack. pop();
106
+ if (! functionStack. empty()) {
107
+ /* there is a current function: change location to this function */
108
+ location = functionStack. peek(). getName();
109
+ } else {
110
+ /* we are in the main program: change location to main */
111
+ location = MAINPROGRAM ;
112
+ }
113
+ }catch (EmptyStackException e){
114
+ final String errorMessage = e. getMessage();
115
+ throw new JFlexException (this . getClass(). getName(), parsedFileName,
116
+ errorMessage, yytext(), yyline, yycolumn);
117
+ }
118
+ }
119
+
120
+ /**
121
+ * checkVariable: checks for violations on the current variable name (var).
122
+ * Called from YYINITIAL and STRING.
123
+ */
124
+ private void checkVariable(final String var ) throws JFlexException {
125
+ boolean found = false ;
126
+ if (! functionStack. empty()){
127
+ /* we are in a function */
128
+ if (functionStack. peek(). getLocalVariables(). contains(var ))
129
+ found = true ;
130
+ if (functionStack. peek(). getGlobalVariables(). contains(var ))
131
+ found = true ;
132
+ }
133
+ if (! found && ! globalVariables. contains(var )) {
134
+ setError(location," The variable $" + var + " is used before being initialized." , yyline+ 1 );
135
+ }
136
+ }
137
+
138
+ /**
139
+ * addVariable: adds the current variable name (var) to the list of variables : glabals if
140
+ * in main, locals if in funtion.
141
+ * Called from YYINITIAL, WRITE, FORLOOP and READ.
142
+ */
143
+ private void addVariable(final String var ) throws JFlexException {
144
+ if (! functionStack. empty()){
145
+ /* we are in a function */
146
+ functionStack. peek(). getLocalVariables(). add(var );
147
+ } else {
148
+ /* we are in main */
149
+ globalVariables. add(var );
150
+ }
151
+ }
152
+
153
+ /**
154
+ * setGlobals: adds the current globals to the globals of pFunction.
155
+ * If there is a higher level function, its locals are also added.
156
+ * Called from BEGINFUNC.
157
+ */
158
+ private void setGlobals(FunctionWithVariables pFunction) throws JFlexException {
159
+ if (! functionStack. empty()){
160
+ /* we are in a function: add the locals of the current function as globals of the new function */
161
+ pFunction. getGlobalVariables(). addAll(functionStack. peek(). getLocalVariables());
162
+ }
163
+ /* in all cases add the current globals */
164
+ pFunction. getGlobalVariables(). addAll(globalVariables);
165
+ }
166
+
76
167
%}
77
168
78
169
%eofval{
@@ -102,9 +193,15 @@ OPTION = \- ("a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "k" |
102
193
/* ***********************/
103
194
<NAMING>
104
195
{
105
- {VAR } {location = location + yytext(); yybegin(YYINITIAL );}
106
- \n {yybegin(YYINITIAL );}
107
- . {}
196
+ {VAR } {
197
+ location = yytext();
198
+ functionLine = yyline+ 1 ;
199
+ yybegin(BEGINFUNC );
200
+ }
201
+ \n {
202
+ yybegin(YYINITIAL );
203
+ }
204
+ . {}
108
205
}
109
206
110
207
/* ***********************/
@@ -113,18 +210,41 @@ OPTION = \- ("a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "k" |
113
210
<YYINITIAL>
114
211
{
115
212
{COMMENT_WORD } {yybegin(COMMENT );}
116
- {FUNC } {location = yytext(); yybegin(NAMING );}
117
- /* * variables initialisation **/
213
+ {FUNCTION } {yybegin(NAMING );}
214
+ {FUNCT } {
215
+ functionLine = yyline+ 1 ;
216
+ location = yytext(). substring(0 ,yytext(). length()- 2 ). trim();
217
+ yybegin(BEGINFUNC );
218
+ }
219
+ {FUNCSTART } {
220
+ if (! functionStack. empty()){
221
+ if (functionStack. peek(). getFinisher(). equals(Function . finisherOf(yytext()))){
222
+ functionStack. peek(). addStarterRepetition();
223
+ }
224
+ }
225
+ }
226
+ {FUNCEND } {
227
+ if (! functionStack. empty()){
228
+ if (functionStack. peek(). isFinisher(yytext())){
229
+ if (functionStack. peek(). getStarterRepetition()> 0 ) {
230
+ functionStack. peek(). removeStarterRepetition();
231
+ } else {
232
+ endLocation();
233
+ }
234
+ }
235
+ }
236
+ }
237
+ /* * variables initialisation **/
118
238
{VAR }{SPACE }* \= {String var = yytext(). substring(0 ,yytext(). length()- 1 ). trim();
119
- variables . add (var );}
239
+ addVariable (var );}
120
240
/* * Varible use found **/
121
241
\${VAR } {String var = yytext(). substring(1 );
122
- if ( ! variables . contains( var )) setError(location, " The variable $ " + var + " is used before being initialized. " , yyline + 1 );}
242
+ checkVariable( var );}
123
243
" tee" | \> \> {yybegin(WRITE );}
124
244
" for" {yybegin(FORLOOP );}
125
245
" read" {yybegin(READ );}
126
246
{FILEEXIST } {String var = yytext(). replaceAll(" \" " , " " ). replaceAll(" \\ {" , " " ). replaceAll(" \\ }" , " " ). split(" \\ $" )[1 ];
127
- variables . add (var );}
247
+ addVariable (var );}
128
248
{VAR } {}
129
249
\" {yybegin(STRING);}
130
250
. {}
@@ -137,7 +257,7 @@ OPTION = \- ("a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "k" |
137
257
{
138
258
\- {VAR} {}
139
259
\$ (\{ )?{VAR} {String var = yytext().substring(1).replace(" {" ," " );
140
- variables.add (var);}
260
+ addVariable (var);}
141
261
\n | \; {yybegin(YYINITIAL);}
142
262
. {}
143
263
}
@@ -147,7 +267,7 @@ OPTION = \- ("a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "k" |
147
267
/************************/
148
268
<FORLOOP>
149
269
{
150
- {VAR} {variables.add (yytext()); yybegin(YYINITIAL);}
270
+ {VAR} {addVariable (yytext()); yybegin(YYINITIAL);}
151
271
\n | \; {yybegin(YYINITIAL);}
152
272
. {}
153
273
}
@@ -159,7 +279,7 @@ OPTION = \- ("a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "k" |
159
279
{
160
280
\\\$ {}
161
281
\$ (\{ )?{VAR} {String var = yytext().substring(1).replace(" {" ," " );
162
- if(!variables.contains( var)) setError(location, " The variable $ " + var + " is used before being initialized . " , yyline+1 );}
282
+ checkVariable( var);}
163
283
\n | \; | \" {yybegin(YYINITIAL);}
164
284
. {}
165
285
}
@@ -169,11 +289,32 @@ OPTION = \- ("a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "k" |
169
289
/************************/
170
290
<READ>
171
291
{
172
- {VAR} {variables.add (yytext()); }
292
+ {VAR} {addVariable (yytext()); }
173
293
\n | \; {yybegin(YYINITIAL);}
174
294
. {}
175
295
}
176
296
297
+ /************************/
298
+ /* BEGINFUNC STATE */
299
+ /************************/
300
+ /*
301
+ * This state target is to retrieve the function starter. For more information on fonction starter, have a look on {@link Function} class.
302
+ * Pending this starter, the function ender can be defined.
303
+ *
304
+ */
305
+ <BEGINFUNC>
306
+ {
307
+ \(\) {}
308
+ {FUNCSTART} {
309
+ FunctionWithVariables function;
310
+ function = new FunctionWithVariables(location, functionLine, yytext());
311
+ setGlobals(function);
312
+ functionStack.push(function);
313
+ yybegin(YYINITIAL);
314
+ }
315
+ [^]|{SPACE} {}
316
+ }
317
+
177
318
178
319
/************************/
179
320
/* ERROR STATE */
0 commit comments