3c462c17b4735e5a425326420c556163f82dcda5
[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                                                                 funcDecl = readFunctionDecl(reader);
76                                                                 specConstruct = new SpecConstruct(
77                                                                                 specText.toString(), file,
78                                                                                 _beginLineNum, _endLineNum, inst, funcDecl);
79                                                         } else {
80                                                                 specConstruct = new SpecConstruct(
81                                                                                 specText.toString(), file,
82                                                                                 _beginLineNum, _endLineNum, inst);
83                                                         }
84                                                         _constructs.add(specConstruct);
85                                                         specText = new StringBuilder();
86 //                                                      System.out.println(specConstruct);
87                                                 }
88                                         }
89                                 } else {
90                                         specText.append("\n");
91                                         specText.append(curLine);
92                                         if (trimedLine.endsWith("*/")) {
93                                                 _endLineNum = reader.getLineNumber();
94                                                 foundHead = false;
95                                                 if (isComment(specText.toString())) {
96                                                         specText = new StringBuilder();
97                                                         continue;
98                                                 }
99                                                 Construct inst = SpecParser.parseSpec(specText
100                                                                 .toString());
101                                                 if (inst instanceof InterfaceConstruct) {
102                                                         funcDecl = readFunctionDecl(reader);
103                                                         specConstruct = new SpecConstruct(
104                                                                         specText.toString(), file,
105                                                                         _beginLineNum, _endLineNum, inst, funcDecl);
106                                                 } else {
107                                                         specConstruct = new SpecConstruct(
108                                                                         specText.toString(), file,
109                                                                         _beginLineNum, _endLineNum, inst);
110                                                 }
111                                                 _constructs.add(specConstruct);
112                                                 specText = new StringBuilder();
113 //                                              System.out.println(specConstruct);
114                                         }
115                                 }
116                         }
117                         // At the end we can only find the head "/**" but no tail found
118                         if (foundHead) {
119                                 String msg = "In file \"" + file.getAbsolutePath()
120                                                 + "\", line: " + _beginLineNum + "\n" + _beginLine
121                                                 + "\n" + "Can't find matching spec.";
122                                 throw new SpecNotMatchException(msg);
123                         }
124                 } catch (FileNotFoundException e) {
125                         e.printStackTrace();
126                 } catch (IOException e) {
127                         e.printStackTrace();
128                 } catch (ParseException e) {
129                         printSpecInfo(file, specText.toString());
130                         e.printStackTrace();
131                 } catch (TokenMgrError e) {
132                         printSpecInfo(file, specText.toString());
133                         e.printStackTrace();
134                 }
135         }
136         
137         private void printSpecInfo(File file, String text) {
138                 System.out.println("Error in spec!");
139                 System.out.println("File: " + file.getAbsolutePath());
140                 System.out.println("Begin: "
141                                 + _beginLineNum + "  End: " + _endLineNum);
142                 System.out.println(text);
143         }
144         
145         private boolean isComment(String specText) {
146                 if (specText.indexOf("@Begin") != -1)
147                         return false;
148                 return true;
149         }
150
151         private String readFunctionDecl(LineNumberReader reader) throws IOException {
152                 String res = "", curLine;
153                 while ((curLine = reader.readLine()) != null) {
154                         int braceIdx = curLine.indexOf(')');
155                         if (braceIdx == -1) {
156                                 res = res + " " + curLine;
157                         } else {
158                                 res = res + curLine.substring(0, braceIdx + 1);
159                                 res = trimSpace(res);
160                                 break;
161                         }
162                 }
163                 return res;
164         }
165
166         private String trimSpace(String line) {
167                 int i, j;
168                 char ch;
169                 for (i = 0; i < line.length(); i++) {
170                         ch = line.charAt(i);
171                         if (ch != ' ' && ch != '\t')
172                                 break;
173                 }
174                 for (j = line.length() - 1; j >= 0; j--) {
175                         ch = line.charAt(j);
176                         if (ch != ' ' && ch != '\t')
177                                 break;
178                 }
179                 if (i > j)
180                         return "";
181                 else
182                         return line.substring(i, j + 1);
183         }
184         
185         public ArrayList<SpecConstruct> getConstructs() {
186                 return this._constructs;
187         }
188
189         public static void main(String[] argvs) {
190                 SpecExtractor extractor = new SpecExtractor();
191                 File file = new File("./grammer/spec1.txt");
192                 try {
193                         extractor.extract(file);
194                 } catch (SpecNotMatchException e) {
195                         e.printStackTrace();
196                 }
197         }
198 }