001: /*
002: * RubyTagger.java
003: *
004: * Copyright (C) 2002 Jens Luedicke <jens@irs-net.com>
005: * based on PythonTagger.java
006: * $Id: RubyTagger.java,v 1.1.1.1 2002/09/24 16:08:05 piso Exp $
007: *
008: * This program is free software; you can redistribute it and/or
009: * modify it under the terms of the GNU General Public License
010: * as published by the Free Software Foundation; either version 2
011: * of the License, or (at your option) any later version.
012: *
013: * This program is distributed in the hope that it will be useful,
014: * but WITHOUT ANY WARRANTY; without even the implied warranty of
015: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
016: * GNU General Public License for more details.
017: *
018: * You should have received a copy of the GNU General Public License
019: * along with this program; if not, write to the Free Software
020: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
021: */
022:
023: package org.armedbear.j;
024:
025: import java.util.ArrayList;
026:
027: public final class RubyTagger extends Tagger {
028: // States.
029: private static final int STATE_NEUTRAL = 0;
030: private static final int STATE_CLASS_NAME = 1;
031: private static final int STATE_FUNCTION_NAME = 2;
032: private static final int STATE_SINGLE_QUOTE = 3;
033: private static final int STATE_DOUBLE_QUOTE = 4;
034: private static final int STATE_TRIPLE_SINGLE = 5;
035: private static final int STATE_TRIPLE_DOUBLE = 6;
036:
037: private static final RubyMode mode = RubyMode.getMode();
038:
039: public RubyTagger(SystemBuffer buffer) {
040: super (buffer);
041: }
042:
043: public void run() {
044: ArrayList tags = new ArrayList();
045: Position pos = new Position(buffer.getFirstLine(), 0);
046: int state = STATE_NEUTRAL;
047: while (!pos.atEnd()) {
048: char c = pos.getChar();
049: if (Character.isWhitespace(c)) {
050: pos.skipWhitespace();
051: continue;
052: }
053: if (c == '\\') {
054: // Escape.
055: if (pos.getOffset() < pos.getLineLength() - 1) {
056: pos.skip(2);
057: } else {
058: pos.setLine(pos.getNextLine());
059: pos.setOffset(0);
060: }
061: continue;
062: }
063: if (state == STATE_SINGLE_QUOTE) {
064: if (c == '\'')
065: state = STATE_NEUTRAL;
066: pos.next();
067: continue;
068: }
069: if (state == STATE_DOUBLE_QUOTE) {
070: if (c == '"')
071: state = STATE_NEUTRAL;
072: pos.next();
073: continue;
074: }
075: if (state == STATE_TRIPLE_SINGLE) {
076: if (c == '\'' && pos.lookingAt("'''")) {
077: pos.skip(3);
078: state = STATE_NEUTRAL;
079: } else
080: pos.next();
081: continue;
082: }
083: if (state == STATE_TRIPLE_DOUBLE) {
084: if (c == '"' && pos.lookingAt("\"\"\"")) {
085: pos.skip(3);
086: state = STATE_NEUTRAL;
087: } else
088: pos.next();
089: continue;
090: }
091: if (c == '\'') {
092: if (pos.lookingAt("'''")) {
093: state = STATE_TRIPLE_SINGLE;
094: pos.skip(3);
095: } else {
096: state = STATE_SINGLE_QUOTE;
097: pos.next();
098: }
099: continue;
100: }
101: if (c == '"') {
102: if (pos.lookingAt("\"\"\"")) {
103: state = STATE_TRIPLE_DOUBLE;
104: pos.skip(3);
105: } else {
106: state = STATE_DOUBLE_QUOTE;
107: pos.next();
108: }
109: continue;
110: }
111: if (c == '#') {
112: // Comment.
113: pos.setLine(pos.getNextLine());
114: pos.setOffset(0);
115: continue;
116: }
117: if (mode.isIdentifierStart(c)) {
118: Position start = pos.copy();
119: String token = gatherToken(pos);
120: if (state == STATE_CLASS_NAME) {
121: LocalTag tag = new RubyTag("class " + token, start,
122: TAG_CLASS);
123: tags.add(tag);
124: state = STATE_NEUTRAL;
125: } else if (state == STATE_FUNCTION_NAME) {
126: LocalTag tag = new RubyTag(token, start,
127: TAG_FUNCTION);
128: tags.add(tag);
129: state = STATE_NEUTRAL;
130: } else if (token.equals("class")) {
131: state = STATE_CLASS_NAME;
132: } else if (token.equals("def")) {
133: state = STATE_FUNCTION_NAME;
134: }
135: continue;
136: }
137: pos.next();
138: }
139: buffer.setTags(tags);
140: }
141:
142: private static String gatherToken(Position pos) {
143: FastStringBuffer sb = new FastStringBuffer();
144: char c;
145: while (mode.isIdentifierPart(c = pos.getChar())) {
146: sb.append(c);
147: if (!pos.next())
148: break;
149: }
150: return sb.toString();
151: }
152: }
|