Mercurial > hg > Members > kono > PLparser
view src/plparser/PropertyListParser.java @ 5:29b5497fc942
full test passed.
author | one |
---|---|
date | Sun, 29 Aug 2010 20:28:00 +0900 |
parents | 29c0866e3a84 |
children | 563bcb96e4fa |
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; // scope is necessary if you have to parse nested name scope // private PropertyListScope<Node> scope; public PropertyListParser(String string, PropertyListNodeFactory<Node> lf) { this.lf = lf; initialize(); scanner.set(string); } public PropertyListParser(PropertyListNodeFactory<Node> lf) { this.lf = lf; initialize(); } 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; // internal error if (scanner.cb==null) return null; // nothing to do 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 Node parseFile(String file) { try { scanner = scanner.pushScannerFile(file); } catch (FileNotFoundException e) { error("Can't open "+file); return null; } return doParse(); } public Node parse(InputStream file) { scanner = scanner.pushScannerFile(file,null); return doParse(); } public Node parse(InputStream in, String prompt) { scanner = scanner.pushScannerFile(in,prompt); return doParse(); } public Node doParse() { Node n; do { n=parse(); } while(scanner.hasRemaining()); scanner = scanner.popScanner(); nextToken = scanner.nextToken; return n; } /** * expr1 {} Dictionary * @return list of node (key,value,key,value) */ public LinkedList<Node> expr1() { LinkedList<Node> list = new LinkedList<Node>(); if (nextToken.type==TokenID.CloseCurParen ) return list; expr2(list); while(nextToken.type == TokenID.Semicolon) { nextToken(); if (nextToken.type==TokenID.CloseCurParen ) return list; expr2(list); } return list; } /** * expr2 * key = value */ public void expr2(LinkedList<Node>list) { Node n1 = term(); if (nextToken.type!=TokenID.Assign) { error("needs assignment"); return; } nextToken(); Node n2 = term(); list.add(n1); list.add(n2); return; } /** * expr3 Array * @return list of node */ public LinkedList<Node> expr3() { LinkedList<Node>list = new LinkedList<Node>(); if (nextToken.type==TokenID.CloseParen) return list; Node n1 = term(); list.add(n1); while (nextToken.type==TokenID.Comma) { nextToken(); if (nextToken.type==TokenID.CloseParen) return list; 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; error(") expected but got "+nextToken); return lf.trueNode(); } nextToken(); return lf.arrayNode(list1); case CurParen: // Dictionary nextToken(); LinkedList<Node> list = expr1(); if (nextToken.type==TokenID.CloseCurParen) { } else { // syntax error; error("} expected but got "+nextToken); } nextToken(); 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); } }