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 sideEffect;
28 public final Code postCondition;
29 public final Code print;
31 // The ending line number of the specification annotation construct
32 public final int endLineNum;
34 // The ending line number of the function definition
35 private int endLineNumFunction;
36 // The function header of the corresponding interface --- The list of
37 // variable declarations that represent the RETURN value and
38 // arguments of the interface
39 private FunctionHeader funcHeader;
41 public InterfaceConstruct(File file, int beginLineNum, int endLineNum,
42 ArrayList<String> annotations) throws WrongAnnotationException {
43 super(file, beginLineNum);
44 this.endLineNum = endLineNum;
46 this.transition = new Code();
47 this.preCondition = new Code();
48 this.sideEffect = new Code();
49 this.postCondition = new Code();
50 this.print = new Code();
52 processAnnotations(annotations);
55 public FunctionHeader getFunctionHeader() {
56 return this.funcHeader;
59 public boolean equals(Object other) {
60 if (!(other instanceof InterfaceConstruct)) {
63 InterfaceConstruct o = (InterfaceConstruct) other;
64 if (o.name.equals(this.name))
70 public String getName() {
76 * Assert that the interface primitive is valid; if not, throws an exception
82 * The primitive string that we have extracted earlier
83 * @throws WrongAnnotationException
85 private void assertValidPrimitive(File file, Primitive primitive)
86 throws WrongAnnotationException {
87 int lineNum = primitive.beginLineNum;
88 String name = primitive.name;
89 if (!name.equals(SpecNaming.Interface)
90 && !name.equals(SpecNaming.Transition)
91 && !name.equals(SpecNaming.PreCondition)
92 && !name.equals(SpecNaming.SideEffect)
93 && !name.equals(SpecNaming.PostCondition)
94 && !name.equals(SpecNaming.PrintValue)) {
95 WrongAnnotationException.err(file, lineNum, name
96 + " is NOT a valid CDSSpec interface primitive.");
102 * Assert that the "@Interface" primitive has correct syntax; if not, throws
103 * an exception. If so, it basically checks whether content of the primitive
104 * is a valid word and then return interface label name.
110 * Current line number
112 * The primitive string that we have extracted earlier
113 * @throws WrongAnnotationException
115 private String extractInterfaceName(File file, Primitive primitive)
116 throws WrongAnnotationException {
117 int lineNum = primitive.beginLineNum;
118 String name = primitive.name;
119 if (primitive.contents.size() != 1)
120 WrongAnnotationException.err(file, lineNum,
121 "The @Interface primitive: " + name + " has wrong syntax.");
122 String line = primitive.contents.get(0);
123 SpecUtils.matcherWord.reset(line);
124 if (!SpecUtils.matcherWord.find())
125 WrongAnnotationException.err(file, lineNum, name
126 + " is NOT a valid CDSSpec @Interface primitive.");
130 private void processAnnotations(ArrayList<String> annotations)
131 throws WrongAnnotationException {
132 IntObj curIdx = new IntObj(0);
133 Primitive primitive = null;
135 while ((primitive = SpecUtils.extractPrimitive(file, beginLineNum,
136 annotations, curIdx)) != null) {
137 String name = primitive.name;
138 assertValidPrimitive(file, primitive);
139 if (primitive.contents.size() == 0)
141 if (name.equals(SpecNaming.Interface)) {
142 this.name = extractInterfaceName(file, primitive);
143 } else if (name.equals(SpecNaming.Transition)) {
144 this.transition.addLines(primitive.contents);
145 } else if (name.equals(SpecNaming.PreCondition)) {
146 this.preCondition.addLines(primitive.contents);
147 } else if (name.equals(SpecNaming.SideEffect)) {
148 this.sideEffect.addLines(primitive.contents);
149 } else if (name.equals(SpecNaming.PostCondition)) {
150 this.postCondition.addLines(primitive.contents);
151 } else if (name.equals(SpecNaming.PrintValue)) {
152 this.print.addLines(primitive.contents);
159 * This function is called to extract all the declarations that should go to
160 * the corresponding value struct --- a C++ struct to be generated for this
161 * interface that contains the information of the return value and the
166 * The line that represents the interface declaration line
167 * @throws ParseException
169 public void processFunctionDeclaration(String line) throws ParseException {
170 // FIXME: Currently we only allow the declaration to be one-liner
171 funcHeader = UtilParser.parseFuncHeader(line);
172 // Record the original declaration line
173 funcHeader.setHeaderLine(line);
176 public String toString() {
177 StringBuilder sb = new StringBuilder();
178 sb.append(super.toString() + "\n");
179 sb.append("@Interface: " + name + "\n");
180 if (!transition.isEmpty())
181 sb.append("@Transition:\n" + transition);
182 if (!preCondition.isEmpty())
183 sb.append("@PreCondition:\n" + preCondition);
184 if (!sideEffect.isEmpty())
185 sb.append("@SideEffect:\n" + sideEffect);
186 if (!postCondition.isEmpty())
187 sb.append("@PostCondition:\n" + postCondition);
188 if (!print.isEmpty())
189 sb.append("@Print:\n" + print + "\n");
190 sb.append(funcHeader);
192 return sb.toString();
195 public int getEndLineNumFunction() {
196 return endLineNumFunction;
199 public void setEndLineNumFunction(int endLineNumFunction) {
200 this.endLineNumFunction = endLineNumFunction;