Mercurial > hg > Applications > JavaLite
view src/parser/LogicNodeParser.java @ 92:23853660f8b7
*** empty log message ***
author | kono |
---|---|
date | Fri, 18 Jan 2008 21:20:23 +0900 |
parents | 8affa0aa0fc0 |
children | 116a6afd11aa |
line wrap: on
line source
package parser; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.util.LinkedList; import verifier.LogicSolver; public class LogicNodeParser<Node extends LogicSolver> { /* * Simple Logic Node Parser * * Syntax is based on Prolog implementation of LITE verifier, but * it is not an operator order grammer parser. Currently we use * object comparison, but it is better to use id, because we can * use switch statements. * * Tokenize is done by Scanner. Nested parsing (necesssary for macro * expansion) is done by scanner.push()/pop(). * * Scope is handled by association linked list based scope. Use scope.push()/pop() * and scope.getLocalName(s). * * All nodes are created by logicnNodeFactory. In order to handle various * logic, constructed Node is parameterized. * * 2007/12 Shinji Kono */ public LogicNodeFactoryInterface<Node> logicNodeFactory; public LogicNodeScanner<Node> scanner; public Dictionary<Node> dict; public LogicNodeScope<Node> scope; public int position; public int end; public Token<Node> nextToken; private ExecutorInterface<Node> exec = new NullExecutor<Node>(); public LogicNodeParser() { super(); initialize(); } public LogicNodeParser(String string, LogicNodeFactoryInterface<Node> lf) { super(); logicNodeFactory = lf; initialize(); scanner.set(string); } public void initReservedWord() { dict.reserve(",",TokenID.And); dict.reserve(";",TokenID.Or); dict.reserve("(",TokenID.Paren); dict.reserve(")",TokenID.CloseParen); dict.reserve("{",TokenID.CurParen); dict.reserve("}",TokenID.CloseCurParen); dict.reserve("[",TokenID.BParen); dict.reserve("]",TokenID.CloseBParen); dict.reserve("~",TokenID.Not); dict.reserve(".",TokenID.Period); dict.reserve("?",TokenID.Question); dict.reserve(":",TokenID.Colon); dict.reserve("exists",TokenID.Exists); dict.reserve("true",TokenID.True); dict.reserve("false",TokenID.False); } public void initialize() { dict = new Dictionary<Node>(); scope = new LogicNodeScope<Node>(null,dict); initReservedWord(); scanner = new LogicNodeScanner<Node>(dict); } public Node parse() { if (scanner==null) return null; nextToken(); return expr1(); } 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(); exec.verify(n); } while(scanner.hasRemaining()); scanner = scanner.popScanner(); nextToken = scanner.nextToken; return n; } public Node expr1() { Node n = expr2(); while(nextToken.type == TokenID.Or) { nextToken(); n = logicNodeFactory.orNode(n, expr2()); } return n; } public Node expr2() { Node n = expr3(); while(nextToken.type == TokenID.And) { nextToken(); n = logicNodeFactory.andNode(n, expr3()); } return n; } public Node expr3() { if (nextToken.type==TokenID.Not) { nextToken(); return logicNodeFactory.notNode(expr3()); } else if (nextToken.type==TokenID.Exists) { return quantifier(); } return expr4(); } /* * exists(x,(x,a)) * this operator has a local scope */ public Node quantifier() { LinkedList<Node> arg; nextToken(); if (nextToken.type==TokenID.Paren) { // symbolc x havs been already converted to a variable when it was // evaluated as a macro argument. We cannot make it local here. // Do it in exists evaluation. nextToken(); arg = arguments(); if (arg.size()!=2 /* || !arg.get(0).isVariable() */) { error("bad quantifier"); return logicNodeFactory.trueNode(); } return logicNodeFactory.existsNode(arg.get(0),arg.get(1)); } else { error("( expected"); return logicNodeFactory.trueNode(); } } public Node expr4() { Node n = term(); if (nextToken.type==TokenID.Paren) { // predicate ( or macro ) nextToken(); n = logicNodeFactory.predicateNode(n,arguments()); } return n; } protected LinkedList<Node> arguments() { Node n; LinkedList<Node> arg = new LinkedList<Node>(); while(nextToken.type!=TokenID.CloseParen) { n = expr3(); arg.add(n); if (nextToken.type == TokenID.And) nextToken(); } if (nextToken.type==TokenID.CloseParen) nextToken(); else { scanner.error(") expected"); } return arg; } protected Node term() { Node n = null; switch (nextToken.type) { case Paren: nextToken(); n = expr1(); if (nextToken.type==TokenID.CloseParen) { } else { // syntax error; scanner.error(") expected but got "+nextToken); return logicNodeFactory.trueNode(); } break; case CurParen: nextToken(); n = expr1(); if (nextToken.type==TokenID.CloseCurParen) { } else { // syntax error; scanner.error("} expected"); } break; case NUMBER: n = logicNodeFactory.numberNode(Integer.parseInt(nextToken.name)); break; case True: n = logicNodeFactory.trueNode(); break; case False: n = logicNodeFactory.falseNode(); break; case NULL: case Period: 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; } /* * All names in LogicNode are variables. A token represents * name. To get the variable, use this method. */ protected Node makeVariable(Token<Node> t) { Node n; if ((n=t.value())==null) { n = logicNodeFactory.variableNode(t.realName(),true); t.setValue(n); } // n.token = t; 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 setExecutor(ExecutorInterface<Node> exec) { this.exec = exec; } public boolean getResource(String filename) { System.out.println("try to get resource ... "+filename); try { URL rsrc = getClass().getResource(filename); if (rsrc==null) throw new IOException(); InputStream in = rsrc.openStream(); parse(in); System.out.println("done."); return true; } catch (IOException e) { System.out.println("failed."); return false; } } public void showResourceFile(String file) { try { InputStream in; in = getClass().getResourceAsStream("/"+file); if (in==null) { in = new FileInputStream(file); } byte[] buf = new byte[4096]; for(int len; (len=in.read(buf,0,4096))>0;) { System.out.write(buf,0,len); } } catch (IOException e) { } } public void error(String err) { scanner.error(err); } }