/*
 * DlpParser.java
 *
 * Copyright (C) 2006 - 2007 Martin Slota
 *
 * This program 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 2 of the License, or (at your option) any later
 * version.
 *
 * This program 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
 * this program; if not, write to the Free Software Foundation, Inc., 51
 * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 */

/*
 * History:
 * v0.1 (2007-02-17): initial version
 * v0.2 (2007-03-05):
 * - tests added
 * - documentation
 * 1.0.0 (2007-05-04):
 * - promoted to version 1.0.0 :o)
 */

package lp.parse;

import lp.struct.LpAtom;
import lp.struct.LpLiteral;
import lp.struct.LpPredicate;
import lp.struct.LpRule;
import lp.unit.GeneralizedLogicProgram;
import lp.unit.DynamicLogicProgram;
import lp.unit.LogicProgram;

/**
 * This parser inherits all behaviour from {@link LpParser}. In addition, it
 * offers the static method {@link #parseDlp()} that parses the given input as a
 * dynamic logic program, i.e. a sequence of logic program separated from each
 * other by "newProgram." facts. These facts are not contained in any of the
 * parsed programs. For example on this input:
 *
 *<pre>
 *a.
 *newProgram.
 *not a.
 *newProgram.
 *a <- not b.
 *</pre>
 *
 * it would produce a dynamic logic program consisting of 3 logic programs, each
 * containing 1 rule:
 *
 *<pre>a.</pre>
 *<pre>not a.</pre>
 *<pre>a <- not b.</pre>
 *
 * @author Martin Slota
 * @version 1.0.0
 * @see LpParser
 */
public class DlpParser extends LpParser {
	/**
	 * The fact "newProgram." for separating programs in a dynamic logic
	 * programs.
	 */
	public static final LpRule SEP_RULE;
	
	static {
		LpAtom sepAtom = LpAtom.getInstance(
				LpPredicate.getInstance("newProgram", 0), null);
		LpLiteral sepLit = sepAtom.getPositiveLiteral();
		SEP_RULE = new LpRule(sepLit, null);
	}
	
	/**
	 * Creates a new {@code DlpParser} instance that uses a new {@link LpLexer}
	 * instance to tokenize the character input before parsing.
	 */
	public DlpParser() {
		super();
	}
	
	/**
	 * Creates a new {@code DlpParser} instance that uses {@code lexer} to
	 * tokenize the character input before parsing.
	 *
	 * @param lexer the {@code DlpLexer} instance used to tokenize the character
	 * input before parsing
	 */
	public DlpParser(LpLexer lexer) {
		super(lexer);
	}
	
	/**
	 * Parses the given input as a dynamic logic program, i.e. as a sequence of
	 * logic program separated from each other by "newProgram." facts. These
	 * facts are not contained in any of the parsed programs.
	 *
	 * @return the parsed dynamic logic program
	 * @throws IOException (wrapped in an {@link lp.util.ExceptionAdapter}) in
	 * case an I/O error occurs while tokenizing the input
	 * @throws LpParserException if the input doesn't match the expression
	 * (Rule* EOF) (Rule is a non-terminal from the grammar in class
	 * description)
	 * @see #parseRule()
	 */
	public DynamicLogicProgram parseDlp() {
		DynamicLogicProgram result = new DynamicLogicProgram();
		LogicProgram p = new GeneralizedLogicProgram();
		while (hasMoreTokens()) {
			LpRule r = parseRule();
			if (SEP_RULE.equals(r)) {
				result.add(p);
				p = new GeneralizedLogicProgram();
			} else {
				p.add(r);
			}
		}
		result.add(p);
		return result;
	}
}