1 /*
2 * $Header: /cvsroot/plb4jedit/plb4jedit/Plb/src/java/net/sf/plb4jedit/plb/SourceLine.java,v 1.1 2003/11/04 17:40:31 skopp Exp $
3 *
4 * Copyright 2001 Riege Software International, All Rights Reserved.
5 *
6 * This software is the proprietary information of Riege Software International
7 * Use is subject to license terms.
8 *
9 */
10 package net.sf.plb4jedit.plb;
11
12 import java.util.Comparator;
13 import java.util.Iterator;
14 import java.util.List;
15 import java.util.regex.Matcher;
16 import java.util.regex.Pattern;
17
18 import org.gjt.sp.util.Log;
19
20 /***
21 * Description: Represents a PLB-Source line, which is no comment.<br/>
22 * Parses a line from a source and determines wether it is a label, a variable, an include or a command.
23 * Gives access to these information and has some convenience methods to ask for the type of the line.
24 * <br/>
25 *
26 * Also defines some Comparators to sort SourceLines according to there lineno or in alphabetic order of their
27 * labels.
28 * <br/>
29 *
30 * A source line is scanned via a regular expression, which uses the structure/format of the PLB instruction syntax,
31 * which defines an instruction as something like
32 * <code>
33 * (LABEL) (KEYWORD) (REST)
34 * </code>
35 * where LABEL is of fix width (8 characters at RSI). Depending on the Type of the instruction LABEL can
36 * be the name of an instruction label or lroutine or a variable name. <br/>
37 * KEYWORD can be the type of a variable or a PLB command/keyword.
38 * <br/>
39 * Depending on the Type of the line, the REST can be a comment, name of an include, parameters to an lroutine.
40 * size of a variable, etc ... Be aware that for lines of Type INCLUDE only the first word of REST is taken where
41 * for other Types REST may need further parsing, because it can also contain comments or anything else.
42 *
43 * <br/>
44 * Notice that only a single Line is parsed, so e.g. for a routine which parameters a splitted over more than one
45 * line, not all parameter may be recognized. TODO: normalize PLB-Sources so that all line splits (by :) are
46 * resolved.
47 * <br/>
48 * @author Peter Schaefer
49 * @version $Header: /cvsroot/plb4jedit/plb4jedit/Plb/src/java/net/sf/plb4jedit/plb/SourceLine.java,v 1.1 2003/11/04 17:40:31 skopp Exp $
50 */
51
52 public class SourceLine {
53 final public static String cvsId =
54 "$Header: /cvsroot/plb4jedit/plb4jedit/Plb/src/java/net/sf/plb4jedit/plb/SourceLine.java,v 1.1 2003/11/04 17:40:31 skopp Exp $";
55
56 private String line;
57 private Type type;
58 private int lineNumber;
59 private String label;
60 private String keyword;
61 private String rest;
62 private boolean isLabel;
63
64 /*** maximal possible width of a plb label, TODO: define via jEdit-Property, Plugin Option pane */
65 private static String LABEL_WIDTH = "8";
66 /***
67 * regular expression used to split a line intot a LABEL (group 0), a KEYWORD (group 1) and the Rest up to
68 * the end of the line
69 */
70 private static final Pattern SYNTAX =
71 Pattern.compile(
72 "(^[ a-zA-Z#$_0-9]{1,"+LABEL_WIDTH+"})//s*([a-zA-Z\".0-9]{0,10})//s*(.*)$");
73
74 private static final Pattern RECORDLIKE =
75 Pattern.compile(
76 "^//s*like//s*([a-zA-Z#$_0-9]{1,"+LABEL_WIDTH+"}).*$");
77
78 private static final Pattern RECORDARRAYLIKE =
79 Pattern.compile(
80 "^//s*//(//d//)//s*like//s*([a-zA-Z#$_0-9]{1,"+LABEL_WIDTH+"}).*$");
81 /***
82 * Constructs a SourceLine for a given line and it position of occurence in a file
83 * being nested inside record definitions.
84 * @param line one line of a Source file
85 * @param lineNumber where the line appears in the source file.
86 * @param records a list of records where this line is nested in
87 */
88 public SourceLine(String line, int lineNumber, List records) {
89 this(line,lineNumber);
90 StringBuffer recordPrefix = new StringBuffer();
91 Iterator it = records.iterator();
92 while (it.hasNext()) {
93 recordPrefix.append(it.next().toString());
94 recordPrefix.append(".");
95 }
96 label = recordPrefix.toString() + label;
97 }
98
99 /***
100 * Constructs a SourceLine for a given line and it position of occurence in a file.
101 * @param line one line of a Source file
102 * @param lineNumber where the line appears in the source file.
103 */
104 public SourceLine(String line, int lineNumber) {
105 this.isLabel = false;
106 this.line = line;
107 this.lineNumber = lineNumber;
108 this.label = "";
109 this.keyword = "";
110 this.rest = "";
111 if (line.startsWith(".")) {
112 type = Type.COMMENT;
113 } else if (line.trim().length() == 0) {
114 type = Type.EMPTY;
115 } else { // can be VARDEF, ROUTINE, COMMAND, INCLUDE
116 Matcher aMatcher = SYNTAX.matcher(line);
117 if (aMatcher.matches()) {
118 label = aMatcher.group(1).trim();
119 keyword = aMatcher.group(2).trim();
120 rest = aMatcher.group(3).trim();
121 //String comment = "";//aMatcher.group(4).trim();
122 if (keyword.equals("inc")) {
123 type = Type.INCLUDE;
124 rest = getFirstWord(rest);
125 if (label.length() > 0) {
126 isLabel = true;
127 }
128 } else if (
129 keyword.equals("afile")
130 || keyword.equals("bfile")
131 || keyword.equals("comfile")
132 || keyword.equals("const")
133 || keyword.equals("dbfile")
134 || keyword.equals("define")
135 || keyword.equals("dim")
136 || keyword.equals("equ")
137 || keyword.equals("equate")
138 || keyword.equals("file")
139 || keyword.equals("filelist")
140 || keyword.equals("form")
141 || keyword.equals("ifile")
142 || keyword.equals("init")
143 || keyword.equals("integer")
144 || keyword.equals("list")
145 || keyword.equals("pfile")
146 || keyword.equals("plform")
147 || keyword.equals("record")
148 || keyword.equals("sndfile")
149 || keyword.equals("varlist")
150 ) {
151 type = Type.VARDEF;
152 } else if (
153 keyword.equals("external")
154 || keyword.equals("lroutine")
155 || keyword.equals("macro")
156 ) {
157 type = Type.ROUTINE;
158 isLabel = true;
159 } else if (!(
160 keyword.equals("recordend")
161 || keyword.equals("listend")
162 || keyword.equals("mend")
163 )) {
164 type = Type.COMMAND;
165 if (label.length() > 0) {
166 isLabel = true;
167 }
168 } else {
169 type = Type.UNKNOWN;
170 }
171 } else {
172 Log.log(
173 Log.DEBUG,
174 this,
175 "SYNTAX pattern doesn't match " + lineNumber + ":" + line);
176 }
177 }
178 }
179
180 /***
181 * helper to get the first word out of s.
182 * TODO: better recognition of more whitespaces ?!; only used to get proper include names
183 * out or rest at the moment
184 * @param s trimmed string, so that it doesn't start with whitespaces.
185 * @return
186 */
187 private String getFirstWord(String s) {
188 if (s.indexOf(" ") >= 0) {
189 return s.substring(0, s.indexOf(" ")).trim();
190 } else if (s.indexOf("\t") >= 0) {
191 return s.substring(0, s.indexOf(" ")).trim();
192 } else {
193 return s;
194 }
195 }
196
197 /***
198 *
199 * @return true if SourceLine defines a label
200 */
201 public boolean isLabel() {
202 return isLabel;
203 }
204
205 /***
206 * gets the label of the line, see class documentation. Depending on Type of the line
207 * this may be an execution label/lroutine or variable definition.
208 * @return the label of this line
209 */
210 public String getLabel() {
211 return label;
212 }
213
214 /***
215 *
216 * @return the whole line.
217 */
218 public String getLine() {
219 return line;
220 }
221
222 /***
223 *
224 * @return line number
225 */
226 public int getLineNumber() {
227 return lineNumber;
228 }
229
230 /***
231 * gets keyword of the line. Depending on the Type of the line this may be
232 * the variable type, or a PLB keyword (like e.g. inc, lroutine, move, ....)
233 * @return the KEYWORD of the line, see class documentation
234 */
235 public String getKeyword() {
236 return keyword;
237 }
238
239 /***
240 * gets rest of the line. Content depends on Type. See class documentation.
241 * @return rest of the line
242 */
243 public String getRest() {
244 return rest;
245 }
246
247 /***
248 * gets the Type of the line, which indicates if the line is a comment, a variable definition,
249 * an execution label or a command.
250 * @return type of the line.
251 */
252 public Type getType() {
253 return type;
254 }
255
256 /***
257 *
258 * @return true if the line defines a dim
259 */
260 public boolean isDimDef() {
261 return (
262 type == Type.VARDEF
263 && (keyword.equals("dim") || keyword.equals("init")));
264 }
265
266 /***
267 *
268 * @return true if the line defines a form.
269 */
270 public boolean isFormDef() {
271 return (type == Type.VARDEF && keyword.equals("form"));
272 }
273
274 /***
275 *
276 * NOTE: records defined via like and record arrays are currently not supported
277 *
278 * @return true if the line defines the beginning of a record definition.
279 */
280 public boolean isRecordDef() {
281 return ( (type == Type.VARDEF)
282 && (keyword.equals("record"))
283 && (!RECORDLIKE.matcher(rest).matches())
284 && (!RECORDARRAYLIKE.matcher(rest).matches())
285 );
286 }
287
288 /***
289 *
290 * @return true if the line defines the end of a record definition.
291 */
292 public boolean isRecordEnd() {
293 return (keyword.equals("recordend"));
294 }
295
296 /***
297 *
298 * @return true if the line defines a lroutine.
299 */
300 public boolean isLroutine() {
301 return (type == Type.ROUTINE);
302 }
303
304 /***
305 *
306 * @return true if the line includes another file
307 */
308 public boolean isInclude() {
309 return (type == Type.INCLUDE);
310 }
311
312 /***
313 *
314 * @return true if the line defines a variable
315 */
316 public boolean isVarDef() {
317 return (type == Type.VARDEF);
318 }
319
320 public String toString() {
321 if (isLabel()) {
322 return lineNumber
323 + " is a "
324 + type
325 + ":"
326 + label.toUpperCase()
327 + " "
328 + keyword
329 + " "
330 + rest;
331 } else {
332 return lineNumber
333 + " is a "
334 + type
335 + ":"
336 + " "
337 + " "
338 + keyword
339 + " "
340 + rest;
341 }
342 }
343
344 public int compareTo(Object obj) {
345 SourceLine aLine = (SourceLine) obj;
346 return aLine.getLineNumber() - this.getLineNumber();
347 }
348
349 public static final Comparator LINE_NUMBER_ORDERED = new Comparator() {
350 public int compare(Object obj1, Object obj2) {
351 SourceLine aLine = (SourceLine) obj1;
352 SourceLine bLine = (SourceLine) obj2;
353 return aLine.getLineNumber() - bLine.getLineNumber();
354 }
355 };
356
357 public static final Comparator LABEL_ORDERED = new Comparator() {
358 public int compare(Object obj1, Object obj2) {
359 SourceLine aLine = (SourceLine) obj1;
360 SourceLine bLine = (SourceLine) obj2;
361 int res;
362 if ((res = aLine.getLabel().compareToIgnoreCase(bLine.getLabel()))
363 != 0) {
364 return res;
365 }
366 res = aLine.getLineNumber() - bLine.getLineNumber();
367 return res;
368 }
369 };
370
371 public static final Comparator REST_ORDERED = new Comparator() {
372 public int compare(Object obj1, Object obj2) {
373 SourceLine aLine = (SourceLine) obj1;
374 SourceLine bLine = (SourceLine) obj2;
375 int res;
376 if ((res = aLine.getRest().compareToIgnoreCase(bLine.getRest()))
377 != 0) {
378 return res;
379 }
380 res = aLine.getLineNumber() - bLine.getLineNumber();
381 return res;
382 }
383 };
384 }
This page was automatically generated by Maven