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