View Javadoc

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