001 /* Copyright 2000, 2001, Compaq Computer Corporation */
002
003 package escjava.parser;
004
005 import java.io.IOException;
006 import java.util.Hashtable;
007
008 import javafe.util.Assert;
009 import javafe.util.ErrorSet;
010 import javafe.util.CorrelatedReader;
011 import javafe.util.Location;
012 import javafe.util.StackVector;
013
014 import javafe.parser.Lex;
015 import javafe.parser.PragmaParser;
016 import javafe.parser.Token;
017 import javafe.parser.Parse;
018
019 import javafe.ast.*;
020
021 import escjava.ast.*;
022 import escjava.ast.TagConstants;
023
024 /**
025 * This lexer overrides {@link Lex#scanJavaExtensions(int)} to
026 * support "informal predicates". An informal predicate is an
027 * embedded comment. <br>
028 * <pre>
029 * //@ requires (* this is an informal predicate *);
030 * //@ requires true &&(*soIsThis*)
031 * //@ ensures (((((* Here's one inside some parens *)))));
032 * </pre>
033 * Informal predicates can even be more crazy with embedded comments.
034 * See the file ESCTools/Escjava/test/escjava/test/test70/C.java for
035 * examples.
036 *
037 * <p> Informal predicates are parsed as boolean literal expressions
038 * with an AST decoration of "informalPredicate". See
039 * {@link EscPragmaParser#parsePrimaryExpression(Lex)} and
040 * {@link EscPragmaParser#informalPredicateDecoration} for details.
041 */
042
043 public final class EscPragmaLex extends Lex
044 {
045 // Documented in parent class.
046 public EscPragmaLex(PragmaParser pragmaParser, boolean isJava) {
047 super(pragmaParser, isJava);
048 }
049
050 // Documented in parent class.
051 //@ also
052 //@ assignable endingLoc, identifierVal, text, textlen;
053 protected int scanJavaExtensions(int nextchr) {
054 try {
055 if (nextchr == '\\') {
056 int h = 0;
057 do {
058 try {
059 text[textlen] = (char)nextchr;
060 textlen++;
061 } catch (ArrayIndexOutOfBoundsException e) {
062 this.append(nextchr);
063 }
064 h = _SpecialParserInterface.HC * h + nextchr;
065 nextchr = m_in.read();
066 } while (Character.isJavaIdentifierPart((char)nextchr));
067 m_nextchr = nextchr;
068 auxVal = null;
069 identifierVal = _SpecialParserInterface.intern(text, textlen, h);
070 if (keywords != null) {
071 Object val = keywords.get(identifierVal);
072 if (val != null) {
073 ttype = ((Integer)val).intValue();
074 } else {
075 int esckeytag = TagConstants.fromIdentifier(identifierVal);
076 if (TagConstants.isKeywordTag(esckeytag)) {
077 ttype = _SpecialParserInterface.getTokenType(identifierVal);
078 } else {
079 ErrorSet.fatal(startingLoc, "Unrecognized special keyword");
080 }
081 }
082 } else {
083 ttype = TagConstants.NULL;
084 }
085 return ttype;
086 } else if (nextchr == '(') {
087 // Try to lex an informal predicate
088 m_in.mark();
089 nextchr = m_in.read();
090 if (nextchr == '*') {
091 // now look for the closing "*)"
092 while (true) {
093 nextchr = m_in.read();
094 try {
095 text[textlen] = (char)nextchr;
096 textlen++;
097 } catch (ArrayIndexOutOfBoundsException e) {
098 this.append(nextchr);
099 }
100 if (nextchr == '*') {
101 // read all the '*'s there are
102 do {
103 nextchr = m_in.read();
104 try {
105 text[textlen] = (char)nextchr;
106 textlen++;
107 } catch (ArrayIndexOutOfBoundsException e) {
108 this.append(nextchr);
109 }
110 } while (nextchr == '*');
111 if (nextchr == ')') {
112 // we've found the end of the informal predicate
113 ttype = TagConstants.INFORMALPRED_TOKEN;
114 m_nextchr = nextchr;
115 auxVal = new String(text, 0, textlen-2);
116 endingLoc = m_in.getLocation();
117 m_nextchr = m_in.read();
118 return ttype;
119 }
120 }
121 if (nextchr == -1) {
122 // error in input
123 ErrorSet.fatal(startingLoc,
124 "Unterminated informal predicate");
125 }
126 }
127 } else {
128 // it wasn't an informal predicate after all
129 m_in.reset();
130 }
131 }
132
133 ttype = TagConstants.NULL;
134 return ttype;
135 } catch (IOException e) {
136 ErrorSet.fatal(m_in.getLocation(), e.toString());
137 return TagConstants.NULL; // Dummy
138 }
139 }
140 } // end of class EscPragmaLex
141
142 /*
143 * Local Variables:
144 * Mode: Java
145 * fill-column: 85
146 * End:
147 */
148