Skip to main content
aboutsummaryrefslogtreecommitdiffstats
blob: d9200c749307ef69d8c2eeb525b4591524e90f4f (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
/*******************************************************************************
 * Copyright (c) 2012 Red Hat Inc. and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *******************************************************************************/
package org.eclipse.cdt.internal.autotools.ui.editors.automake;

import java.util.Arrays;
import java.util.Comparator;

import org.eclipse.jface.text.rules.ICharacterScanner;
import org.eclipse.jface.text.rules.IPredicateRule;
import org.eclipse.jface.text.rules.IToken;
import org.eclipse.jface.text.rules.Token;

public class AutoconfSubstRule implements IPredicateRule {

	private IToken token;
	private char[][] fLineDelimiters;
	private char[][] fSortedLineDelimiters;
	
	private static class DecreasingCharArrayLengthComparator implements Comparator<Object> {
		@Override
		public int compare(Object o1, Object o2) {
			return ((char[]) o2).length - ((char[]) o1).length;
		}
	}

	private Comparator<Object> fLineDelimiterComparator= new DecreasingCharArrayLengthComparator();

	public AutoconfSubstRule(IToken token) {
		this.token = token;
	}
	
	@Override
	public IToken evaluate(ICharacterScanner scanner, boolean resume) {
		char[][] originalDelimiters= scanner.getLegalLineDelimiters();
		int count= originalDelimiters.length;
		if (fLineDelimiters == null || originalDelimiters.length != count) {
			fSortedLineDelimiters= new char[count][];
		} else {
			while (count > 0 && fLineDelimiters[count-1] == originalDelimiters[count-1])
				count--;
		}
		if (count != 0) {
			fLineDelimiters= originalDelimiters;
			System.arraycopy(fLineDelimiters, 0, fSortedLineDelimiters, 0, fLineDelimiters.length);
			Arrays.sort(fSortedLineDelimiters, fLineDelimiterComparator);
		}
		
		int c;
		boolean okToScan = resume;
		int charCount = 0;
		
		if (!resume) {
			// Not resuming.  Verify first char is '@'.
			c = scanner.read();
			++charCount;
			if (c == '@') {
				okToScan = true;
			}
		}
		
		if (okToScan) {
			// We want to make sure we have a valid id (not @@) or (@_@).  When
			// we resume, we have no choice but to assume it is valid so far.
			boolean isId = resume;
			++charCount;
			while ((c = scanner.read()) != ICharacterScanner.EOF) {
				if (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z') {
					// A valid id has some alphabetic character in it.
					isId = true;
				}
				else if (c >= '0' && c <= '9' || c == '_') {
					; // continue
				}
				else if (c == '@' && isId)
					return getSuccessToken();
				else
					break;
				++charCount;
			}
		}
		
		for (int i = 0; i < charCount; ++i)
			scanner.unread();
		
		return Token.UNDEFINED;
	}

	@Override
	public IToken getSuccessToken() {
		return token;
	}

	@Override
	public IToken evaluate(ICharacterScanner scanner) {
		return evaluate(scanner, false);
	}

}

Back to the top