001: /*
002: * xtc - The eXTensible Compiler
003: * Copyright (C) 2004, 2006 Robert Grimm
004: *
005: * This program is free software; you can redistribute it and/or
006: * modify it under the terms of the GNU General Public License
007: * version 2 as published by the Free Software Foundation.
008: *
009: * This program is distributed in the hope that it will be useful,
010: * but WITHOUT ANY WARRANTY; without even the implied warranty of
011: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
012: * GNU General Public License for more details.
013: *
014: * You should have received a copy of the GNU General Public License
015: * along with this program; if not, write to the Free Software
016: * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
017: * USA.
018: */
019: package xtc.parser;
020:
021: import java.util.ArrayList;
022: import java.util.List;
023:
024: import xtc.util.State;
025:
026: /**
027: * Parser state for parsing <i>Rats!</i> grammars. Note that
028: * this class supports only a single state-modifying transaction. In
029: * other words, calls to {@link #start()}, {@link #commit()}, and
030: * {@link #abort()} cannot be nested within each other.
031: *
032: * @author Robert Grimm
033: * @version $Revision: 1.5 $
034: */
035: public class PParserState implements State {
036:
037: /** The current indentation level. */
038: private int level;
039:
040: /** The list of indentation levels. */
041: private List<Integer> indent;
042:
043: /**
044: * The flag for whether we have seen anything besides spaces on the
045: * current line.
046: */
047: private boolean content;
048:
049: /** Create a new packrat parser state object. */
050: public PParserState() {
051: reset(null);
052: }
053:
054: public void reset(String file) {
055: level = -1;
056: indent = null;
057: }
058:
059: public void start() {
060: level = 0;
061: indent = new ArrayList<Integer>();
062: indent.add(level);
063: content = false;
064: }
065:
066: public void commit() {
067: level = -1;
068: }
069:
070: public void abort() {
071: level = -1;
072: }
073:
074: /** Record an opening brace. */
075: public void open() {
076: if (-1 < level)
077: level++;
078: }
079:
080: /** Record any character besides spaces. */
081: public void content() {
082: if (-1 < level)
083: content = true;
084: }
085:
086: /** Record a newline. */
087: public void newline() {
088: if (-1 < level) {
089: indent.add(level);
090: content = false;
091: }
092: }
093:
094: /** Record a closing brace. */
095: public void close() {
096: if (0 < level) {
097: // If the closing brace appears at the beginning of the current
098: // line (disregarding spaces), we need to also decrement the
099: // last captured indentation level.
100: if (!content) {
101: final int idx = indent.size() - 1;
102: final int value = indent.get(idx) - 1;
103: indent.set(idx, value);
104: }
105: level--;
106: }
107: }
108:
109: /**
110: * Retrieve the list of indentation levels. The list contains one
111: * entry per invocation of {@link #newline()} since the last
112: * invocation of {@link #start()}.
113: *
114: * @return The list of indentation levels.
115: */
116: public List<Integer> indentations() {
117: return indent;
118: }
119:
120: }
|