generate more structured code
[cdsspec-compiler.git] / src / edu / uci / eecs / specCompiler / specExtraction / SpecExtractor.java
1 package edu.uci.eecs.specCompiler.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
11 import edu.uci.eecs.specCompiler.grammerParser.ParseException;
12 import edu.uci.eecs.specCompiler.grammerParser.SpecParser;
13 import edu.uci.eecs.specCompiler.grammerParser.TokenMgrError;
14
15 /**
16  * <p>
17  * This class represents the specification extractor of the specification. The
18  * main function of this class is to read C/C++11 source files and extract the
19  * corresponding specification out, and remember its location, including the
20  * file name and the line number, to help the code generation process.
21  * </p>
22  * 
23  * @author peizhaoo
24  * 
25  */
26 public class SpecExtractor {
27         private ArrayList<SpecConstruct> _constructs;
28         private int _beginLineNum, _endLineNum;
29         private String _beginLine;
30
31         public SpecExtractor() {
32                 _constructs = new ArrayList<SpecConstruct>();
33         }
34
35         /**
36          * <p>
37          * Given a list of files, it scans each file and add found SpecConstrcut to
38          * the _constructs list.
39          * </p>
40          * 
41          * @param files
42          * @throws SpecNotMatchException
43          */
44         public void extract(File[] files) throws SpecNotMatchException {
45                 for (int i = 0; i < files.length; i++)
46                         extract(files[i]);
47         }
48
49         public void extract(File file) throws SpecNotMatchException {
50                 StringBuilder specText = new StringBuilder();
51                 try {
52                         LineNumberReader reader = new LineNumberReader(new FileReader(file));
53                         String prevLine = "", curLine, trimedLine, funcDecl;
54                         SpecConstruct specConstruct;
55                         boolean foundHead = false;
56                         while ((curLine = reader.readLine()) != null) {
57                                 if (prevLine.endsWith("\\"))
58                                         continue;
59                                 trimedLine = trimSpace(curLine);
60                                 if (!foundHead) {
61                                         if (trimedLine.startsWith("/**")) {
62                                                 _beginLineNum = reader.getLineNumber();
63                                                 _beginLine = curLine;
64                                                 foundHead = true;
65                                                 specText.append("\n");
66                                                 specText.append(curLine);
67                                                 if (trimedLine.endsWith("*/")) {
68                                                         _endLineNum = reader.getLineNumber();
69                                                         foundHead = false;
70                                                         if (isComment(specText.toString()))
71                                                                 continue;
72                                                         Construct inst = SpecParser.parseSpec(specText
73                                                                         .toString());
74                                                         if (inst instanceof InterfaceConstruct
75                                                                         || inst instanceof InterfaceDefineConstruct) {
76                                                                 funcDecl = readFunctionDecl(reader);
77                                                                 specConstruct = new SpecConstruct(
78                                                                                 specText.toString(), file,
79                                                                                 _beginLineNum, _endLineNum, inst,
80                                                                                 funcDecl);
81                                                         } else {
82                                                                 specConstruct = new SpecConstruct(
83                                                                                 specText.toString(), file,
84                                                                                 _beginLineNum, _endLineNum, inst);
85                                                         }
86                                                         _constructs.add(specConstruct);
87                                                         specText = new StringBuilder();
88                                                         // System.out.println(specConstruct);
89                                                 }
90                                         }
91                                 } else {
92                                         specText.append("\n");
93                                         specText.append(curLine);
94                                         if (trimedLine.endsWith("*/")) {
95                                                 _endLineNum = reader.getLineNumber();
96                                                 foundHead = false;
97                                                 if (isComment(specText.toString())) {
98                                                         specText = new StringBuilder();
99                                                         continue;
100                                                 }
101                                                 Construct inst = SpecParser.parseSpec(specText
102                                                                 .toString());
103                                                 if (inst instanceof InterfaceConstruct
104                                                                 || inst instanceof InterfaceDefineConstruct) {
105                                                         funcDecl = readFunctionDecl(reader);
106                                                         specConstruct = new SpecConstruct(
107                                                                         specText.toString(), file, _beginLineNum,
108                                                                         _endLineNum, inst, funcDecl);
109                                                 } else {
110                                                         specConstruct = new SpecConstruct(
111                                                                         specText.toString(), file, _beginLineNum,
112                                                                         _endLineNum, inst);
113                                                 }
114                                                 _constructs.add(specConstruct);
115                                                 specText = new StringBuilder();
116                                                 // System.out.println(specConstruct);
117                                         }
118                                 }
119                         }
120                         // At the end we can only find the head "/**" but no tail found
121                         if (foundHead) {
122                                 String msg = "In file \"" + file.getAbsolutePath()
123                                                 + "\", line: " + _beginLineNum + "\n" + _beginLine
124                                                 + "\n" + "Can't find matching spec.";
125                                 throw new SpecNotMatchException(msg);
126                         }
127                 } catch (FileNotFoundException e) {
128                         e.printStackTrace();
129                 } catch (IOException e) {
130                         e.printStackTrace();
131                 } catch (ParseException e) {
132                         printSpecInfo(file, specText.toString());
133                         e.printStackTrace();
134                 } catch (TokenMgrError e) {
135                         printSpecInfo(file, specText.toString());
136                         e.printStackTrace();
137                 }
138         }
139
140         private void printSpecInfo(File file, String text) {
141                 System.out.println("Error in spec!");
142                 System.out.println("File: " + file.getAbsolutePath());
143                 System.out.println("Begin: " + _beginLineNum + "  End: " + _endLineNum);
144                 System.out.println(text);
145         }
146
147         private boolean isComment(String specText) {
148                 if (specText.indexOf("@Begin") != -1)
149                         return false;
150                 return true;
151         }
152
153         private String readFunctionDecl(LineNumberReader reader) throws IOException {
154                 String res = "", curLine;
155                 while ((curLine = reader.readLine()) != null) {
156                         int braceIdx = curLine.indexOf(')');
157                         if (braceIdx == -1) {
158                                 res = res + " " + curLine;
159                         } else {
160                                 res = res + curLine;
161                                 break;
162                         }
163                 }
164                 return res;
165         }
166
167         public static String trimSpace(String line) {
168                 int i, j;
169                 char ch;
170                 for (i = 0; i < line.length(); i++) {
171                         ch = line.charAt(i);
172                         if (ch != ' ' && ch != '\t')
173                                 break;
174                 }
175                 for (j = line.length() - 1; j >= 0; j--) {
176                         ch = line.charAt(j);
177                         if (ch != ' ' && ch != '\t')
178                                 break;
179                 }
180                 if (i > j)
181                         return "";
182                 else
183                         return line.substring(i, j + 1);
184         }
185
186         public ArrayList<SpecConstruct> getConstructs() {
187                 return this._constructs;
188         }
189
190         public static void main(String[] argvs) {
191                 SpecExtractor extractor = new SpecExtractor();
192                 File file = new File("./grammer/spec1.txt");
193                 try {
194                         extractor.extract(file);
195                 } catch (SpecNotMatchException e) {
196                         e.printStackTrace();
197                 }
198         }
199 }