view src/plparser/PropertyListParser.java @ 1:b149a5aa465a

Parser is written
author kono@ie.u-ryukyu.ac.jp
date Sat, 28 Aug 2010 17:39:34 +0900
parents
children 151c7fe6c61a
line wrap: on
line source

package plparser;

import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.LinkedList;


public class PropertyListParser<Node extends Property> {
	PropertyListNodeFactory<Node> lf;
	Token<Node> nextToken;
	public PropertyListScanner<Node> scanner;
	private Dictionary<Node> dict;
	// private PropertyListScope<Node> scope;
	
	public PropertyListParser(String string,
			PropertyListNodeFactory<Node> lf) {
		this.lf = lf;
	}

	public void initReservedWord() {
		dict.reserve("=",TokenID.Assign);
		dict.reserve(",",TokenID.Comma);
		dict.reserve(";",TokenID.Semicolon);
		dict.reserve("(",TokenID.Paren);
		dict.reserve(")",TokenID.CloseParen);
		dict.reserve("{",TokenID.CurParen);
		dict.reserve("}",TokenID.CloseCurParen);
		dict.reserve("true",TokenID.True);
		dict.reserve("false",TokenID.False);
	}

	public void initialize() {
		dict = new Dictionary<Node>();
		// scope = new PropertyListScope<Node>(null,dict);
		initReservedWord();
		scanner = new PropertyListScanner<Node>(dict);
	}

	public Node parse() {
		if (scanner==null) return null;
		nextToken();
		return term();
	}

	public Node parse(String exp) {
		Node n;
		scanner = scanner.pushScanner(exp);
		n = parse();
		scanner = scanner.popScanner();
		nextToken = scanner.nextToken;
		return n;
		
	}

	public void parseFile(String file) {
		try {
			scanner = scanner.pushScannerFile(file);
		} catch (FileNotFoundException e) {
			error("Can't open "+file);
			return;
		}
		doParse();
	}
	
	public void parse(InputStream file) {
		scanner = scanner.pushScannerFile(file,null);
		doParse();
	}

	public void parse(InputStream in, String prompt) {
		scanner = scanner.pushScannerFile(in,prompt);
		doParse();
	}
	
	public Node doParse() {
		Node n;
		do {
			n=parse();
		} while(scanner.hasRemaining());
		scanner = scanner.popScanner();
		nextToken = scanner.nextToken;
		return n;
	}

	public LinkedList<Node> expr1() {
		LinkedList<Node> list = new LinkedList<Node>();
	    expr2(list);
		while(nextToken.type == TokenID.Semicolon) {
			nextToken();
			expr2(list);
		}
		return list;
	}


	public void expr2(LinkedList<Node>list) {
		Node n1 = term();
		if (nextToken.type!=TokenID.Assign) {
			error("needs assignment");
			return;
		}
		Node n2 = term();
		list.add(n1); list.add(n2);
		return;
	}

	public LinkedList<Node> expr3() {
		LinkedList<Node>list = new LinkedList<Node>();
		Node n1 = term();
		list.add(n1); 
		while (nextToken.type==TokenID.Comma) {
			Node n2 = term();
			list.add(n2);
		}
		return list;
	}
	
	protected Node makeVariable(Token<Node> t) {
		Node n;
		if ((n=t.value())==null) {
			n =  lf.variableNode(t.name(),true);
			t.setValue(n);
		}
		// n.token = t;
		return n;
	}

	protected Node term() {
		Node n = null;
		switch (nextToken.type) {
		case Paren: // Array
			nextToken();
			LinkedList<Node>list1 = expr3();
			if (nextToken.type==TokenID.CloseParen) {
			} else { // syntax error;
				scanner.error(") expected but got "+nextToken);
				return lf.trueNode();
			}
			return lf.arrayNode(list1);
		case CurParen: // Dictionary
			nextToken();
			LinkedList<Node> list = expr1();
			if (nextToken.type==TokenID.CloseCurParen) {
			} else { // syntax error;
				scanner.error("} expected");
			}
			return lf.dictionaryNode(list);
		case NUMBER:
			n = lf.numberNode(Integer.parseInt(nextToken.name));
			break;
		case NULL: 
			break;
		default:
			if (nextToken.type.isVariable()) 
				n = makeVariable(nextToken);
			else {
				// error("Internal ununderstandable term '"+nextToken+"' type: "+nextToken.type+".");
				n = makeVariable(nextToken); // skip any
			}
		}
		nextToken();
		return n;
	}


	/*
	 * Syntactical Short cut for scanner.textToken()
	 * 
	 * It never returns null, to check EOF, 
	 *     nextToken.type==TokenID.NULL
	 */
	public Token<Node> nextToken() {
		return nextToken = scanner.nextToken();
	}
	

	public void error(String err) {
		scanner.error(err);
	}
}