CParser.java

package edu.udel.cis.vsl.abc.front.c.parse;

import java.util.Stack;

import org.antlr.runtime.CommonTokenStream;
import org.antlr.runtime.RecognitionException;
import org.antlr.runtime.TokenStream;
import org.antlr.runtime.tree.CommonTree;

import edu.udel.cis.vsl.abc.config.IF.Configurations.Language;
import edu.udel.cis.vsl.abc.err.IF.ABCRuntimeException;
import edu.udel.cis.vsl.abc.front.IF.ParseException;
import edu.udel.cis.vsl.abc.front.IF.Parser;
import edu.udel.cis.vsl.abc.front.IF.PreprocessorRuntimeException;
import edu.udel.cis.vsl.abc.front.IF.RuntimeParseException;
import edu.udel.cis.vsl.abc.front.c.ptree.CParseTree;
import edu.udel.cis.vsl.abc.front.common.parse.TreeUtils;
import edu.udel.cis.vsl.abc.token.IF.CivlcTokenSource;

// why not make static methods of all these?
/**
 * <p>
 * Simple interface for a parser of C programs. It includes a bunch of integer
 * constants which are ID numbers of each kind of token (real or fake) that can
 * occur in a C parse tree.
 * </p>
 * 
 * 
 * @author siegel
 * 
 */
public class CParser implements Parser {
	/**
	 * Kind of parsing rule
	 * 
	 * @author Manchun Zheng
	 *
	 */
	public static enum RuleKind {
		/**
		 * the rule for translating a translation unit
		 */
		TRANSLATION_UNIT,
		/**
		 * the rule for translating a block item
		 */
		BLOCK_ITEM,
		/**
		 * ACSL contracts
		 */
		CONTRACT
	}

	/* *************************** Constructors *************************** */

	public CParser() {

	}

	/* ************************* CParser Methods ************************** */

	/**
	 * Returns the ANTLR CommonTree resulting from parsing the input, after some
	 * "post-processing" has been done to the tree to fill in some fields.
	 * 
	 * @return the ANTLR tree that results from parsing
	 * @throws ParseException
	 *             if something goes wrong parsing the input
	 */
	public CParseTree parse(RuleKind rule, CivlcTokenSource tokenSource,
			Stack<ScopeSymbols> symbols) throws ParseException {
		TokenStream stream = new CommonTokenStream(tokenSource);
		CivlCParser parser = new CivlCParser(stream);
		PP2CivlcTokenCConverter pp2cConverter = new PP2CivlcTokenCConverter();
		CommonTree root;

		parser.setSymbols_stack(symbols);
		stream = pp2cConverter.convert(stream);
		try {
			switch (rule) {
				case TRANSLATION_UNIT :
					try {
						root = (CommonTree) parser.translationUnit().getTree();
					} catch (PreprocessorRuntimeException ex) {
						throw new ParseException(ex.getMessage(),
								ex.getToken());
					}
					break;
				case BLOCK_ITEM :
					root = (CommonTree) parser.blockItemWithScope().getTree();
					break;
				// TODO: confusing there is no case for CONTRACT.
				// That is because this method will not be used to parse
				// contracts.
				default :
					throw new ABCRuntimeException("Unreachable");
			}
			TreeUtils.postProcessTree(root);
		} catch (RecognitionException e) {
			throw new ParseException(e.getMessage(), e.token);
		} catch (RuntimeParseException e) {
			throw new ParseException(e.getMessage());
		}
		return new CParseTree(Language.CIVL_C, rule, tokenSource, root);
	}

	@Override
	public CParseTree parse(CivlcTokenSource tokenSource)
			throws ParseException {
		return parse(RuleKind.TRANSLATION_UNIT, tokenSource,
				new Stack<ScopeSymbols>());
	}

}