View Javadoc

    1   /*
    2    * EiffelTokenMarker.java - Eiffel token marker
    3    * Copyright (C) 1999 Slava Pestov
    4    * Copyright (C) 1999 Artur Biesiadowski
    5    *
    6    * You may use and modify this package for any purpose. Redistribution is
    7    * permitted, in both source and binary form, provided that this notice
    8    * remains intact in all source distributions of this package.
    9    */
    10
    11  package org.syntax.jedit.tokenmarker;
    12
    13  import javax.swing.text.Segment;
    14
    15  import org.syntax.jedit.KeywordMap;
    16
    17  /***
    18   * Eiffel token Marker.
    19   *
    20   * @author Artur Biesiadowski
    21   */
    22  public class EiffelTokenMarker extends TokenMarker
    23  {
    24
    25  	public EiffelTokenMarker()
    26  	{
    27  		this.keywords = getKeywords();
    28  	}
    29
    30  	public byte markTokensImpl(byte token, Segment line, int lineIndex)
    31  	{
    32  		char[] array = line.array;
    33  		int offset = line.offset;
    34  		lastOffset = offset;
    35  		lastKeyword = offset;
    36  		int length = line.count + offset;
    37  		boolean backslash = false;
    38
    39  loop:		for(int i = offset; i < length; i++)
    40  		{
    41  			int i1 = (i+1);
    42
    43  			char c = array[i];
    44  			if(c == '%')
    45  			{
    46  				backslash = !backslash;
    47  				continue;
    48  			}
    49
    50  			switch(token)
    51  			{
    52  			case Token.NULL:
    53  				switch(c)
    54  				{
    55  				case '"':
    56  					doKeyword(line,i,c);
    57  					if(backslash)
    58  						backslash = false;
    59  					else
    60  					{
    61  						addToken(i - lastOffset,token);
    62  						token = Token.LITERAL1;
    63  						lastOffset = lastKeyword = i;
    64  					}
    65  					break;
    66  				case '\'':
    67  					doKeyword(line,i,c);
    68  					if(backslash)
    69  						backslash = false;
    70  					else
    71  					{
    72  						addToken(i - lastOffset,token);
    73  						token = Token.LITERAL2;
    74  						lastOffset = lastKeyword = i;
    75  					}
    76  					break;
    77  				case ':':
    78  					if(lastKeyword == offset)
    79  					{
    80  						if(doKeyword(line,i,c))
    81  							break;
    82  						backslash = false;
    83  						addToken(i1 - lastOffset,Token.LABEL);
    84  						lastOffset = lastKeyword = i1;
    85  					}
    86  					else if(doKeyword(line,i,c))
    87  						break;
    88  					break;
    89  				case '-':
    90  					backslash = false;
    91  					doKeyword(line,i,c);
    92  					if(length - i > 1)
    93  					{
    94  						switch(array[i1])
    95  						{
    96  						case '-':
    97  							addToken(i - lastOffset,token);
    98  							addToken(length - i,Token.COMMENT1);
    99  							lastOffset = lastKeyword = length;
    100 							break loop;
    101 						}
    102 					}
    103 					break;
    104 				default:
    105 					backslash = false;
    106 					if(!Character.isLetterOrDigit(c)
    107 						&& c != '_')
    108 						doKeyword(line,i,c);
    109 					break;
    110 				}
    111 				break;
    112 			case Token.COMMENT1:
    113 			case Token.COMMENT2:
    114 				throw new RuntimeException("Wrong eiffel parser state");
    115 			case Token.LITERAL1:
    116 				if(backslash)
    117 					backslash = false;
    118 				else if(c == '"')
    119 				{
    120 					addToken(i1 - lastOffset,token);
    121 					token = Token.NULL;
    122 					lastOffset = lastKeyword = i1;
    123 				}
    124 				break;
    125 			case Token.LITERAL2:
    126 				if(backslash)
    127 					backslash = false;
    128 				else if(c == '\'')
    129 				{
    130 					addToken(i1 - lastOffset,Token.LITERAL1);
    131 					token = Token.NULL;
    132 					lastOffset = lastKeyword = i1;
    133 				}
    134 				break;
    135 			default:
    136 				throw new InternalError("Invalid state: "
    137 					+ token);
    138 			}
    139 		}
    140
    141 		if(token == Token.NULL)
    142 			doKeyword(line,length,'\0');
    143
    144 		switch(token)
    145 		{
    146 		case Token.LITERAL1:
    147 		case Token.LITERAL2:
    148 			addToken(length - lastOffset,Token.INVALID);
    149 			token = Token.NULL;
    150 			break;
    151 		case Token.KEYWORD2:
    152 			addToken(length - lastOffset,token);
    153 			if(!backslash)
    154 				token = Token.NULL;
    155 		default:
    156 			addToken(length - lastOffset,token);
    157 			break;
    158 		}
    159
    160 		return token;
    161 	}
    162
    163 	public static KeywordMap getKeywords()
    164 	{
    165 		if(eiffelKeywords == null)
    166 		{
    167 			eiffelKeywords = new KeywordMap(true);
    168 			eiffelKeywords.add("alias", Token.KEYWORD1);
    169 			eiffelKeywords.add("all", Token.KEYWORD1);
    170 			eiffelKeywords.add("and", Token.KEYWORD1);
    171 			eiffelKeywords.add("as", Token.KEYWORD1);
    172 			eiffelKeywords.add("check", Token.KEYWORD1);
    173 			eiffelKeywords.add("class", Token.KEYWORD1);
    174 			eiffelKeywords.add("creation", Token.KEYWORD1);
    175 			eiffelKeywords.add("debug", Token.KEYWORD1);
    176 			eiffelKeywords.add("deferred", Token.KEYWORD1);
    177 			eiffelKeywords.add("do", Token.KEYWORD1);
    178 			eiffelKeywords.add("else",Token.KEYWORD1);
    179 			eiffelKeywords.add("elseif", Token.KEYWORD1);
    180 			eiffelKeywords.add("end", Token.KEYWORD1);
    181 			eiffelKeywords.add("ensure", Token.KEYWORD1);
    182 			eiffelKeywords.add("expanded", Token.KEYWORD1);
    183 			eiffelKeywords.add("export", Token.KEYWORD1);
    184 			eiffelKeywords.add("external", Token.KEYWORD1);
    185 			eiffelKeywords.add("feature", Token.KEYWORD1);
    186 			eiffelKeywords.add("from", Token.KEYWORD1);
    187 			eiffelKeywords.add("frozen", Token.KEYWORD1);
    188 			eiffelKeywords.add("if", Token.KEYWORD1);
    189 			eiffelKeywords.add("implies",Token.KEYWORD1);
    190 			eiffelKeywords.add("indexing", Token.KEYWORD1);
    191 			eiffelKeywords.add("infix", Token.KEYWORD1);
    192 			eiffelKeywords.add("inherit", Token.KEYWORD1);
    193 			eiffelKeywords.add("inspect", Token.KEYWORD1);
    194 			eiffelKeywords.add("invariant", Token.KEYWORD1);
    195 			eiffelKeywords.add("is", Token.KEYWORD1);
    196 			eiffelKeywords.add("like", Token.KEYWORD1);
    197 			eiffelKeywords.add("local", Token.KEYWORD1);
    198 			eiffelKeywords.add("loop", Token.KEYWORD1);
    199 			eiffelKeywords.add("not", Token.KEYWORD1);
    200 			eiffelKeywords.add("obsolete", Token.KEYWORD1);
    201 			eiffelKeywords.add("old",Token.KEYWORD1);
    202 			eiffelKeywords.add("once", Token.KEYWORD1);
    203 			eiffelKeywords.add("or", Token.KEYWORD1);
    204 			eiffelKeywords.add("prefix", Token.KEYWORD1);
    205 			eiffelKeywords.add("redefine", Token.KEYWORD1);
    206 			eiffelKeywords.add("rename", Token.KEYWORD1);
    207 			eiffelKeywords.add("require", Token.KEYWORD1);
    208 			eiffelKeywords.add("rescue", Token.KEYWORD1);
    209 			eiffelKeywords.add("retry", Token.KEYWORD1);
    210 			eiffelKeywords.add("select", Token.KEYWORD1);
    211 			eiffelKeywords.add("separate", Token.KEYWORD1);
    212 			eiffelKeywords.add("then",Token.KEYWORD1);
    213 			eiffelKeywords.add("undefine", Token.KEYWORD1);
    214 			eiffelKeywords.add("until", Token.KEYWORD1);
    215 			eiffelKeywords.add("variant", Token.KEYWORD1);
    216 			eiffelKeywords.add("when", Token.KEYWORD1);
    217 			eiffelKeywords.add("xor", Token.KEYWORD1);
    218
    219 			eiffelKeywords.add("current",Token.LITERAL2);
    220 			eiffelKeywords.add("false",Token.LITERAL2);
    221 			eiffelKeywords.add("precursor",Token.LITERAL2);
    222 			eiffelKeywords.add("result",Token.LITERAL2);
    223 			eiffelKeywords.add("strip",Token.LITERAL2);
    224 			eiffelKeywords.add("true",Token.LITERAL2);
    225 			eiffelKeywords.add("unique",Token.LITERAL2);
    226 			eiffelKeywords.add("void",Token.LITERAL2);
    227
    228 		}
    229 		return eiffelKeywords;
    230 	}
    231
    232 	// private members
    233 	private static KeywordMap eiffelKeywords;
    234
    235 	private boolean cpp;
    236 	private KeywordMap keywords;
    237 	private int lastOffset;
    238 	private int lastKeyword;
    239
    240 	private boolean doKeyword(Segment line, int i, char c)
    241 	{
    242 		int i1 = i+1;
    243 		boolean klassname = false;
    244
    245 		int len = i - lastKeyword;
    246 		byte id = keywords.lookup(line,lastKeyword,len);
    247 		if ( id == Token.NULL )
    248 		{
    249 			klassname = true;
    250 			for ( int at = lastKeyword; at < lastKeyword + len; at++ )
    251 			{
    252 				char ch = line.array[at];
    253 				if ( ch != '_' && !Character.isUpperCase(ch) )
    254 				{
    255 					klassname = false;
    256 					break;
    257 				}
    258 			}
    259 			if ( klassname )
    260 				id = Token.KEYWORD3;
    261 		}
    262
    263 		if(id != Token.NULL)
    264 		{
    265 			if(lastKeyword != lastOffset)
    266 				addToken(lastKeyword - lastOffset,Token.NULL);
    267 			addToken(len,id);
    268 			lastOffset = i;
    269 		}
    270 		lastKeyword = i1;
    271 		return false;
    272 	}
    273 }