d3a2521223e3a3c5a9f918de46de5161fbaf8544
[cdsspec-compiler.git] / src / edu / uci / eecs / specExtraction / SpecExtractor.java
1 package edu.uci.eecs.specExtraction;
2
3 import java.io.BufferedReader;
4 import java.io.File;
5 import java.io.FileNotFoundException;
6 import java.io.FileReader;
7 import java.io.IOException;
8 import java.io.LineNumberReader;
9 import java.util.ArrayList;
10 import java.util.Collections;
11 import java.util.HashMap;
12 import java.util.HashSet;
13 import java.util.regex.Matcher;
14 import java.util.regex.Pattern;
15
16 import edu.uci.eecs.codeGenerator.CodeGeneratorUtils;
17 import edu.uci.eecs.codeGenerator.Environment;
18 import edu.uci.eecs.utilParser.ParseException;
19
20 /**
21  * <p>
22  * This class represents the specification extractor of the specification. The
23  * main function of this class is to read C/C++11 source files and extract the
24  * corresponding specifications, and record corresponding information such as
25  * location, e.g., the file name and the line number, to help the code
26  * generation process.
27  * </p>
28  * 
29  * @author Peizhao Ou
30  * 
31  */
32 public class SpecExtractor {
33         public final HashMap<File, ArrayList<DefineConstruct>> defineListMap;
34         public final HashMap<File, ArrayList<InterfaceConstruct>> interfaceListMap;
35         public final HashMap<File, ArrayList<OPConstruct>> OPListMap;
36         public final HashSet<String> OPLabelSet;
37         // Note that we only allow one entry per file at most
38         public final HashMap<File, EntryConstruct> entryMap;
39
40         public final HashSet<String> headerFiles;
41         
42         // In the generated header file, we need to forward the user-defined 
43         public final HashSet<String> forwardClass;
44
45         private GlobalConstruct globalConstruct;
46
47         public SpecExtractor() {
48                 defineListMap = new HashMap<File, ArrayList<DefineConstruct>>();
49                 interfaceListMap = new HashMap<File, ArrayList<InterfaceConstruct>>();
50                 OPListMap = new HashMap<File, ArrayList<OPConstruct>>();
51                 OPLabelSet = new HashSet<String>();
52                 entryMap = new HashMap<File, EntryConstruct>();
53                 headerFiles = new HashSet<String>();
54                 forwardClass = new HashSet<String>();
55                 globalConstruct = null;
56         }
57         
58         private void addDefineConstruct(DefineConstruct construct) {
59                 ArrayList<DefineConstruct> list = defineListMap
60                                 .get(construct.file);
61                 if (list == null) {
62                         list = new ArrayList<DefineConstruct>();
63                         defineListMap.put(construct.file, list);
64                 }
65                 list.add(construct);
66         }
67
68         private void addInterfaceConstruct(InterfaceConstruct construct) {
69                 ArrayList<InterfaceConstruct> list = interfaceListMap
70                                 .get(construct.file);
71                 if (list == null) {
72                         list = new ArrayList<InterfaceConstruct>();
73                         interfaceListMap.put(construct.file, list);
74                 }
75                 list.add(construct);
76         }
77
78         private void addOPConstruct(OPConstruct construct) {
79                 ArrayList<OPConstruct> list = OPListMap.get(construct.file);
80                 if (list == null) {
81                         list = new ArrayList<OPConstruct>();
82                         OPListMap.put(construct.file, list);
83                 }
84                 list.add(construct);
85         }
86
87         private void addEntryConstruct(File file, EntryConstruct construct)
88                         throws WrongAnnotationException {
89                 EntryConstruct old = entryMap.get(file);
90                 if (old == null)
91                         entryMap.put(file, construct);
92                 else { // Error processing
93                         String errMsg = "Multiple @Entry annotations in the same file.\n\t Other @Entry at Line "
94                                         + old.beginLineNum + ".";
95                         WrongAnnotationException.err(file, construct.beginLineNum, errMsg);
96                 }
97         }
98
99         public GlobalConstruct getGlobalConstruct() {
100                 return this.globalConstruct;
101         }
102
103         /**
104          * <p>
105          * A print out function for the purpose of debugging. Note that we better
106          * call this function after having called the checkSemantics() function to
107          * check annotation consistency.
108          * </p>
109          */
110         public void printAnnotations() {
111                 System.out
112                                 .println("/**********    Print out of specification extraction    **********/");
113                 System.out.println("// Extracted header files");
114                 for (String header : headerFiles)
115                         System.out.println(header);
116
117                 System.out.println("// Global State Construct");
118                 if (globalConstruct != null)
119                         System.out.println(globalConstruct);
120
121                 for (File file : interfaceListMap.keySet()) {
122                         ArrayList<InterfaceConstruct> list = interfaceListMap.get(file);
123                         System.out.println("// Interface in file: " + file.getName());
124                         for (InterfaceConstruct construct : list) {
125                                 System.out.println(construct);
126                                 System.out.println("EndLineNumFunc: "
127                                                 + construct.getEndLineNumFunction());
128                         }
129                 }
130
131                 for (File file : OPListMap.keySet()) {
132                         System.out.println("// Ordering points in file: " + file.getName());
133                         ArrayList<OPConstruct> list = OPListMap.get(file);
134                         for (OPConstruct construct : list)
135                                 System.out.println(construct);
136                 }
137
138                 for (File file : entryMap.keySet()) {
139                         System.out.println("// Entry in file: " + file.getName());
140                         System.out.println(entryMap.get(file));
141                 }
142         }
143
144         /**
145          * <p>
146          * Perform basic semantics checking of the extracted specification.
147          * </p>
148          * 
149          * @return
150          * @throws WrongAnnotationException
151          */
152         public void checkSemantics() throws WrongAnnotationException {
153                 String errMsg = null;
154
155                 // Assert that we have defined and only defined one global state
156                 // annotation
157                 if (globalConstruct == null) {
158                         errMsg = "Spec error: There should be one global state annotation.\n";
159                         throw new WrongAnnotationException(errMsg);
160                 }
161
162                 // Assert that the interface constructs have unique label name
163                 HashMap<String, InterfaceConstruct> interfaceMap = new HashMap<String, InterfaceConstruct>();
164                 for (File f : interfaceListMap.keySet()) {
165                         ArrayList<InterfaceConstruct> list = interfaceListMap.get(f);
166                         if (list != null) {
167                                 for (InterfaceConstruct construct : list) {
168                                         InterfaceConstruct existingConstruct = interfaceMap
169                                                         .get(construct.getName());
170                                         if (existingConstruct != null) { // Error
171                                                 errMsg = "Interface labels duplication with: \""
172                                                                 + construct.getName() + "\" in File \""
173                                                                 + existingConstruct.file.getName()
174                                                                 + "\", Line " + existingConstruct.beginLineNum
175                                                                 + ".";
176                                                 WrongAnnotationException.err(construct.file,
177                                                                 construct.beginLineNum, errMsg);
178                                         } else {
179                                                 interfaceMap.put(construct.getName(), construct);
180                                         }
181                                 }
182                         }
183                 }
184
185                 // Process ordering point labels
186                 for (File file : OPListMap.keySet()) {
187                         ArrayList<OPConstruct> list = OPListMap.get(file);
188                         for (OPConstruct construct : list) {
189                                 if (construct.type == OPType.OPCheck
190                                                 || construct.type == OPType.PotentialOP) {
191                                         String label = construct.label;
192                                         OPLabelSet.add(label);
193                                 }
194                         }
195                 }
196
197         }
198
199         /**
200          * <p>
201          * This function applies on a String (a plain line of text) to check whether
202          * the current line is a C/C++ header include statement. If it is, it
203          * extracts the header file name and store it, and returns true; otherwise,
204          * it returns false.
205          * </p>
206          * 
207          * @param line
208          *            The line of text to be processed
209          * @return Returns true if the current line is a C/C++ header include
210          *         statement
211          */
212         public boolean extractHeaders(String line) {
213                 // "^( |\t)*#include( |\t)+("|<)([a-zA-Z_0-9\-\.])+("|>)"
214                 Pattern regexp = Pattern
215                                 .compile("^( |\\t)*(#include)( |\\t)+(\"|<)([a-zA-Z_0-9\\-\\.]+)(\"|>)");
216                 Matcher matcher = regexp.matcher(line);
217
218                 // process the line.
219                 if (matcher.find()) {
220                         String header = null;
221                         String braceSymbol = matcher.group(4);
222                         if (braceSymbol.equals("<"))
223                                 header = "<" + matcher.group(5) + ">";
224                         else
225                                 header = "\"" + matcher.group(5) + "\"";
226                         if (!SpecNaming.isPreIncludedHeader(header)) {
227                                 headerFiles.add(header);
228                         }
229                         return true;
230                 } else
231                         return false;
232         }
233
234         /**
235          * <p>
236          * A sub-routine to extract the construct from beginning till end. When
237          * called, we have already match the beginning of the construct. We will
238          * call this sub-routine when we extract the interface construct and the
239          * global state construct.
240          * </p>
241          * 
242          * <p>
243          * The side effect of this function is that the lineReader has just read the
244          * end of the construct, meaning that the caller can get the end line number
245          * by calling lineReader.getLineNumber().
246          * </p>
247          * 
248          * @param file
249          *            The file that we are processing
250          * @param lineReader
251          *            The LineNumberReader that we are using when processing the
252          *            current file.
253          * @param file
254          *            The file that we are processing
255          * @param curLine
256          *            The current line that we are processing. It should be the
257          *            beginning line of the annotation construct.
258          * @param beginLineNum
259          *            The beginning line number of the interface construct
260          *            annotation
261          * @return Returns the annotation string list of the current construct
262          * @throws WrongAnnotationException
263          */
264         private ArrayList<String> extractTillConstructEnd(File file,
265                         LineNumberReader lineReader, String curLine, int beginLineNum)
266                         throws WrongAnnotationException {
267                 ArrayList<String> annotations = new ArrayList<String>();
268                 annotations.add(curLine);
269                 // System.out.println(curLine);
270                 // Initial settings for matching lines
271                 // "\*/\s*$"
272                 Pattern regexpEnd = Pattern.compile("\\*/\\s*$");
273                 Matcher matcher = regexpEnd.matcher(curLine);
274                 if (matcher.find()) {
275                         // The beginning line is also the end line
276                         // In this case, we have already add the curLine
277                         return annotations;
278                 } else {
279                         try {
280                                 String line;
281                                 while ((line = lineReader.readLine()) != null) {
282                                         // process the line.
283                                         // System.out.println(line);
284
285                                         matcher.reset(line); // reset the input
286                                         annotations.add(line);
287                                         if (matcher.find())
288                                                 return annotations;
289                                 }
290                                 WrongAnnotationException
291                                                 .err(file,
292                                                                 beginLineNum,
293                                                                 "The interface annotation should have the matching closing symbol closing \"*/\"");
294                         } catch (IOException e) {
295                                 e.printStackTrace();
296                         }
297                 }
298                 return null;
299         }
300
301         /**
302          * <p>
303          * A sub-routine to extract the global construct. When called, we have
304          * already match the beginning of the construct.
305          * </p>
306          * 
307          * @param file
308          *            The file that we are processing
309          * @param lineReader
310          *            The LineNumberReader that we are using when processing the
311          *            current file.
312          * @param curLine
313          *            The current line that we are processing. It should be the
314          *            beginning line of the annotation construct.
315          * @param beginLineNum
316          *            The beginning line number of the interface construct
317          *            annotation
318          * @throws WrongAnnotationException
319          */
320         private void extractGlobalConstruct(File file, LineNumberReader lineReader,
321                         String curLine, int beginLineNum) throws WrongAnnotationException {
322                 ArrayList<String> annotations = extractTillConstructEnd(file,
323                                 lineReader, curLine, beginLineNum);
324                 GlobalConstruct construct = new GlobalConstruct(file, beginLineNum,
325                                 annotations);
326                 if (globalConstruct != null) { // Check if we have seen a global state
327                                                                                 // construct earlier
328                         File otherDefinitionFile = globalConstruct.file;
329                         int otherDefinitionLine = globalConstruct.beginLineNum;
330                         String errMsg = "Multiple definition of global state.\n"
331                                         + "\tAnother definition is in File \""
332                                         + otherDefinitionFile.getName() + "\" (Line "
333                                         + otherDefinitionLine + ").";
334                         WrongAnnotationException.err(file, beginLineNum, errMsg);
335                 }
336                 globalConstruct = construct;
337         }
338
339         /**
340          * @param file
341          *            The current file we are processing
342          * @param lineReader
343          *            Call this function when the lineReader will read the beginning
344          *            of the definition right away
345          * @param startingLine
346          *            The line that we should start processing
347          * @return The line number of the ending line of the interfae definition. If
348          *         returning -1, it means the curl symbols in the interface do not
349          *         match
350          * @throws WrongAnnotationException
351          */
352         private int findEndLineNumFunction(File file, LineNumberReader lineReader,
353                         String startingLine) throws WrongAnnotationException {
354                 String line = startingLine;
355                 // FIXME: We assume that in the string of the code, there does not exist
356                 // the symbol '{' & '{'
357                 try {
358                         boolean foundFirstCurl = false;
359                         int unmatchedCnt = 0;
360                         do {
361                                 // process the line.
362                                 // System.out.println(line);
363
364                                 // Extract the one-liner construct first
365                                 extractOneLineConstruct(file, lineReader.getLineNumber(), line);
366
367                                 for (int i = 0; i < line.length(); i++) {
368                                         char ch = line.charAt(i);
369                                         if (ch == '{') {
370                                                 foundFirstCurl = true;
371                                                 unmatchedCnt++;
372                                         } else if (ch == '}') {
373                                                 unmatchedCnt--;
374                                         }
375                                         // The current line is the end of the function
376                                         if (foundFirstCurl && unmatchedCnt == 0) {
377                                                 int endLineNumFunction = lineReader.getLineNumber();
378                                                 return endLineNumFunction;
379                                         }
380                                 }
381                         } while ((line = lineReader.readLine()) != null);
382                 } catch (IOException e) {
383                         e.printStackTrace();
384                 }
385                 // -1 means the curl symbols in the interface do not match
386                 return -1;
387         }
388         
389         /**
390          * <p>
391          * A sub-routine to extract the define construct. When called, we have
392          * already match the beginning of the construct, and we also need to find
393          * the ending line number of the anntotation.
394          * </p>
395          * 
396          * @param file
397          *            The file that we are processing
398          * @param lineReader
399          *            The LineNumberReader that we are using when processing the
400          *            current file.
401          * @param curLine
402          *            The current line that we are processing. It should be the
403          *            beginning line of the annotation construct.
404          * @param beginLineNum
405          *            The beginning line number of the interface construct
406          *            annotation
407          * @throws WrongAnnotationException
408          * @throws IOException
409          * @throws ParseException
410          */
411         private void extractDefineConstruct(File file,
412                         LineNumberReader lineReader, String curLine, int beginLineNum)
413                         throws WrongAnnotationException, IOException, ParseException {
414                 ArrayList<String> annotations = extractTillConstructEnd(file,
415                                 lineReader, curLine, beginLineNum);
416                 int endLineNum = lineReader.getLineNumber();
417                 DefineConstruct construct = new DefineConstruct(file,
418                                 beginLineNum, endLineNum, annotations);
419                 addDefineConstruct(construct);
420         }
421         
422
423         /**
424          * <p>
425          * A sub-routine to extract the interface construct. When called, we have
426          * already match the beginning of the construct, and we also need to find
427          * the ending line number of the closing brace of the corresponding
428          * function.
429          * </p>
430          * 
431          * @param file
432          *            The file that we are processing
433          * @param lineReader
434          *            The LineNumberReader that we are using when processing the
435          *            current file.
436          * @param curLine
437          *            The current line that we are processing. It should be the
438          *            beginning line of the annotation construct.
439          * @param beginLineNum
440          *            The beginning line number of the interface construct
441          *            annotation
442          * @throws WrongAnnotationException
443          * @throws IOException
444          * @throws ParseException
445          */
446         private void extractInterfaceConstruct(File file,
447                         LineNumberReader lineReader, String curLine, int beginLineNum)
448                         throws WrongAnnotationException, IOException, ParseException {
449                 ArrayList<String> annotations = extractTillConstructEnd(file,
450                                 lineReader, curLine, beginLineNum);
451                 int endLineNum = lineReader.getLineNumber();
452                 InterfaceConstruct construct = new InterfaceConstruct(file,
453                                 beginLineNum, endLineNum, annotations);
454                 addInterfaceConstruct(construct);
455
456                 // Process the corresponding interface function declaration header
457                 String line = null;
458                 int lineNum = -1;
459                 String errMsg;
460                 try {
461                         line = lineReader.readLine();
462                         lineNum = lineReader.getLineNumber();
463                         construct.processFunctionDeclaration(line);
464                         
465                         // Record those user-defined struct
466                         // RET
467                         String returnType = construct.getFunctionHeader().returnType;
468                         if (SpecUtils.isUserDefinedStruct(returnType))
469                                 forwardClass.add(SpecUtils.getPlainType(returnType));
470                         // Arguments
471                         for (VariableDeclaration decl : construct.getFunctionHeader().args) {
472                                 if (SpecUtils.isUserDefinedStruct(decl.type))
473                                         forwardClass.add(SpecUtils.getPlainType(decl.type));
474                         }
475                         
476                 } catch (IOException e) {
477                         errMsg = "Spec error in file \""
478                                         + file.getName()
479                                         + "\", Line "
480                                         + lineNum
481                                         + " :\n\tThe function declaration should take only one line and have the correct syntax (follow the annotations immediately)\n";
482                         System.out.println(errMsg);
483                         throw e;
484                 } catch (ParseException e) {
485                         errMsg = "Spec error in file \""
486                                         + file.getName()
487                                         + "\", Line "
488                                         + lineNum
489                                         + " :\n\tThe function declaration should take only one line and have the correct syntax (follow the annotations immediately)\n";
490                         System.out.println(errMsg);
491                         throw e;
492                 }
493
494                 // Now we find the end of the interface definition
495                 int endLineNumFunction = findEndLineNumFunction(file, lineReader, line);
496                 construct.setEndLineNumFunction(endLineNumFunction);
497                 if (endLineNumFunction == -1) {
498                         WrongAnnotationException
499                                         .err(file, beginLineNum,
500                                                         "The interface definition does NOT have matching curls '}'");
501                 }
502         }
503
504         /**
505          * <p>
506          * A sub-routine to extract the ordering point construct. When called, we
507          * have already match the beginning of the construct.
508          * </p>
509          * 
510          * @param file
511          *            The file that we are processing
512          * @param beginLineNum
513          *            The beginning line number of the interface construct
514          *            annotation
515          * @param curLine
516          *            The current line that we are processing. It should be the
517          *            beginning line of the annotation construct.
518          * @param type
519          *            The type of ordering point construct we are processing
520          * @throws WrongAnnotationException
521          */
522         private void extractOPConstruct(File file, int beginLineNum,
523                         String curLine, OPType type) throws WrongAnnotationException {
524                 String condition = null;
525                 String label = null;
526
527                 // "(\(\s?(\w+)\s?\))?\s:\s?(.+)\*/\s?$"
528                 Pattern regexp = Pattern
529                                 .compile("(\\(\\s*(\\w+)\\s*\\))?\\s*:\\s*(.+)\\*/\\s*$");
530                 Matcher matcher = regexp.matcher(curLine);
531                 if (matcher.find()) {
532                         label = matcher.group(2);
533                         condition = matcher.group(3);
534                 } else {
535                         WrongAnnotationException
536                                         .err(file,
537                                                         beginLineNum,
538                                                         "Wrong syntax for the ordering point construct. You might need a colon before the condition.");
539                 }
540                 OPConstruct op = new OPConstruct(file, beginLineNum, type, label,
541                                 condition, curLine);
542                 addOPConstruct(op);
543         }
544
545         /**
546          * <p>
547          * A sub-routine to extract the entry construct. When called, we have
548          * already match the beginning of the construct.
549          * </p>
550          * 
551          * @param file
552          *            The file that we are processing
553          * @param beginLineNum
554          *            The beginning line number of the interface construct
555          *            annotation
556          * @param curLine
557          *            Current line being processed
558          * @throws WrongAnnotationException
559          */
560         public void extractEntryConstruct(File file, int beginLineNum,
561                         String curLine) throws WrongAnnotationException {
562                 addEntryConstruct(file, new EntryConstruct(file, beginLineNum, curLine));
563         }
564
565         /**
566          * <p>
567          * A sub-routine to extract those annotation constructs that take only one
568          * line --- Entry, OPDefine, PotentialOP, OPCheck, OPClear and OPClearDefin.
569          * </p>
570          * 
571          * @param file
572          *            The file that we are processing
573          * @param beginLineNum
574          *            The beginning line number of the interface construct
575          *            annotation
576          * @param curLine
577          *            The current line that we are processing. It should be the
578          *            beginning line of the annotation construct.
579          * @throws WrongAnnotationException
580          */
581         private void extractOneLineConstruct(File file, int beginLineNum,
582                         String curLine) throws WrongAnnotationException {
583                 // "/\*\*\s*@(Entry|OPDefine|PotentialOP|OPCheck|OPClear|OPClearDefine)"
584                 Pattern regexpBegin = Pattern.compile("/\\*\\*\\s*@(\\w+)");
585                 Matcher matcher = regexpBegin.matcher(curLine);
586                 matcher.reset(curLine);
587                 if (matcher.find()) {
588                         String name = matcher.group(1);
589                         if (name.equals("Entry"))
590                                 extractEntryConstruct(file, beginLineNum, curLine);
591                         else if (name.equals("OPDefine") || name.equals("PotentialOP")
592                                         || name.equals("OPCheck") || name.equals("OPClear")
593                                         || name.equals("OPClearDefine"))
594                                 extractOPConstruct(file, beginLineNum, curLine,
595                                                 OPType.valueOf(name));
596                 }
597         }
598
599         /**
600          * <p>
601          * This function will process a given C/C++ file ( .h, .c or .cc). It will
602          * extract all the headers included in that file, and all the annotation
603          * constructs specified in that file. We then will store the information in
604          * the corresponding containers.
605          * </p>
606          * 
607          * <p>
608          * The basic idea is to read the file line by line, and then use regular
609          * expression to match the specific annotations or the header files.
610          * </p>
611          * 
612          * @param file
613          *            The file object of the corresponding file to be processed
614          * @throws WrongAnnotationException
615          * @throws ParseException
616          */
617         public void extractConstruct(File file) throws WrongAnnotationException,
618                         ParseException {
619                 BufferedReader br = null;
620                 LineNumberReader lineReader = null;
621                 try {
622                         // Initial settings for processing the lines
623                         br = new BufferedReader(new FileReader(file));
624                         lineReader = new LineNumberReader(br);
625                         // "/\*\*\s*@(DeclareState|Interface)"
626                         Pattern regexpBegin = Pattern
627                                         .compile("/\\*\\*\\s*@(DeclareState|Interface|Define)");
628                         Matcher matcher = regexpBegin.matcher("");
629
630                         String line;
631                         while ((line = lineReader.readLine()) != null) {
632                                 // Start to process the line
633
634                                 // First try to process the line to see if it's a header file
635                                 // include
636                                 boolean succ = extractHeaders(line);
637                                 if (succ) // It's a header line and we successfully extract it
638                                         continue;
639
640                                 int beginLineNum = lineReader.getLineNumber();
641                                 // Extract the one-liner construct first
642                                 extractOneLineConstruct(file, beginLineNum, line);
643
644                                 // Now we process the line to see if it's an annotation (State
645                                 // or Interface)
646                                 matcher.reset(line); // reset the input
647                                 if (matcher.find()) { // Found the beginning line
648                                         // The matching annotation name
649                                         String constructName = matcher.group(1);
650
651                                         // Process each annotation accordingly
652                                         if (constructName.equals(SpecNaming.DeclareState)) {
653                                                 extractGlobalConstruct(file, lineReader, line,
654                                                                 beginLineNum);
655                                         } else if (constructName.equals(SpecNaming.Interface)) {
656                                                 extractInterfaceConstruct(file, lineReader, line,
657                                                                 beginLineNum);
658                                         } else if (constructName.equals(SpecNaming.Define)) {
659                                                 extractDefineConstruct(file, lineReader, line,
660                                                                 beginLineNum);
661                                         } else {
662                                                 WrongAnnotationException.err(file, beginLineNum,
663                                                                 constructName
664                                                                                 + " is not a supported annotation.");
665                                         }
666
667                                 }
668                         }
669                 } catch (FileNotFoundException e) {
670                         e.printStackTrace();
671                 } catch (IOException e) {
672                         e.printStackTrace();
673                 } finally {
674                         try {
675                                 lineReader.close();
676                         } catch (IOException e) {
677                                 e.printStackTrace();
678                         }
679                 }
680         }
681
682         /**
683          * <p>
684          * Given a list of files, it scans each file and add found SpecConstrcut to
685          * the _constructs list.
686          * </p>
687          * 
688          * @param files
689          *            The list of files that needs to be processed. In general, this
690          *            list only need to contain those that have specification
691          *            annotations
692          * @throws WrongAnnotationException
693          * @throws ParseException
694          */
695         public void extract(File[] files) throws WrongAnnotationException,
696                         ParseException {
697                 for (int i = 0; i < files.length; i++)
698                         extract(files[i]);
699
700                 // Check basic specification semantics
701                 checkSemantics();
702         }
703
704         public void extract(ArrayList<File> files) throws WrongAnnotationException,
705                         ParseException {
706                 for (int i = 0; i < files.size(); i++)
707                         extract(files.get(i));
708
709                 // Check basic specification semantics
710                 checkSemantics();
711         }
712
713         /**
714          * <p>
715          * Extract the specification annotations and header files in the current
716          * file. This function should generally be called by extractFiles.
717          * </p>
718          * 
719          * @param files
720          *            The list of files that needs to be processed. In general, this
721          *            list only need to contain those that have specification
722          *            annotations
723          * @throws WrongAnnotationException
724          * @throws ParseException
725          */
726         public void extract(File file) throws WrongAnnotationException,
727                         ParseException {
728                 extractConstruct(file);
729         }
730 }