KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > SOFA > SOFAnode > Util > DFSRChecker > parser > Builder


1 /*
2  * $Id: Builder.java,v 1.5 2005/07/13 07:27:49 kofron Exp $
3  *
4  * Copyright 2004
5  * Distributed Systems Research Group
6  * Department of Software Engineering
7  * Faculty of Mathematics and Physics
8  * Charles University, Prague
9  *
10  * Copyright 2005
11  * Formal Methods In Software Engineering Group
12  * Institute of Computer Science
13  * Academy of Sciences of the Czech Republic
14  *
15  * This code was originally developed by
16  * Stanislav Visnovsky <visnovsky@nenya.ms.mff.cuni.cz>
17  * and significantly extended by Jan Kofron <kofron@nenya.ms.mff.cuni.cz>
18  */

19  
20
21 package SOFA.SOFAnode.Util.DFSRChecker.parser;
22
23 import java.io.*;
24 import java.util.*;
25
26 import SOFA.SOFAnode.Util.DFSRChecker.DFSR.Options;
27 import SOFA.SOFAnode.Util.DFSRChecker.node.ActionRepository;
28 import SOFA.SOFAnode.Util.DFSRChecker.node.AdjustmentNode;
29 import SOFA.SOFAnode.Util.DFSRChecker.node.AlternativeNode;
30 import SOFA.SOFAnode.Util.DFSRChecker.node.AndParallelNode;
31 import SOFA.SOFAnode.Util.DFSRChecker.node.AtomicNode;
32 import SOFA.SOFAnode.Util.DFSRChecker.node.CompositionNode;
33 import SOFA.SOFAnode.Util.DFSRChecker.node.EventNode;
34 import SOFA.SOFAnode.Util.DFSRChecker.node.NullNode;
35 import SOFA.SOFAnode.Util.DFSRChecker.node.RepetitionNode;
36 import SOFA.SOFAnode.Util.DFSRChecker.node.RestrictionNode;
37 import SOFA.SOFAnode.Util.DFSRChecker.node.SequenceNode;
38 import SOFA.SOFAnode.Util.DFSRChecker.node.TreeNode;
39 import SOFA.SOFAnode.Util.DFSRChecker.node.ConsentNode;
40 import SOFA.SOFAnode.Util.SyntaxErrorException;
41
42
43 /**
44  * This original code was written by
45  *
46  * Stanislav Visnovsky
47  *
48  * to be used by his checker in SOFAnode. I decided to reuse this part because
49  * the parser (class Builder) is exactly what I needed for my
50  * SOFA.SOFAnode.Util.objectweb.fractal.behprotocols.checker.
51  *
52  * The class for building the automata from a given behavior protocol. A
53  * protocol is passed not into constructor, thus, one instance can be used for
54  * building any number of automata.
55  */

56 public class Builder {
57
58     /**
59      * multinode optimization enabled
60      */

61     private boolean MULTINODES = true;
62
63     /**
64      * next char for LL(1) parsing
65      */

66     private char next_char;
67
68     /**
69      * a reader which contains a behavior protocol to be parsed and built
70      */

71     private ProtocolReader source;
72
73     /**
74      * next token for LL(1) parsing
75      */

76     private String JavaDoc next_token;
77
78     /**
79      * flag for indicating the action token read
80      */

81     private boolean isTokenID;
82
83     /**
84      * action repository for storing the action names and their indices
85      */

86     private ActionRepository repository;
87
88     /**
89      * protocol being parsed
90      */

91     private String JavaDoc protocol;
92
93     /**
94      * Creates new instance of Builder and stores the reference to the action
95      * repository object
96      */

97     public Builder(ActionRepository repository) {
98         this.repository = repository;
99         this.MULTINODES = Options.multinodes;
100     }
101
102     /**
103      * Inverse of the action Check the first character of the string and returns
104      * the complementary action
105      *
106      * @param src source string containing the action description
107      * @return the string containing the complement operation
108      */

109     static private String JavaDoc getReverseAction(String JavaDoc src) {
110         String JavaDoc e;
111         if (src.startsWith("!"))
112             e = (new String JavaDoc("?")).concat(src.substring(1));
113         else if (src.startsWith("?"))
114             e = (new String JavaDoc("!")).concat(src.substring(1));
115         else
116             e = new String JavaDoc(src);
117         return e;
118     }
119
120     /**
121      * Check if the given action is a simple call (i.e. not a response, a
122      * request, a general event and a special event)
123      *
124      * @param src source string containing the action description
125      * @return true if this is a simple call
126      */

127     static private boolean isSimpleCall(String JavaDoc src) {
128         return !(src.endsWith("^") || src.endsWith("$") || src.endsWith("~") || src.endsWith("["));
129     }
130
131     /**
132      * Test for character to be a letter (case insensitive).
133      * @param ch character to be tested
134      * @return result of the test
135      * @see Builder#nextToken
136      */

137     private boolean isLetter(char ch) {
138         return (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch == '_') || (ch >= '0' && ch <= '9');
139     }
140
141     /**
142      * Test for character to be a whitespace.
143      *
144      * @param ch
145      * character to be tested
146      * @return result of the test
147      */

148     public static boolean isWhiteSpace(char ch) {
149         return ((ch == ' ') || (ch == '\t') || (ch == '\n'));
150     }
151     
152     private void nextPart(String JavaDoc part) {
153         protocol += part;
154         Debug.print(2, part);
155     }
156
157     /**
158      * Read the next token from the reader. In case of action token, indicate it
159      * by the isTokenID flag.
160      *
161      * @return read token, or token EOF
162      * @throws SyntaxErrorException
163      * in case of badly formed protocols
164      * @see Builder#isTokenID
165      */

166     private String JavaDoc nextToken() throws SyntaxErrorException, IOException {
167         String JavaDoc result;
168         isTokenID = false;
169         if (!source.ready()) {
170             Debug.println(2, "");
171             return "";
172         }
173         while (isWhiteSpace(next_char))
174             // skip whitespaces
175
if (source.ready()) {
176                 protocol += " ";
177                 next_char = (char) source.read();
178             }
179             else {
180                 Debug.println(2, "");
181                 return "";
182             }
183         switch (next_char) {
184         case (char) -1: {
185             Debug.println(2, "");
186             return "";
187         }
188         case '|':
189             next_char = (char) source.read();
190             if (next_char == '|') {
191                 next_char = (char) source.read();
192                 nextPart("||");
193                 return "||";
194             } else {
195                 nextPart("|");
196                 return "|";
197             }
198         case '&':
199             next_char = (char) source.read();
200             nextPart("&");
201             return "&";
202         case '@':
203             next_char = (char) source.read();
204             nextPart("@");
205             return "@";
206         case '.':
207             next_char = (char) source.read();
208             nextPart(".");
209             return ".";
210         case '*':
211             next_char = (char) source.read();
212             nextPart("*");
213             return "*";
214         case '+':
215             next_char = (char) source.read();
216             nextPart("+");
217             return "+";
218         case ';':
219             next_char = (char) source.read();
220             nextPart(";");
221             return ";";
222         case ',':
223             next_char = (char) source.read();
224             nextPart(",");
225             return ",";
226         case '\\':
227             next_char = (char) source.read();
228             nextPart("\\");
229             return "\\";
230         case '{':
231             next_char = (char) source.read();
232             nextPart("{");
233             return "{";
234         case '}':
235             next_char = (char) source.read();
236             nextPart("}");
237             return "}";
238         case '(':
239             next_char = (char) source.read();
240             nextPart("(");
241             return "(";
242         case ')':
243             next_char = (char) source.read();
244             nextPart(")");
245             return ")";
246         case '[':
247             next_char = (char) source.read();
248             nextPart("[");
249             return "[";
250             
251         case ']':
252             next_char = (char) source.read();
253             nextPart("]");
254             return "]";
255             
256         /*
257         case '[':
258             result = "[";
259             next_char = (char) source.read();
260             while (next_char != ']') {
261                 result += next_char;
262                 next_char = (char) source.read();
263             }
264             result += next_char;
265             next_char = (char) source.read();
266             isTokenID = true;
267             nextPart(result);
268             return result;
269         */

270         default:
271             if (isLetter(next_char) || next_char == '?' || next_char == '!' || next_char == '<' || next_char == '#') {
272                 result = "";
273                 if (next_char == '!' || next_char == '?' || next_char == '#') {
274                     result = result + next_char;
275                     next_char = (char) source.read();
276                 }
277                 if (next_char == '<') {
278                     do {
279                         result = result + next_char;
280                         next_char = (char) source.read();
281                     } while (next_char != '>');
282                     result = result + next_char;
283                     next_char = (char) source.read();
284                 } else {
285                     while (isLetter(next_char)) {
286                         result = result + next_char;
287                         next_char = (char) source.read();
288                     }
289                 }
290                 if (next_char != '.') {
291                     if (result.equals("NULL")) {
292                         isTokenID = true;
293                         nextPart(result);
294                         return result;
295                     }
296                     throw new SyntaxErrorException("invalide event name: dot delimiter expected in event name, found " + next_char + " after " + result);
297                 } else
298                     result = result + next_char;
299                 next_char = (char) source.read();
300                 while (isLetter(next_char)) {
301                     result = result + next_char;
302                     next_char = (char) source.read();
303                 }
304                 if (next_char == '^' || next_char == '$' || next_char == '~') {
305                     result = result + next_char;
306                     next_char = (char) source.read();
307                 }
308                 isTokenID = true;
309                 nextPart(result);
310                 return result;
311             }
312             throw new SyntaxErrorException("Unexpected literal with code " + (int) next_char);
313         }
314     }
315
316
317     /**
318      * Builds protocol for + operator.
319      *
320      * @return built protocol
321      * @throws SyntaxErrorException
322      * in case of badly formed protocols
323      * @throws IOException
324      * in case of unexpected end of reader
325      *
326      */

327     private TreeNode alternative() throws SyntaxErrorException, IOException {
328         Vector nodelist = new Vector();
329
330         Vector protindices = new Vector();
331         protindices.add(new Integer JavaDoc(source.getIndex() - next_token.length() - 1));
332
333         nodelist.add(sequence());
334         while (next_token == "+") {
335             next_token = nextToken();
336             nodelist.add(sequence());
337             protindices.add(new Integer JavaDoc(source.getIndex() - next_token.length() - (next_token.length() > 0 ? 1 : 0)));
338         }
339
340         //protindices.add(new
341
// Integer(((Integer)protindices.lastElement()).intValue() - 1));
342

343         if (nodelist.size() > 1) {
344             if (MULTINODES) {
345                 TreeNode[] nodes = new TreeNode[nodelist.size()];
346                 for (int i = 0; i < nodelist.size(); ++i)
347                     nodes[i] = (TreeNode) nodelist.get(i);
348
349                 TreeNode newnode = new AlternativeNode(nodes);
350                 newnode.protocol = protocol.substring(((Integer JavaDoc) protindices.get(0)).intValue(), ((Integer JavaDoc) protindices.lastElement()).intValue());
351                 return newnode;
352             }
353
354             else {
355                 TreeNode[] nodes = new TreeNode[2];
356                 TreeNode result = (TreeNode) nodelist.get(0);
357
358                 for (int i = 1; i < nodelist.size(); ++i) {
359                     nodes = new TreeNode[2];
360                     nodes[0] = result;
361                     nodes[1] = (TreeNode) nodelist.get(i);
362                     result = new AlternativeNode(nodes);
363                     result.protocol = protocol.substring(((Integer JavaDoc) protindices.get(0)).intValue(), ((Integer JavaDoc) protindices.get(i)).intValue());
364                 }
365
366                 return result;
367             }
368         } else {
369             return (TreeNode) nodelist.get(0);
370         }
371     }
372
373     /**
374      * Builds protocol for ; operator.
375      *
376      * @return built automaton
377      * @throws SyntaxErrorException
378      * in case of badly formed protocols
379      * @throws IOException
380      * in case of unexpected end of reader
381      *
382      *
383      */

384     private TreeNode sequence() throws SyntaxErrorException, IOException {
385         Vector nodelist = new Vector();
386         Vector protindices = new Vector();
387         protindices.add(new Integer JavaDoc(source.getIndex() - next_token.length() - 1));
388
389         nodelist.add(andparallel());
390
391         while (next_token == ";") {
392             next_token = nextToken();
393             nodelist.add(andparallel());
394             protindices.add(new Integer JavaDoc(source.getIndex() - next_token.length() - (next_token.length() > 0 ? 1 : 0)));
395         }
396
397         //protindices.add(new
398
// Integer(((Integer)protindices.lastElement()).intValue() - 1));
399

400         if (nodelist.size() > 1) {
401             if (MULTINODES) {
402                 TreeNode[] nodes = new TreeNode[nodelist.size()];
403                 for (int i = 0; i < nodelist.size(); ++i)
404                     nodes[i] = (TreeNode) nodelist.get(i);
405
406                 TreeNode newnode = new SequenceNode(nodes);
407                 newnode.protocol = protocol.substring(((Integer JavaDoc) protindices.get(0)).intValue(), ((Integer JavaDoc) protindices.lastElement()).intValue());
408                 return newnode;
409             } else {
410                 TreeNode[] nodes = new TreeNode[2];
411                 TreeNode result = (TreeNode) nodelist.get(0);
412
413                 for (int i = 1; i < nodelist.size(); ++i) {
414                     nodes = new TreeNode[2];
415                     nodes[0] = result;
416                     nodes[1] = (TreeNode) nodelist.get(i);
417                     result = new SequenceNode(nodes);
418                     result.protocol = protocol.substring(((Integer JavaDoc) protindices.get(0)).intValue(), ((Integer JavaDoc) protindices.get(i)).intValue());
419                 }
420
421                 return result;
422             }
423
424         } else {
425             return (TreeNode) nodelist.get(0);
426         }
427     }
428
429     /**
430      * Builds protocol for | operator.
431      *
432      * @return built protocol
433      * @throws SyntaxErrorException
434      * in case of badly formed protocols
435      * @throws IOException
436      * in case of unexpected end of reader
437      *
438      * @see Builder#orparallel
439      */

440     private TreeNode andparallel() throws SyntaxErrorException, IOException {
441         Vector nodelist = new Vector();
442         Vector protindices = new Vector();
443         protindices.add(new Integer JavaDoc(source.getIndex() - next_token.length() - 1));
444
445         nodelist.add(orparallel());
446         while (next_token == "|") {
447             next_token = nextToken();
448             nodelist.add(orparallel());
449             protindices.add(new Integer JavaDoc(source.getIndex() - next_token.length() - (next_token.length() > 0 ? 1 : 0)));
450         }
451         //protindices.add(new
452
// Integer(((Integer)protindices.lastElement()).intValue() - 1));
453

454         if (nodelist.size() > 1) {
455             if (MULTINODES) {
456                 TreeNode[] nodes = new TreeNode[nodelist.size()];
457                 for (int i = 0; i < nodelist.size(); ++i)
458                     nodes[i] = (TreeNode) nodelist.get(i);
459
460                 TreeNode newnode = new AndParallelNode(nodes);
461                 newnode.protocol = protocol.substring(((Integer JavaDoc) protindices.get(0)).intValue(), ((Integer JavaDoc) protindices.lastElement()).intValue());
462                 return newnode;
463             } else {
464                 TreeNode[] nodes = new TreeNode[2];
465                 TreeNode result = (TreeNode) nodelist.get(0);
466
467                 for (int i = 1; i < nodelist.size(); ++i) {
468                     nodes = new TreeNode[2];
469                     nodes[0] = result;
470                     nodes[1] = (TreeNode) nodelist.get(i);
471                     result = new AndParallelNode(nodes);
472                     result.protocol = protocol.substring(((Integer JavaDoc) protindices.get(0)).intValue(), ((Integer JavaDoc) protindices.get(i)).intValue());
473                 }
474
475                 return result;
476             }
477
478         } else {
479             return (TreeNode) nodelist.get(0);
480         }
481
482     }
483
484     /**
485      * Builds protocol for || operator.
486      *
487      * @return built protocol
488      * @throws SyntaxErrorException
489      * in case of badly formed protocols
490      * @throws IOException
491      * in case of unexpected end of reader
492      *
493      * @see Builder#term
494      */

495     private TreeNode orparallel() throws SyntaxErrorException, IOException {
496         Vector nodelist = new Vector();
497         Vector protindices = new Vector();
498         protindices.add(new Integer JavaDoc(source.getIndex() - next_token.length() - 1));
499
500         nodelist.add(term());
501         while (next_token == "||") {
502             next_token = nextToken();
503             nodelist.add(term());
504             protindices.add(new Integer JavaDoc(source.getIndex() - next_token.length() - (next_token.length() > 0 ? 1 : 0)));
505         }
506
507         //protindices.set(protindices.size() - 1, new
508
// Integer(((Integer)protindices.lastElement()).intValue() - 1));
509
//protindices.add(new
510
// Integer(((Integer)protindices.lastElement()).intValue() -
511
// next_token.length()));
512

513         TreeNode result = (TreeNode) nodelist.get(0);
514         for (int i = 1; i < nodelist.size(); ++i) {
515             
516             TreeNode[] altnodes = new TreeNode[3];
517             TreeNode[] apnodes = new TreeNode[2];
518             apnodes[0] = result;
519             apnodes[1] = (TreeNode) nodelist.get(i);
520             altnodes[0] = result;
521             altnodes[1] = (TreeNode) nodelist.get(i);
522             altnodes[2] = new AndParallelNode(apnodes);
523             result = new AlternativeNode(altnodes);
524             ((AlternativeNode)result).setorparallel();
525             //result = new OrParallelNode(result, (TreeNode) nodelist.get(i));
526
result.protocol = protocol.substring(((Integer JavaDoc) protindices.get(0)).intValue(), ((Integer JavaDoc) protindices.get(i)).intValue());
527         }
528
529         return result;
530     }
531
532     /**
533      * Parse a list of comma-separaded ids. Requires that all identifiers to be
534      * already in EdgeFactory.ActionTokens.
535      *
536      * @return read list of ids
537      * @param endmark
538      * a string to mark the end of the list
539      * @throws SyntaxErrorException
540      * in case of badly formed protocols
541      * @throws IOException
542      * in case of unexpected end of reader
543      *
544      * @see Builder#nextToken
545      * @see Builder#composition
546      * @see Builder#adjustment
547      */

548     private TreeSet collectList(String JavaDoc endmark) throws SyntaxErrorException, IOException {
549         TreeSet result = new TreeSet();
550         while (isTokenID) {
551             if (next_token.startsWith("?") || next_token.startsWith("!") || next_token.startsWith("#")) {
552                 // this is action /action token
553
if (next_token.endsWith("^") || next_token.endsWith("$") || next_token.endsWith("~")) {
554                     // this is action token
555
Debug.println(3, "CollectList: action token");
556
557                     result.add(new Integer JavaDoc(repository.addItem(next_token)));
558
559                 } else {
560                     Debug.println(3, "CollectList: action token without");
561                     // this is just action
562

563                     result.add(new Integer JavaDoc(repository.addItem(next_token + "^")));
564
565                     //append inverse action
566
result.add(new Integer JavaDoc(repository.addItem(getReverseAction(next_token + "$"))));
567
568                 }
569             } else {
570                 // this is event / or event name
571
if (next_token.endsWith("^") || next_token.endsWith("$") || next_token.endsWith("~")) {
572                     Debug.println(3, "CollectList: adding event");
573                     // this is event
574
result.add(new Integer JavaDoc(repository.addItem("?" + next_token)));
575
576                     result.add(new Integer JavaDoc(repository.addItem("!" + next_token)));
577
578                     if (endmark == "&") { // this is list for composition
579
result.add(new Integer JavaDoc(repository.addItem("#" + next_token)));
580                     }
581                 } else {
582                     Debug.println(3, "CollectList: adding event name");
583                     // this is event name
584
result.add(new Integer JavaDoc(repository.addItem("?" + next_token + "^")));
585
586                     result.add(new Integer JavaDoc(repository.addItem("?" + next_token + "$")));
587
588                     result.add(new Integer JavaDoc(repository.addItem("!" + next_token + "^")));
589
590                     result.add(new Integer JavaDoc(repository.addItem("!" + next_token + "$")));
591
592                     if (endmark == "&") { // this is list for composition
593
result.add(new Integer JavaDoc(repository.addItem("#" + next_token + "^")));
594
595                         result.add(new Integer JavaDoc(repository.addItem("#" + next_token + "$")));
596
597                     }
598                 }
599             }
600             next_token = nextToken();
601             if (next_token == endmark) {
602                 Debug.println(2, "End mark reached ");
603                 next_token = nextToken();
604                 return result;
605             }
606             if (next_token.compareTo(",") != 0)
607                 throw new SyntaxErrorException("Comma expected in list");
608             else
609                 next_token = nextToken();
610         }
611         if (next_token == endmark) {
612             Debug.println(2, "End mark reached");
613             next_token = nextToken();
614             return result;
615         } else
616             throw new SyntaxErrorException("List syntax error");
617     }
618
619     /**
620      * Builds automaton for restriction operator by invoking the Restrict()
621      * operation.
622      *
623      * @return built automaton
624      * @throws SyntaxErrorException
625      * in case of badly formed protocols
626      * @throws IOException
627      * in case of unexpected end of reader
628      *
629      * @see Builder#collectList
630      */

631     private TreeNode restriction() throws SyntaxErrorException, IOException {
632         int protstart = source.getIndex() - next_token.length() - 1;
633         TreeNode result = alternative();
634
635         while (next_token == "\\") {
636             Debug.println(2, "Restriction found");
637             next_token = nextToken();
638             if (next_token != "(")
639                 throw new SyntaxErrorException("Restriction list expected");
640             next_token = nextToken();
641             TreeSet sync = collectList(")");
642             Debug.println(2, "Restriction action tokens: " + sync.toString());
643
644             /*
645              * result.Restrict( new ActionTokenArray(sync ) );
646              *
647              * result = new ProtocolRestriction( result, sync );
648              */

649             result = new RestrictionNode(result, sync, repository);
650             result.protocol = protocol.substring(protstart, source.getIndex() - next_token.length());
651         }
652
653         return result;
654     }
655
656     /**
657      * Builds automaton for composition operator by invoking the
658      * createComposition.
659      *
660      * @return built automaton
661      * @throws SyntaxErrorException
662      * in case of badly formed protocols
663      * @throws IOException
664      * in case of unexpected end of reader
665      *
666      * @see Builder#alternative
667      */

668     private TreeNode composition() throws SyntaxErrorException, IOException {
669         int protstart = source.getIndex() - next_token.length() - 1;
670
671         TreeNode node1 = restriction();
672
673         while (next_token == "&") {
674             Debug.println(2, "Composition found");
675             next_token = nextToken();
676             TreeSet sync = collectList("&");
677             Debug.println(2, "Composition action tokens: " + sync.toString());
678
679             /*
680              * Protocol m = restriction(); result = new ProtocolComposition(
681              * result, m, sync );
682              */

683
684             TreeNode node2 = restriction();
685             //node1 = new CompositionNode(node1, node2, sync, repository);
686
node1 = new ConsentNode(node1, node2, sync, new TreeSet(), repository, true);
687             node1.protocol = protocol.substring(protstart, source.getIndex() - next_token.length());
688
689         }
690         return node1;
691     }
692
693     /**
694      * Builds protocol for adjustment operator.
695      *
696      * @return built protocol
697      * @throws SyntaxErrorException
698      * in case of badly formed protocols
699      * @throws IOException
700      * in case of unexpected end of reader
701      *
702      * @see Builder#composition
703      */

704     private TreeNode adjustment() throws SyntaxErrorException, IOException {
705         int protstart = source.getIndex() - next_token.length() - 1;
706
707         TreeNode node1 = composition();
708
709         while (next_token == "@") {
710             Debug.println(2, "Adjustment found");
711             next_token = nextToken();
712             TreeSet sync = collectList("@");
713             Debug.println(2, "Adjustment action tokens: " + sync.toString());
714
715             /*
716              * Protocol m = composition(); result = new ProtocolAdjustment(
717              * result, m, new ActionTokenArray(sync) );
718              */

719             TreeNode node2 = composition();
720             node1 = new AdjustmentNode(node1, node2, sync);
721             node1.protocol = protocol.substring(protstart, source.getIndex() - next_token.length());
722
723         }
724         return node1;
725     }
726
727     /**
728      * Builds the automata for unary operator *.
729      *
730      * @return built automaton
731      * @throws SyntaxErrorException
732      * in case of badly formed protocols
733      * @throws IOException
734      * in case of unexpected end of reader
735      *
736      * @see Builder#factor
737      *
738      */

739     private TreeNode term() throws SyntaxErrorException, IOException {
740         int protstart = source.getIndex() - next_token.length() - 1;
741
742         TreeNode result = factor();
743
744         if (next_token == "*") {
745             next_token = nextToken();
746             result = new RepetitionNode(result); //(Options.action == Options.ACTIONTESTNOCONSENT ? ((TreeNode)new ComplianceRepetitionNode(result)) : ((TreeNode)new RepetitionNode(result)));
747
result.protocol = protocol.substring(protstart, source.getIndex() - next_token.length());
748
749         }
750
751         return result;
752     }
753
754     /**
755      * Builds the basic automata for action tokens and NULL. Also, parentheses
756      * are handled here.
757      *
758      * @return built automaton
759      * @throws SyntaxErrorException
760      * in case of badly formed protocols
761      * @throws IOException
762      * in case of unexpected end of reader
763      *
764      * @see Builder#alternative
765      */

766     private TreeNode factor() throws SyntaxErrorException, IOException {
767         TreeNode result;
768         if (next_token.equals("NULL")) {
769             result = new NullNode();
770             result.protocol = "null";
771             next_token = nextToken();
772         }
773
774         else if (next_token == "(") {
775             next_token = nextToken();
776             result = adjustment();
777             if (next_token != ")") {
778                 throw new SyntaxErrorException(") expected");
779             }
780             next_token = nextToken();
781         }
782         
783         else if (next_token == "[") {
784             Debug.println(2, "Atomic action found");
785             next_token = nextToken();
786             
787             TreeSet events = collectList("]");
788             
789             result = new AtomicNode(repository.addAtomicItem(events), events, repository);
790             
791         }
792         
793         else if (next_token.equals("")) {
794             result = null;
795         } else { // it has to be an action token or abbreviation
796
int protstart = source.getIndex() - next_token.length() - 1;
797
798             if (!isTokenID)
799                 throw new SyntaxErrorException("identifier expected, last token " + next_token);
800             String JavaDoc event = next_token;
801             next_token = nextToken();
802             if (next_token == "{") {
803                 // nested call abbreviation
804
next_token = nextToken();
805                 TreeNode pom = alternative();
806
807                 if (next_token != "}")
808                     throw new SyntaxErrorException("} expected");
809
810                 int protstop = source.getIndex() - next_token.length();
811
812                 next_token = nextToken();
813
814                 //if (!event.startsWith("?"))
815
// event = "?" + event;
816
EventNode start = new EventNode(repository.addItem(event + "^"), repository);
817                 start.protocol = event + "^";
818
819                 EventNode stop;
820
821                 /*
822                  * stop = new ActionToken(
823                  * stop.name.substring(0,stop.name.length()-1) + "$" );
824                  */

825                 String JavaDoc rev = getReverseAction(event);
826                 stop = new EventNode(repository.addItem(rev + "$"), repository);
827                 stop.protocol = rev + "$";
828                 //stop = new EventNode(repository.addItem(event + "$"));
829

830                 /*
831                  * pom = new SequenceEvent( new ProtocolToken( start ), pom );
832                  * pom = new ProtocolSequence( pom, new ProtocolToken( stop ) );
833                  */

834                 TreeNode[] nodearray = new TreeNode[3];
835                 nodearray[0] = start;
836                 nodearray[1] = pom;
837                 nodearray[2] = stop;
838                 result = new SequenceNode(nodearray);
839                 result.protocol = protocol.substring(protstart, protstop);
840
841                 Debug.println(3, "Nested call abbreviation:");
842                 //((Printer)pom).Print(3);
843

844             } else { // action token or simple call abbrevation
845
EventNode a = new EventNode(repository.addItem(event), repository);
846                 if (isSimpleCall(event)) { // simple call abbreviation
847
EventNode start = new EventNode(repository.addItem(event + "^"), repository);
848                     start.protocol = event + "^";
849                     EventNode stop = new EventNode(repository.addItem(getReverseAction(event + "$")), repository);
850                     stop.protocol = getReverseAction(event + "$");
851
852                     TreeNode[] nodearray = new TreeNode[2];
853                     nodearray[0] = start;
854                     nodearray[1] = stop;
855                     result = new SequenceNode(nodearray);
856                     result.protocol = event;
857                 } else { // action token
858
result = a;
859                     result.protocol = event;
860                 }
861             }
862         }
863         return result;
864     }
865
866     /**
867      * The main entry point for building the automaton for a behavior protocol.
868      * Using all private methods of this class, this method takes a string as
869      * the argument and then it builds the automton by invoking Build for reader
870      * argument
871      *
872      * @param reader
873      * a reader containing a protocol to be build
874      * @return built automaton
875      * @throws SyntaxErrorException
876      * in case of badly formed protocols
877      */

878     public TreeNode build(ProtocolReader reader) throws SyntaxErrorException {
879         Debug.println(1, "Protocol Build: start");
880         try {
881             source = reader;
882             protocol = new String JavaDoc();
883             next_char = (char) source.read();
884             if (next_char == -1)
885                 return null;
886             
887             next_token = nextToken();
888             TreeNode m = adjustment();
889             if (next_token != "")
890                 throw new SyntaxErrorException("Unexpected token: '" + next_token + "'.");
891             
892             Debug.println(1, "Protocol Build: finished");
893             //((Printer)m).Print( 2 );
894
return m;
895         } catch (IOException e) {
896             return null;
897         }
898     }
899
900 }
901
902
Popular Tags