/**
* Copyright 2011 Oliver Buchtala
*
* This file is part of ndogen.
*
* ndogen is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* ndogen is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ndogen. If not, see <http://www.gnu.org/licenses/>.
*/
package org.ndogen.antlr;
import java.util.Stack;
import org.antlr.runtime.*;
public class IndentWatcher {
Lexer lexer;
Stack<Integer> indentStack;
private CharStream input;
private final int DEDENT;
private final int INDENT;
public IndentWatcher(Lexer lexer, int INDENT, int DEDENT) {
super();
this.lexer = lexer;
this.INDENT = INDENT;
this.DEDENT = DEDENT;
input = lexer.getCharStream();
indentStack = new Stack<Integer>();
}
public void checkIndent(CharStream input) {
if(indentStack.isEmpty()) {
indentStack.push(0);
}
// look ahead and emit INDENTs and DEDENTS if necessary
int idx = 1;
int level = 0;
int pos = 0;
while(true) {
int c = input.LA(idx++);
pos++;
if(c == '\n') {
return;
} else if (c == -1) {
for (int i = 0; i < indentStack.size()-1; i++) {
lexer.emit(new CommonToken(DEDENT));
}
return;
} else if (c == ' ') {
level++;
} else if (c == '\t') {
level+=4;
} else break;
}
if(level>0) {
input.seek(input.index()+pos-1);
}
if (level > indentStack.peek()) {
indentStack.push(level);
CommonToken indent = new CommonToken(INDENT);
indent.setStartIndex(input.index()+1);
indent.setStopIndex(input.index()+pos);
lexer.emit(indent);
} else if (level < indentStack.peek()) {
while (indentStack.peek() > level) {
indentStack.pop();
lexer.emit(new CommonToken(DEDENT));
}
}
}
}