View Javadoc

    1   /*
    2    * ShellScriptTokenMarker.java - Shell script 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.SyntaxUtilities;
    15
    16  /***
    17   * Shell script token marker.
    18   *
    19   * @author Slava Pestov
    20   * @version $Id: ShellScriptTokenMarker.java,v 1.18 1999/12/13 03:40:30 sp Exp $
    21   */
    22  public class ShellScriptTokenMarker extends TokenMarker
    23  {
    24  	// public members
    25  	public static final byte LVARIABLE = Token.INTERNAL_FIRST;
    26
    27  	public byte markTokensImpl(byte token, Segment line, int lineIndex)
    28  	{
    29  		char[] array = line.array;
    30  		byte cmdState = 0; // 0 = space before command, 1 = inside
    31  				// command, 2 = after command
    32  		int offset = line.offset;
    33  		int lastOffset = offset;
    34  		int length = line.count + offset;
    35
    36  		if(token == Token.LITERAL1 && lineIndex != 0
    37  			&& lineInfo[lineIndex - 1].obj != null)
    38  		{
    39  			String str = (String)lineInfo[lineIndex - 1].obj;
    40  			if(str != null && str.length() == line.count
    41  				&& SyntaxUtilities.regionMatches(false,line,
    42  				offset,str))
    43  			{
    44  				addToken(line.count,Token.LITERAL1);
    45  				return Token.NULL;
    46  			}
    47  			else
    48  			{
    49  				addToken(line.count,Token.LITERAL1);
    50  				lineInfo[lineIndex].obj = str;
    51  				return Token.LITERAL1;
    52  			}
    53  		}
    54
    55  		boolean backslash = false;
    56  loop:		for(int i = offset; i < length; i++)
    57  		{
    58  			int i1 = (i+1);
    59
    60  			char c = array[i];
    61
    62  			if(c == '//')
    63  			{
    64  				backslash = !backslash;
    65  				continue;
    66  			}
    67
    68  			switch(token)
    69  			{
    70  			case Token.NULL:
    71  				switch(c)
    72  				{
    73  				case ' ': case '\t': case '(': case ')':
    74  					backslash = false;
    75  					if(cmdState == 1/*insideCmd*/)
    76  					{
    77  						addToken(i - lastOffset,Token.KEYWORD1);
    78  						lastOffset = i;
    79  						cmdState = 2; /*afterCmd*/
    80  					}
    81  					break;
    82  				case '=':
    83  					backslash = false;
    84  					if(cmdState == 1/*insideCmd*/)
    85  					{
    86  						addToken(i - lastOffset,token);
    87  						lastOffset = i;
    88  						cmdState = 2; /*afterCmd*/
    89  					}
    90  					break;
    91  				case '&': case '|': case ';':
    92  					if(backslash)
    93  						backslash = false;
    94  					else
    95  						cmdState = 0; /*beforeCmd*/
    96  					break;
    97  				case '#':
    98  					if(backslash)
    99  						backslash = false;
    100 					else
    101 					{
    102 						addToken(i - lastOffset,token);
    103 						addToken(length - i,Token.COMMENT1);
    104 						lastOffset = length;
    105 						break loop;
    106 					}
    107 					break;
    108 				case '$':
    109 					if(backslash)
    110 						backslash = false;
    111 					else
    112 					{
    113 						addToken(i - lastOffset,token);
    114 						cmdState = 2; /*afterCmd*/
    115 						lastOffset = i;
    116 						if(length - i >= 2)
    117 						{
    118 							switch(array[i1])
    119 							{
    120 							case '(':
    121 								continue;
    122 							case '{':
    123 								token = LVARIABLE;
    124 								break;
    125 							default:
    126 								token = Token.KEYWORD2;
    127 								break;
    128 							}
    129 						}
    130 						else
    131 							token = Token.KEYWORD2;
    132 					}
    133 					break;
    134 				case '"':
    135 					if(backslash)
    136 						backslash = false;
    137 					else
    138 					{
    139 						addToken(i - lastOffset,token);
    140 						token = Token.LITERAL1;
    141 						lineInfo[lineIndex].obj = null;
    142 						cmdState = 2; /*afterCmd*/
    143 						lastOffset = i;
    144 					}
    145 					break;
    146 				case '\'':
    147 					if(backslash)
    148 						backslash = false;
    149 					else
    150 					{
    151 						addToken(i - lastOffset,token);
    152 						token = Token.LITERAL2;
    153 						cmdState = 2; /*afterCmd*/
    154 						lastOffset = i;
    155 					}
    156 					break;
    157 				case '<':
    158 					if(backslash)
    159 						backslash = false;
    160 					else
    161 					{
    162 						if(length - i > 1 && array[i1] == '<')
    163 						{
    164 							addToken(i - lastOffset,
    165 								token);
    166 							token = Token.LITERAL1;
    167 							lastOffset = i;
    168 							lineInfo[lineIndex].obj =
    169 								new String(array,i + 2,
    170 									length - (i+2));
    171 						}
    172 					}
    173 					break;
    174 				default:
    175 					backslash = false;
    176 					if(Character.isLetter(c))
    177 					{
    178 						if(cmdState == 0 /*beforeCmd*/)
    179 						{
    180 							addToken(i - lastOffset,token);
    181 							lastOffset = i;
    182 							cmdState++; /*insideCmd*/
    183 						}
    184 					}
    185 					break;
    186 				}
    187 				break;
    188 			case Token.KEYWORD2:
    189 				backslash = false;
    190 				if(!Character.isLetterOrDigit(c) && c != '_')
    191 				{
    192 					if(i != offset && array[i-1] == '$')
    193 					{
    194 						addToken(i1 - lastOffset,token);
    195 						lastOffset = i1;
    196 						token = Token.NULL;
    197 						continue;
    198 					}
    199 					else
    200 					{
    201 						addToken(i - lastOffset,token);
    202 						lastOffset = i;
    203 						token = Token.NULL;
    204 					}
    205 				}
    206 				break;
    207 			case Token.LITERAL1:
    208 				if(backslash)
    209 					backslash = false;
    210 				else if(c == '"')
    211 				{
    212 					addToken(i1 - lastOffset,token);
    213 					cmdState = 2; /*afterCmd*/
    214 					lastOffset = i1;
    215 					token = Token.NULL;
    216 				}
    217 				else
    218 					backslash = false;
    219 				break;
    220 			case Token.LITERAL2:
    221 				if(backslash)
    222 					backslash = false;
    223 				else if(c == '\'')
    224 				{
    225 					addToken(i1 - lastOffset,Token.LITERAL1);
    226 					cmdState = 2; /*afterCmd*/
    227 					lastOffset = i1;
    228 					token = Token.NULL;
    229 				}
    230 				else
    231 					backslash = false;
    232 				break;
    233 			case LVARIABLE:
    234 				backslash = false;
    235 				if(c == '}')
    236 				{
    237 					addToken(i1 - lastOffset,Token.KEYWORD2);
    238 					lastOffset = i1;
    239 					token = Token.NULL;
    240 				}
    241 				break;
    242 			default:
    243 				throw new InternalError("Invalid state: " + token);
    244 			}
    245 		}
    246
    247 		switch(token)
    248 		{
    249 		case Token.NULL:
    250 			if(cmdState == 1)
    251 				addToken(length - lastOffset,Token.KEYWORD1);
    252 			else
    253 				addToken(length - lastOffset,token);
    254 			break;
    255 		case Token.LITERAL2:
    256 			addToken(length - lastOffset,Token.LITERAL1);
    257 			break;
    258 		case Token.KEYWORD2:
    259 			addToken(length - lastOffset,token);
    260 			token = Token.NULL;
    261 			break;
    262 		case LVARIABLE:
    263 			addToken(length - lastOffset,Token.INVALID);
    264 			token = Token.NULL;
    265 			break;
    266 		default:
    267 			addToken(length - lastOffset,token);
    268 			break;
    269 		}
    270 		return token;
    271 	}
    272 }