import java.io.LineNumberReader;
import java.util.ArrayList;
+import edu.uci.eecs.specCompiler.grammerParser.ParseException;
+import edu.uci.eecs.specCompiler.grammerParser.SpecParser;
+import edu.uci.eecs.specCompiler.grammerParser.TokenMgrError;
+
/**
* <p>
* This class represents the specification extractor of the specification. The
* corresponding specification out, and remember its location, including the
* file name and the line number, to help the code generation process.
* </p>
+ *
* @author peizhaoo
- *
+ *
*/
public class SpecExtractor {
private ArrayList<SpecConstruct> _constructs;
- private StringBuilder _extractedSpecText;
-
- private enum State {
- Neutral, HeadParsed, BeginParsed, EndParsed
- }
-
- private State _curState;
-
- private StringBuilder _potentialConstruct;
- private int _startLine, _endLine;
-
+ private int _beginLineNum, _endLineNum;
+ private String _beginLine;
+
SpecExtractor() {
_constructs = new ArrayList<SpecConstruct>();
- _extractedSpecText = new StringBuilder();
- _curState = State.Neutral;
- _potentialConstruct = new StringBuilder();
}
-
+
/**
* <p>
- * Given a list of files, it scans each file and add found SpecConstrcut
- * to the _constructs list.
+ * Given a list of files, it scans each file and add found SpecConstrcut to
+ * the _constructs list.
* </p>
+ *
* @param files
+ * @throws SpecNotMatchException
*/
- private void extract(File[] files) {
+ public void extract(File[] files) throws SpecNotMatchException {
for (int i = 0; i < files.length; i++)
extract(files[i]);
}
-
- private void extract(File file) {
+
+ public void extract(File file) throws SpecNotMatchException {
+ StringBuilder specText = new StringBuilder();
try {
LineNumberReader reader = new LineNumberReader(new FileReader(file));
- String prevLine = "", curLine;
- ArrayList<String> text;
+ String prevLine = "", curLine, trimedLine, funcDecl;
+ SpecConstruct specConstruct;
+ boolean foundHead = false;
while ((curLine = reader.readLine()) != null) {
-
+ if (prevLine.endsWith("\\"))
+ continue;
+ trimedLine = trimSpace(curLine);
+ if (!foundHead) {
+ if (trimedLine.startsWith("/**")) {
+ _beginLineNum = reader.getLineNumber();
+ _beginLine = curLine;
+ foundHead = true;
+ specText.append("\n");
+ specText.append(curLine);
+ if (trimedLine.endsWith("*/")) {
+ _endLineNum = reader.getLineNumber();
+ foundHead = false;
+ if (isComment(specText.toString()))
+ continue;
+ Construct inst = SpecParser.parseSpec(specText
+ .toString());
+ if (inst instanceof InterfaceConstruct) {
+ funcDecl = readFunctionDecl(reader);
+ specConstruct = new SpecConstruct(
+ specText.toString(), file,
+ _beginLineNum, _endLineNum, inst, funcDecl);
+ } else {
+ specConstruct = new SpecConstruct(
+ specText.toString(), file,
+ _beginLineNum, _endLineNum, inst);
+ }
+ specText = new StringBuilder();
+ System.out.println(specConstruct);
+ }
+ }
+ } else {
+ specText.append("\n");
+ specText.append(curLine);
+ if (trimedLine.endsWith("*/")) {
+ _endLineNum = reader.getLineNumber();
+ foundHead = false;
+ if (isComment(specText.toString())) {
+ specText = new StringBuilder();
+ continue;
+ }
+ Construct inst = SpecParser.parseSpec(specText
+ .toString());
+ if (inst instanceof InterfaceConstruct) {
+ funcDecl = readFunctionDecl(reader);
+ specConstruct = new SpecConstruct(
+ specText.toString(), file,
+ _beginLineNum, _endLineNum, inst, funcDecl);
+ } else {
+ specConstruct = new SpecConstruct(
+ specText.toString(), file,
+ _beginLineNum, _endLineNum, inst);
+ }
+ System.out.println(specConstruct);
+ specText = new StringBuilder();
+ }
+ }
+ }
+ // At the end we can only find the head "/**" but no tail found
+ if (foundHead) {
+ String msg = "In file \"" + file.getAbsolutePath()
+ + "\", line: " + _beginLineNum + "\n" + _beginLine
+ + "\n" + "Can't find matching spec.";
+ throw new SpecNotMatchException(msg);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
+ } catch (ParseException e) {
+ printSpecInfo(file, specText.toString());
+ e.printStackTrace();
+ } catch (TokenMgrError e) {
+ printSpecInfo(file, specText.toString());
+ e.printStackTrace();
}
}
- private void parseHead(String prevLine, String line) {
- assert (_curState == State.Neutral);
-
- // "\" is the C/C++ line break. If the previous line ends with "\",
- // it may be part of a string literal.
- if (prevLine.endsWith("\\"))
- return;
- String newLine = trimBeginningSpace(line);
-// if (newLine.startsWith("/**") &&
-// (newLine.length() == 3 ||
- }
-
- private void parseBegin(String line) {
-
+ private void printSpecInfo(File file, String text) {
+ System.out.println("Error in spec!");
+ System.out.println("File: " + file.getAbsolutePath());
+ System.out.println("Begin: "
+ + _beginLineNum + " End: " + _endLineNum);
+ System.out.println(text);
}
- private void parseEnd(String line) {
-
+ private boolean isComment(String specText) {
+ if (specText.indexOf("@Begin") != -1)
+ return false;
+ return true;
}
-
- private void parseTail(String line) {
-
+
+ private String readFunctionDecl(LineNumberReader reader) throws IOException {
+ String res = "", curLine;
+ while ((curLine = reader.readLine()) != null) {
+ int braceIdx = curLine.indexOf(')');
+ if (braceIdx == -1) {
+ res = res + " " + curLine;
+ } else {
+ res = res + curLine.substring(0, braceIdx + 1);
+ res = trimSpace(res);
+ break;
+ }
+ }
+ return res;
}
-
- private String trimBeginningSpace(String line) {
- int i;
+
+ private String trimSpace(String line) {
+ int i, j;
+ char ch;
for (i = 0; i < line.length(); i++) {
- char ch = line.charAt(i);
- if (ch == ' ' || ch == '\t')
- i++;
- else
+ ch = line.charAt(i);
+ if (ch != ' ' && ch != '\t')
break;
}
- return line.substring(i);
+ for (j = line.length() - 1; j >= 0; j--) {
+ ch = line.charAt(j);
+ if (ch != ' ' && ch != '\t')
+ break;
+ }
+ if (i > j)
+ return "";
+ else
+ return line.substring(i, j + 1);
+ }
+
+ public static void main(String[] argvs) {
+ SpecExtractor extractor = new SpecExtractor();
+ File file = new File("./grammer/spec1.txt");
+ try {
+ extractor.extract(file);
+ } catch (SpecNotMatchException e) {
+ e.printStackTrace();
+ }
}
}