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