/** * 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)); } } } }