    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