edits
[cdsspec-compiler.git] / src / edu / uci / eecs / specExtraction / SpecExtractor.java
index e1d0f2642c5015ab61c091579471416cb5141039..959e51f2a7fda8cbcdbdc6edb1e3177d3a60c0c6 100644 (file)
@@ -30,6 +30,7 @@ import edu.uci.eecs.utilParser.ParseException;
  * 
  */
 public class SpecExtractor {
+       public final HashMap<File, ArrayList<DefineConstruct>> defineListMap;
        public final HashMap<File, ArrayList<InterfaceConstruct>> interfaceListMap;
        public final HashMap<File, ArrayList<OPConstruct>> OPListMap;
        public final HashSet<String> OPLabelSet;
@@ -37,20 +38,36 @@ public class SpecExtractor {
        public final HashMap<File, EntryConstruct> entryMap;
 
        public final HashSet<String> headerFiles;
+       
+       // In the generated header file, we need to forward the user-defined 
+       public final HashSet<String> forwardClass;
 
        private GlobalConstruct globalConstruct;
 
        public SpecExtractor() {
+               defineListMap = new HashMap<File, ArrayList<DefineConstruct>>();
                interfaceListMap = new HashMap<File, ArrayList<InterfaceConstruct>>();
                OPListMap = new HashMap<File, ArrayList<OPConstruct>>();
                OPLabelSet = new HashSet<String>();
                entryMap = new HashMap<File, EntryConstruct>();
                headerFiles = new HashSet<String>();
+               forwardClass = new HashSet<String>();
                globalConstruct = null;
        }
+       
+       private void addDefineConstruct(DefineConstruct construct) {
+               ArrayList<DefineConstruct> list = defineListMap
+                               .get(construct.file);
+               if (list == null) {
+                       list = new ArrayList<DefineConstruct>();
+                       defineListMap.put(construct.file, list);
+               }
+               list.add(construct);
+       }
 
        private void addInterfaceConstruct(InterfaceConstruct construct) {
-               ArrayList<InterfaceConstruct> list = interfaceListMap.get(construct.file);
+               ArrayList<InterfaceConstruct> list = interfaceListMap
+                               .get(construct.file);
                if (list == null) {
                        list = new ArrayList<InterfaceConstruct>();
                        interfaceListMap.put(construct.file, list);
@@ -67,13 +84,14 @@ public class SpecExtractor {
                list.add(construct);
        }
 
-       private void addEntryConstruct(File file, EntryConstruct construct) throws WrongAnnotationException {
+       private void addEntryConstruct(File file, EntryConstruct construct)
+                       throws WrongAnnotationException {
                EntryConstruct old = entryMap.get(file);
                if (old == null)
                        entryMap.put(file, construct);
                else { // Error processing
-                       String errMsg = "Multiple @Entry annotations in the same file.\n\t Other @Entry at Line " + old.beginLineNum
-                                       + ".";
+                       String errMsg = "Multiple @Entry annotations in the same file.\n\t Other @Entry at Line "
+                                       + old.beginLineNum + ".";
                        WrongAnnotationException.err(file, construct.beginLineNum, errMsg);
                }
        }
@@ -90,7 +108,8 @@ public class SpecExtractor {
         * </p>
         */
        public void printAnnotations() {
-               System.out.println("/**********    Print out of specification extraction    **********/");
+               System.out
+                               .println("/**********    Print out of specification extraction    **********/");
                System.out.println("// Extracted header files");
                for (String header : headerFiles)
                        System.out.println(header);
@@ -104,7 +123,8 @@ public class SpecExtractor {
                        System.out.println("// Interface in file: " + file.getName());
                        for (InterfaceConstruct construct : list) {
                                System.out.println(construct);
-                               System.out.println("EndLineNumFunc: " + construct.getEndLineNumFunction());
+                               System.out.println("EndLineNumFunc: "
+                                               + construct.getEndLineNumFunction());
                        }
                }
 
@@ -145,11 +165,16 @@ public class SpecExtractor {
                        ArrayList<InterfaceConstruct> list = interfaceListMap.get(f);
                        if (list != null) {
                                for (InterfaceConstruct construct : list) {
-                                       InterfaceConstruct existingConstruct = interfaceMap.get(construct.getName());
+                                       InterfaceConstruct existingConstruct = interfaceMap
+                                                       .get(construct.getName());
                                        if (existingConstruct != null) { // Error
-                                               errMsg = "Interface labels duplication with: \"" + construct.getName() + "\" in File \""
-                                                               + existingConstruct.file.getName() + "\", Line " + existingConstruct.beginLineNum + ".";
-                                               WrongAnnotationException.err(construct.file, construct.beginLineNum, errMsg);
+                                               errMsg = "Interface labels duplication with: \""
+                                                               + construct.getName() + "\" in File \""
+                                                               + existingConstruct.file.getName()
+                                                               + "\", Line " + existingConstruct.beginLineNum
+                                                               + ".";
+                                               WrongAnnotationException.err(construct.file,
+                                                               construct.beginLineNum, errMsg);
                                        } else {
                                                interfaceMap.put(construct.getName(), construct);
                                        }
@@ -161,7 +186,8 @@ public class SpecExtractor {
                for (File file : OPListMap.keySet()) {
                        ArrayList<OPConstruct> list = OPListMap.get(file);
                        for (OPConstruct construct : list) {
-                               if (construct.type == OPType.OPCheck || construct.type == OPType.PotentialOP) {
+                               if (construct.type == OPType.OPCheck
+                                               || construct.type == OPType.PotentialOP) {
                                        String label = construct.label;
                                        OPLabelSet.add(label);
                                }
@@ -185,7 +211,8 @@ public class SpecExtractor {
         */
        public boolean extractHeaders(String line) {
                // "^( |\t)*#include( |\t)+("|<)([a-zA-Z_0-9\-\.])+("|>)"
-               Pattern regexp = Pattern.compile("^( |\\t)*(#include)( |\\t)+(\"|<)([a-zA-Z_0-9\\-\\.]+)(\"|>)");
+               Pattern regexp = Pattern
+                               .compile("^( |\\t)*(#include)( |\\t)+(\"|<)([a-zA-Z_0-9\\-\\.]+)(\"|>)");
                Matcher matcher = regexp.matcher(line);
 
                // process the line.
@@ -234,8 +261,9 @@ public class SpecExtractor {
         * @return Returns the annotation string list of the current construct
         * @throws WrongAnnotationException
         */
-       private ArrayList<String> extractTillConstructEnd(File file, LineNumberReader lineReader, String curLine,
-                       int beginLineNum) throws WrongAnnotationException {
+       private ArrayList<String> extractTillConstructEnd(File file,
+                       LineNumberReader lineReader, String curLine, int beginLineNum)
+                       throws WrongAnnotationException {
                ArrayList<String> annotations = new ArrayList<String>();
                annotations.add(curLine);
                // System.out.println(curLine);
@@ -258,8 +286,10 @@ public class SpecExtractor {
                                        if (matcher.find())
                                                return annotations;
                                }
-                               WrongAnnotationException.err(file, beginLineNum,
-                                               "The interface annotation should have the matching closing symbol closing \"*/\"");
+                               WrongAnnotationException
+                                               .err(file,
+                                                               beginLineNum,
+                                                               "The interface annotation should have the matching closing symbol closing \"*/\"");
                        } catch (IOException e) {
                                e.printStackTrace();
                        }
@@ -286,16 +316,20 @@ public class SpecExtractor {
         *            annotation
         * @throws WrongAnnotationException
         */
-       private void extractGlobalConstruct(File file, LineNumberReader lineReader, String curLine, int beginLineNum)
-                       throws WrongAnnotationException {
-               ArrayList<String> annotations = extractTillConstructEnd(file, lineReader, curLine, beginLineNum);
-               GlobalConstruct construct = new GlobalConstruct(file, beginLineNum, annotations);
+       private void extractGlobalConstruct(File file, LineNumberReader lineReader,
+                       String curLine, int beginLineNum) throws WrongAnnotationException {
+               ArrayList<String> annotations = extractTillConstructEnd(file,
+                               lineReader, curLine, beginLineNum);
+               GlobalConstruct construct = new GlobalConstruct(file, beginLineNum,
+                               annotations);
                if (globalConstruct != null) { // Check if we have seen a global state
                                                                                // construct earlier
                        File otherDefinitionFile = globalConstruct.file;
                        int otherDefinitionLine = globalConstruct.beginLineNum;
-                       String errMsg = "Multiple definition of global state.\n" + "\tAnother definition is in File \""
-                                       + otherDefinitionFile.getName() + "\" (Line " + otherDefinitionLine + ").";
+                       String errMsg = "Multiple definition of global state.\n"
+                                       + "\tAnother definition is in File \""
+                                       + otherDefinitionFile.getName() + "\" (Line "
+                                       + otherDefinitionLine + ").";
                        WrongAnnotationException.err(file, beginLineNum, errMsg);
                }
                globalConstruct = construct;
@@ -307,19 +341,22 @@ public class SpecExtractor {
         * @param lineReader
         *            Call this function when the lineReader will read the beginning
         *            of the definition right away
+        * @param startingLine
+        *            The line that we should start processing
         * @return The line number of the ending line of the interfae definition. If
         *         returning -1, it means the curl symbols in the interface do not
         *         match
         * @throws WrongAnnotationException
         */
-       private int findEndLineNumFunction(File file, LineNumberReader lineReader) throws WrongAnnotationException {
-               String line;
+       private int findEndLineNumFunction(File file, LineNumberReader lineReader,
+                       String startingLine) throws WrongAnnotationException {
+               String line = startingLine;
                // FIXME: We assume that in the string of the code, there does not exist
                // the symbol '{' & '{'
                try {
                        boolean foundFirstCurl = false;
                        int unmatchedCnt = 0;
-                       while ((line = lineReader.readLine()) != null) {
+                       do {
                                // process the line.
                                // System.out.println(line);
 
@@ -340,13 +377,47 @@ public class SpecExtractor {
                                                return endLineNumFunction;
                                        }
                                }
-                       }
+                       } while ((line = lineReader.readLine()) != null);
                } catch (IOException e) {
                        e.printStackTrace();
                }
                // -1 means the curl symbols in the interface do not match
                return -1;
        }
+       
+       /**
+        * <p>
+        * A sub-routine to extract the define construct. When called, we have
+        * already match the beginning of the construct, and we also need to find
+        * the ending line number of the anntotation.
+        * </p>
+        * 
+        * @param file
+        *            The file that we are processing
+        * @param lineReader
+        *            The LineNumberReader that we are using when processing the
+        *            current file.
+        * @param curLine
+        *            The current line that we are processing. It should be the
+        *            beginning line of the annotation construct.
+        * @param beginLineNum
+        *            The beginning line number of the interface construct
+        *            annotation
+        * @throws WrongAnnotationException
+        * @throws IOException
+        * @throws ParseException
+        */
+       private void extractDefineConstruct(File file,
+                       LineNumberReader lineReader, String curLine, int beginLineNum)
+                       throws WrongAnnotationException, IOException, ParseException {
+               ArrayList<String> annotations = extractTillConstructEnd(file,
+                               lineReader, curLine, beginLineNum);
+               int endLineNum = lineReader.getLineNumber();
+               DefineConstruct construct = new DefineConstruct(file,
+                               beginLineNum, endLineNum, annotations);
+               addDefineConstruct(construct);
+       }
+       
 
        /**
         * <p>
@@ -371,11 +442,14 @@ public class SpecExtractor {
         * @throws IOException
         * @throws ParseException
         */
-       private void extractInterfaceConstruct(File file, LineNumberReader lineReader, String curLine, int beginLineNum)
+       private void extractInterfaceConstruct(File file,
+                       LineNumberReader lineReader, String curLine, int beginLineNum)
                        throws WrongAnnotationException, IOException, ParseException {
-               ArrayList<String> annotations = extractTillConstructEnd(file, lineReader, curLine, beginLineNum);
+               ArrayList<String> annotations = extractTillConstructEnd(file,
+                               lineReader, curLine, beginLineNum);
                int endLineNum = lineReader.getLineNumber();
-               InterfaceConstruct construct = new InterfaceConstruct(file, beginLineNum, endLineNum, annotations);
+               InterfaceConstruct construct = new InterfaceConstruct(file,
+                               beginLineNum, endLineNum, annotations);
                addInterfaceConstruct(construct);
 
                // Process the corresponding interface function declaration header
@@ -386,24 +460,43 @@ public class SpecExtractor {
                        line = lineReader.readLine();
                        lineNum = lineReader.getLineNumber();
                        construct.processFunctionDeclaration(line);
+                       
+                       // Record those user-defined struct
+                       // RET
+                       String returnType = construct.getFunctionHeader().returnType;
+                       if (SpecUtils.isUserDefinedStruct(returnType))
+                               forwardClass.add(SpecUtils.getPlainType(returnType));
+                       // Arguments
+                       for (VariableDeclaration decl : construct.getFunctionHeader().args) {
+                               if (SpecUtils.isUserDefinedStruct(decl.type))
+                                       forwardClass.add(SpecUtils.getPlainType(decl.type));
+                       }
+                       
                } catch (IOException e) {
-                       errMsg = "Spec error in file \"" + file.getName() + "\", Line " + lineNum
+                       errMsg = "Spec error in file \""
+                                       + file.getName()
+                                       + "\", Line "
+                                       + lineNum
                                        + " :\n\tThe function declaration should take only one line and have the correct syntax (follow the annotations immediately)\n";
                        System.out.println(errMsg);
                        throw e;
                } catch (ParseException e) {
-                       errMsg = "Spec error in file \"" + file.getName() + "\", Line " + lineNum
+                       errMsg = "Spec error in file \""
+                                       + file.getName()
+                                       + "\", Line "
+                                       + lineNum
                                        + " :\n\tThe function declaration should take only one line and have the correct syntax (follow the annotations immediately)\n";
                        System.out.println(errMsg);
                        throw e;
                }
 
                // Now we find the end of the interface definition
-               int endLineNumFunction = findEndLineNumFunction(file, lineReader);
+               int endLineNumFunction = findEndLineNumFunction(file, lineReader, line);
                construct.setEndLineNumFunction(endLineNumFunction);
                if (endLineNumFunction == -1) {
-                       WrongAnnotationException.err(file, beginLineNum,
-                                       "The interface definition does NOT have matching curls '}'");
+                       WrongAnnotationException
+                                       .err(file, beginLineNum,
+                                                       "The interface definition does NOT have matching curls '}'");
                }
        }
 
@@ -425,22 +518,26 @@ public class SpecExtractor {
         *            The type of ordering point construct we are processing
         * @throws WrongAnnotationException
         */
-       private void extractOPConstruct(File file, int beginLineNum, String curLine, OPType type)
-                       throws WrongAnnotationException {
+       private void extractOPConstruct(File file, int beginLineNum,
+                       String curLine, OPType type) throws WrongAnnotationException {
                String condition = null;
                String label = null;
 
                // "(\(\s?(\w+)\s?\))?\s:\s?(.+)\*/\s?$"
-               Pattern regexp = Pattern.compile("(\\(\\s*(\\w+)\\s*\\))?\\s*:\\s*(.+)\\*/\\s*$");
+               Pattern regexp = Pattern
+                               .compile("(\\(\\s*(\\w+)\\s*\\))?\\s*:\\s*(.+)\\*/\\s*$");
                Matcher matcher = regexp.matcher(curLine);
                if (matcher.find()) {
                        label = matcher.group(2);
                        condition = matcher.group(3);
                } else {
-                       WrongAnnotationException.err(file, beginLineNum,
-                                       "Wrong syntax for the ordering point construct. You might need a colon before the condition.");
+                       WrongAnnotationException
+                                       .err(file,
+                                                       beginLineNum,
+                                                       "Wrong syntax for the ordering point construct. You might need a colon before the condition.");
                }
-               OPConstruct op = new OPConstruct(file, beginLineNum, type, label, condition, curLine);
+               OPConstruct op = new OPConstruct(file, beginLineNum, type, label,
+                               condition, curLine);
                addOPConstruct(op);
        }
 
@@ -459,7 +556,8 @@ public class SpecExtractor {
         *            Current line being processed
         * @throws WrongAnnotationException
         */
-       public void extractEntryConstruct(File file, int beginLineNum, String curLine) throws WrongAnnotationException {
+       public void extractEntryConstruct(File file, int beginLineNum,
+                       String curLine) throws WrongAnnotationException {
                addEntryConstruct(file, new EntryConstruct(file, beginLineNum, curLine));
        }
 
@@ -479,7 +577,8 @@ public class SpecExtractor {
         *            beginning line of the annotation construct.
         * @throws WrongAnnotationException
         */
-       private void extractOneLineConstruct(File file, int beginLineNum, String curLine) throws WrongAnnotationException {
+       private void extractOneLineConstruct(File file, int beginLineNum,
+                       String curLine) throws WrongAnnotationException {
                // "/\*\*\s*@(Entry|OPDefine|PotentialOP|OPCheck|OPClear|OPClearDefine)"
                Pattern regexpBegin = Pattern.compile("/\\*\\*\\s*@(\\w+)");
                Matcher matcher = regexpBegin.matcher(curLine);
@@ -488,9 +587,11 @@ public class SpecExtractor {
                        String name = matcher.group(1);
                        if (name.equals("Entry"))
                                extractEntryConstruct(file, beginLineNum, curLine);
-                       else if (name.equals("OPDefine") || name.equals("PotentialOP") || name.equals("OPCheck")
-                                       || name.equals("OPClear") || name.equals("OPClearDefine"))
-                               extractOPConstruct(file, beginLineNum, curLine, OPType.valueOf(name));
+                       else if (name.equals("OPDefine") || name.equals("PotentialOP")
+                                       || name.equals("OPCheck") || name.equals("OPClear")
+                                       || name.equals("OPClearDefine"))
+                               extractOPConstruct(file, beginLineNum, curLine,
+                                               OPType.valueOf(name));
                }
        }
 
@@ -512,7 +613,8 @@ public class SpecExtractor {
         * @throws WrongAnnotationException
         * @throws ParseException
         */
-       public void extractConstruct(File file) throws WrongAnnotationException, ParseException {
+       public void extractConstruct(File file) throws WrongAnnotationException,
+                       ParseException {
                BufferedReader br = null;
                LineNumberReader lineReader = null;
                try {
@@ -520,7 +622,8 @@ public class SpecExtractor {
                        br = new BufferedReader(new FileReader(file));
                        lineReader = new LineNumberReader(br);
                        // "/\*\*\s*@(DeclareState|Interface)"
-                       Pattern regexpBegin = Pattern.compile("/\\*\\*\\s*@(DeclareState|Interface)");
+                       Pattern regexpBegin = Pattern
+                                       .compile("/\\*\\*\\s*@(DeclareState|Interface|Define)");
                        Matcher matcher = regexpBegin.matcher("");
 
                        String line;
@@ -546,12 +649,18 @@ public class SpecExtractor {
 
                                        // Process each annotation accordingly
                                        if (constructName.equals(SpecNaming.DeclareState)) {
-                                               extractGlobalConstruct(file, lineReader, line, beginLineNum);
+                                               extractGlobalConstruct(file, lineReader, line,
+                                                               beginLineNum);
                                        } else if (constructName.equals(SpecNaming.Interface)) {
-                                               extractInterfaceConstruct(file, lineReader, line, beginLineNum);
+                                               extractInterfaceConstruct(file, lineReader, line,
+                                                               beginLineNum);
+                                       } else if (constructName.equals(SpecNaming.Define)) {
+                                               extractDefineConstruct(file, lineReader, line,
+                                                               beginLineNum);
                                        } else {
                                                WrongAnnotationException.err(file, beginLineNum,
-                                                               constructName + " is not a supported annotation.");
+                                                               constructName
+                                                                               + " is not a supported annotation.");
                                        }
 
                                }
@@ -582,15 +691,17 @@ public class SpecExtractor {
         * @throws WrongAnnotationException
         * @throws ParseException
         */
-       public void extract(File[] files) throws WrongAnnotationException, ParseException {
+       public void extract(File[] files) throws WrongAnnotationException,
+                       ParseException {
                for (int i = 0; i < files.length; i++)
                        extract(files[i]);
 
                // Check basic specification semantics
                checkSemantics();
        }
-       
-       public void extract(ArrayList<File> files) throws WrongAnnotationException, ParseException {
+
+       public void extract(ArrayList<File> files) throws WrongAnnotationException,
+                       ParseException {
                for (int i = 0; i < files.size(); i++)
                        extract(files.get(i));
 
@@ -611,7 +722,8 @@ public class SpecExtractor {
         * @throws WrongAnnotationException
         * @throws ParseException
         */
-       public void extract(File file) throws WrongAnnotationException, ParseException {
+       public void extract(File file) throws WrongAnnotationException,
+                       ParseException {
                extractConstruct(file);
        }
 }