1 package edu.uci.eecs.specExtraction;
4 import java.util.ArrayList;
5 import java.util.HashMap;
6 import java.util.regex.Matcher;
7 import java.util.regex.Pattern;
9 import edu.uci.eecs.specExtraction.SpecUtils.IntObj;
10 import edu.uci.eecs.specExtraction.SpecUtils.Primitive;
11 import edu.uci.eecs.utilParser.ParseException;
12 import edu.uci.eecs.utilParser.UtilParser;
16 * This class is a subclass of Construct. It represents a complete interface
23 public class InterfaceConstruct extends Construct {
25 public final Code transition;
26 public final Code preCondition;
27 public final Code postCondition;
28 public final Code print;
30 // The ending line number of the specification annotation construct
31 public final int endLineNum;
33 // The ending line number of the function definition
34 private int endLineNumFunction;
35 // The function header of the corresponding interface --- The list of
36 // variable declarations that represent the RETURN value and
37 // arguments of the interface
38 private FunctionHeader funcHeader;
40 public final boolean autoGenPrint;
42 public InterfaceConstruct(File file, int beginLineNum, int endLineNum,
43 ArrayList<String> annotations) throws WrongAnnotationException {
44 super(file, beginLineNum);
45 this.endLineNum = endLineNum;
47 this.transition = new Code();
48 this.preCondition = new Code();
49 this.postCondition = new Code();
50 this.print = new Code();
52 processAnnotations(annotations);
54 autoGenPrint = print.isEmpty();
57 public FunctionHeader getFunctionHeader() {
58 return this.funcHeader;
61 public boolean equals(Object other) {
62 if (!(other instanceof InterfaceConstruct)) {
65 InterfaceConstruct o = (InterfaceConstruct) other;
66 if (o.name.equals(this.name))
72 public String getName() {
78 * This function will automatically generate the printing statements for
79 * supported types if the user has not defined the "@Print" primitive
82 * @return The auto-generated state printing statements
83 * @throws WrongAnnotationException
85 private Code generateAutoPrintFunction() {
86 Code code = new Code();
88 code.addLines(SpecUtils.generatePrintStatement(funcHeader.returnType,
91 for (VariableDeclaration decl : funcHeader.args) {
92 String type = decl.type;
93 String name = decl.name;
94 code.addLines(SpecUtils.generatePrintStatement(type, name));
101 * Assert that the interface primitive is valid; if not, throws an exception
107 * The primitive string that we have extracted earlier
108 * @throws WrongAnnotationException
110 private void assertValidPrimitive(File file, Primitive primitive)
111 throws WrongAnnotationException {
112 int lineNum = primitive.beginLineNum;
113 String name = primitive.name;
114 if (!name.equals(SpecNaming.Interface)
115 && !name.equals(SpecNaming.Transition)
116 && !name.equals(SpecNaming.PreCondition)
117 && !name.equals(SpecNaming.SideEffect)
118 && !name.equals(SpecNaming.PostCondition)
119 && !name.equals(SpecNaming.PrintValue)) {
120 WrongAnnotationException.err(file, lineNum, name
121 + " is NOT a valid CDSSpec interface primitive.");
127 * Assert that the "@Interface" primitive has correct syntax; if not, throws
128 * an exception. If so, it basically checks whether content of the primitive
129 * is a valid word and then return interface label name.
135 * Current line number
137 * The primitive string that we have extracted earlier
138 * @throws WrongAnnotationException
140 private String extractInterfaceName(File file, Primitive primitive)
141 throws WrongAnnotationException {
142 int lineNum = primitive.beginLineNum;
143 String name = primitive.name;
144 if (primitive.contents.size() != 1)
145 WrongAnnotationException.err(file, lineNum,
146 "The @Interface primitive: " + name + " has wrong syntax.");
147 String line = primitive.contents.get(0);
148 SpecUtils.matcherWord.reset(line);
149 if (!SpecUtils.matcherWord.find())
150 WrongAnnotationException.err(file, lineNum, name
151 + " is NOT a valid CDSSpec @Interface primitive.");
155 private void processAnnotations(ArrayList<String> annotations)
156 throws WrongAnnotationException {
157 IntObj curIdx = new IntObj(0);
158 Primitive primitive = null;
160 while ((primitive = SpecUtils.extractPrimitive(file, beginLineNum,
161 annotations, curIdx)) != null) {
162 String name = primitive.name;
163 assertValidPrimitive(file, primitive);
164 if (primitive.contents.size() == 0)
166 if (name.equals(SpecNaming.Interface)) {
167 this.name = extractInterfaceName(file, primitive);
168 } else if (name.equals(SpecNaming.Transition)) {
169 this.transition.addLines(primitive.contents);
170 } else if (name.equals(SpecNaming.PreCondition)) {
171 this.preCondition.addLines(primitive.contents);
172 } else if (name.equals(SpecNaming.PostCondition)) {
173 this.postCondition.addLines(primitive.contents);
174 } else if (name.equals(SpecNaming.PrintValue)) {
175 this.print.addLines(primitive.contents);
182 * This function is called to extract all the declarations that should go to
183 * the corresponding value struct --- a C++ struct to be generated for this
184 * interface that contains the information of the return value and the
189 * The line that represents the interface declaration line
190 * @throws ParseException
192 public void processFunctionDeclaration(String line) throws ParseException {
193 // FIXME: Currently we only allow the declaration to be one-liner
194 funcHeader = UtilParser.parseFuncHeader(line);
195 // Record the original declaration line
196 funcHeader.setHeaderLine(line);
198 // Once we have the compelte function declaration, we can auto-gen the
199 // print-out statements if it's not defined
201 print.addLines(generateAutoPrintFunction());
205 public String toString() {
206 StringBuilder sb = new StringBuilder();
207 sb.append(super.toString() + "\n");
208 sb.append("@Interface: " + name + "\n");
209 if (!transition.isEmpty())
210 sb.append("@Transition:\n" + transition);
211 if (!preCondition.isEmpty())
212 sb.append("@PreCondition:\n" + preCondition);
213 if (!postCondition.isEmpty())
214 sb.append("@PostCondition:\n" + postCondition);
215 if (!print.isEmpty())
216 sb.append("@Print:\n" + print + "\n");
217 sb.append(funcHeader);
219 return sb.toString();
222 public int getEndLineNumFunction() {
223 return endLineNumFunction;
226 public void setEndLineNumFunction(int endLineNumFunction) {
227 this.endLineNumFunction = endLineNumFunction;