minor fix
[cdsspec-compiler.git] / src / edu / uci / eecs / specExtraction / Code.java
1 package edu.uci.eecs.specExtraction;
2
3 import java.util.ArrayList;
4
5 import edu.uci.eecs.specExtraction.SpecUtils.IntObj;
6
7 /**
8  * <p>
9  * This class represents a piece of code --- a list of strings (lines). Such a
10  * wrapper makes code extraction and generation easier.
11  * </p>
12  * 
13  * @author Peizhao Ou
14  * 
15  */
16 public class Code {
17
18         // The list that represents all the lines of this code snippet
19         public final ArrayList<String> lines;
20
21         public Code() {
22                 lines = new ArrayList<String>();
23         }
24
25         /**
26          * <p>
27          * It adds a line, which is very likely to be a simple C/C++ statement,
28          * which is a string lines of statement.
29          * </p>
30          * 
31          * @param line
32          *            A C/C++ line of statement
33          */
34         public void addLine(String line) {
35                 lines.add(line);
36         }
37
38         /**
39          * <p>
40          * It adds a list of lines, which are very likely to be simple C/C++
41          * statements.
42          * </p>
43          * 
44          * @param line
45          *            A list of C/C++ lines of statement
46          */
47         public void addLines(ArrayList<String> code) {
48                 for (int i = 0; i < code.size(); i++)
49                         lines.add(code.get(i));
50         }
51
52         /**
53          * <p>
54          * It adds a list of lines, which are very likely to be simple C/C++
55          * statements.
56          * </p>
57          * 
58          * @param line
59          *            A Code object --- list of C/C++ lines of statement
60          */
61         public void addLines(Code code) {
62                 addLines(code.lines);
63         }
64
65         /**
66          * @return Whether this code snippet is empty
67          */
68         public boolean isEmpty() {
69                 return lines.size() == 0;
70         }
71
72         /**
73          * <p>
74          * Align the set of code with an initial number of tabs. This basically
75          * tries to make the generated code more readable.
76          * 
77          * @param initialTabsCnt
78          *            The number of tabs that we want to put before the code
79          *            initially.
80          */
81         public void align(int initialTabsCnt) {
82                 int tabLevel = initialTabsCnt;
83                 IntObj idx = new IntObj(0);
84                 alignHelper(idx, tabLevel, false);
85         }
86
87         /**
88          * <p>
89          * This is a helper function to align a list of code. Caller should
90          * initialize an IntObj with intial value "0", and pass with the initial tab
91          * level and pass the value of "false" to the noBraceKeyword.
92          * 
93          * @param idx
94          *            The IntObj that represents the current index of the code lines
95          * @param tabLevel
96          *            The tab level we are currently at
97          * @param noBraceKeyword
98          *            Whether we just encountered a "noBraceKeyword"
99          */
100         private void alignHelper(IntObj idx, int tabLevel, boolean noBraceKeyword) {
101                 for (; idx.getVal() < lines.size(); idx.inc()) {
102                         String curLine = lines.get(idx.getVal());
103                         String newLine = null;
104                         // Return to the previous recursive level
105                         if (closingBrace(curLine)) {
106                                 return;
107                         }
108                         if ((noBraceKeyword && !keywordBrace(curLine) && !keywordNoBrace(curLine))) {
109                                 // Before returning, we just need to first add the line with the
110                                 // current tab
111                                 newLine = makeTabs(tabLevel) + curLine;
112                                 lines.set(idx.getVal(), newLine);
113                                 return;
114                         }
115
116                         newLine = makeTabs(tabLevel) + curLine;
117                         lines.set(idx.getVal(), newLine);
118
119                         if (keywordBrace(curLine)) {
120                                 idx.inc();
121                                 alignHelper(idx, tabLevel + 1, false);
122                                 // Add the closing line
123                                 curLine = lines.get(idx.getVal());
124                                 newLine = makeTabs(tabLevel) + curLine;
125                                 lines.set(idx.getVal(), newLine);
126                         } else if (keywordNoBrace(curLine)) { // No brace
127                                 idx.inc();
128                                 alignHelper(idx, tabLevel + 1, true);
129                                 if (noBraceKeyword)
130                                         return;
131                         }
132                 }
133         }
134
135         /**
136          * <p>
137          * Lines that starts with a key word and ends with ";".
138          * </p>
139          * 
140          * @param curLine
141          * @return
142          */
143         private boolean closingBrace(String curLine) {
144                 return curLine.endsWith("}");
145         }
146
147         /**
148          * <p>
149          * Lines that starts with a key word and ends with "{".
150          * </p>
151          * 
152          * @param curLine
153          * @return
154          */
155         private boolean keywordBrace(String curLine) {
156                 return (curLine.startsWith("for") || curLine.startsWith("ForEach")
157                                 || curLine.startsWith("if") || curLine.startsWith("else")
158                                 || curLine.startsWith("while") || curLine.startsWith("do"))
159                                 && curLine.endsWith("{");
160         }
161
162         /**
163          * <p>
164          * Lines that starts with a key word and ends with no "{" and no ";".
165          * </p>
166          * 
167          * @param curLine
168          * @return
169          */
170         private boolean keywordNoBrace(String curLine) {
171                 return (curLine.startsWith("for") || curLine.startsWith("ForEach")
172                                 || curLine.startsWith("if") || curLine.startsWith("else")
173                                 || curLine.startsWith("while") || curLine.startsWith("do"))
174                                 && !curLine.endsWith("{") && !curLine.endsWith(";");
175         }
176
177         /**
178          * @param tabCnt
179          *            The number of tabs
180          * @return Generate a string whose content is a specific number (tabCnt) of
181          *         tab symbols.
182          */
183         private String makeTabs(int tabCnt) {
184                 String res = "";
185                 for (int i = 0; i < tabCnt; i++)
186                         res = res + "\t";
187                 return res;
188         }
189
190         public String toString() {
191                 StringBuilder sb = new StringBuilder();
192                 for (int i = 0; i < lines.size(); i++) {
193                         sb.append(lines.get(i) + "\n");
194                 }
195                 return sb.toString();
196         }
197 }