// [PD] 4.0.0 Non-recursive version System.Text.StringBuilder getString(System.Text.StringBuilder sbuf) { PBListCell pbt = this; PBTerm h; do { h = pbt.arguments [0]; if (h.Atom && h.Name.Length == 1) { // Is head a one char // atom? sbuf.Append(h.Name); } else if (h.Integer) { // Is head an integer? // *** FIXME: Perhaps check if this cast truncates. int c = (int)h.intValue(); if (!isUnicode(c)) { throw new InvalidOperationException("not a list of characters"); } appendCodePoint(sbuf, c); } else { throw new InvalidOperationException("not a list of characters"); } PBTerm t = pbt.arguments [1]; // tail() if (t == PBTerm.NIL) { return(sbuf); } else { if (t.ListCell) { pbt = (PBListCell)t; } else { throw new InvalidOperationException("not a list of characters"); } } } while (true); }
/* * [PM] 4.1.3 Manage an explicit stack to avoid running out of Java stack * (SPRM 11909) */ PBTerm parseTerm(System.IO.Stream stream) { Work outer = new Work(new PBTerm[1], null); Work stack = outer; do { int chr = stream.ReadByte(); PBTerm term; if (FastParser.logging) { Console.Out.WriteLine("parseTerm() switch on " + chr); } switch (chr) { case INTEGER: { string val = getString(stream); // return new PBInteger(val); try { term = new PBInteger(Convert.ToInt64(val, 10), val); } catch (FormatException /* nfe */) { // FIXME: Perhaps not catch FormatException? If malformed then it is no bignum either. term = new PBBignum(BigInteger.Parse(val), val); } catch (OverflowException) { term = new PBBignum(BigInteger.Parse(val), val); } if (logging) { Console.Out.WriteLine("bump() INTEGER " + val); } stack = stack.bump(term); } break; case FLOAT: { string val = getString(stream); term = new PBFloat(Double.Parse(val), val); if (logging) { Console.Out.WriteLine("bump() FLOAT " + val); } stack = stack.bump(term); } break; case ATOM: { string val = getString(stream); term = PBTerm.makeAtom(val); if (logging) { Console.Out.WriteLine("bump() ATOM " + val); } stack = stack.bump(term); } break; case VARIABLE: { string val = '_' + getString(stream); if (variableTable == null) { variableTable = System.Collections.Hashtable.Synchronized(new System.Collections.Hashtable()); } PBVariable var = (PBVariable)variableTable [val]; if (var == null) { var = new PBVariable(val); variableTable [val] = var; } term = var; if (logging) { Console.Out.WriteLine("bump() VARIABLE " + val); } stack = stack.bump(term); } break; case STRING: { byte[] val = getBytes(stream); PBTerm t = parseTerm(stream); // Note that this builds the list from the end. for (int i = val.Length - 1; i >= 0; i--) { t = PBTerm.makeTerm(new PBInteger(val [i]), t); } term = t; if (logging) { Console.Out.WriteLine("bump() STRING " + val); } stack = stack.bump(term); } break; case LIST: { const int noTerms = 2; PBTerm[] terms = new PBTerm[noTerms]; term = new PBListCell(terms); if (logging) { Console.Out.WriteLine("bump() LIST ./2"); } stack = stack.bump(term, terms); } break; case NIL: { term = PBTerm.NIL; if (logging) { Console.Out.WriteLine("bump() NIL"); } stack = stack.bump(term); } break; case COMPOUND: { string val = getString(stream); int noTerms = stream.ReadByte(); PBTerm[] terms = new PBTerm[noTerms]; term = PBTerm.makeTerm(val, terms); if (logging) { Console.Out.WriteLine("bump() COMPOUND " + val + "/" + noTerms); } stack = stack.bump(term, terms); } break; default: throw new System.IO.IOException("Parse error: illegal character " + (char)chr); } } while (stack != null); // assert outer != null; // assert outer.args != null && outer.args.length == 1; // assert validTerm(outer.args[0]); if (logging) { Console.Out.WriteLine("parseTermWithStack returning " + outer.args [0]); } return(outer.args [0]); }