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