www

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | Submodules | README | LICENSE

n3parser.js (41650B)


      1 $rdf.N3Parser = function () {
      2 
      3   function hexify(str) { // also used in parser
      4     return encodeURI(str);
      5   }
      6 
      7   // Things we need to define to make converted pythn code work in js
      8   // environment of $rdf
      9   var RDFSink_forSomeSym = "http://www.w3.org/2000/10/swap/log#forSome";
     10   var RDFSink_forAllSym = "http://www.w3.org/2000/10/swap/log#forAll";
     11   var Logic_NS = "http://www.w3.org/2000/10/swap/log#";
     12 
     13   //  pyjs seems to reference runtime library which I didn't find
     14   var pyjslib_Tuple = function (theList) {
     15       return theList
     16     };
     17 
     18   var pyjslib_List = function (theList) {
     19       return theList
     20     };
     21 
     22   var pyjslib_Dict = function (listOfPairs) {
     23       if(listOfPairs.length > 0)
     24         throw "missing.js: oops nnonempty dict not imp";
     25       return [];
     26     }
     27 
     28   var pyjslib_len = function (s) {
     29       return s.length
     30     }
     31 
     32   var pyjslib_slice = function (str, i, j) {
     33       if(typeof str.slice == 'undefined')
     34         throw '@@ mising.js: No .slice function for ' + str + ' of type ' + (typeof str)
     35       if((typeof j == 'undefined') || (j == null)) return str.slice(i);
     36       return str.slice(i, j) // @ exactly the same spec?
     37     }
     38   var StopIteration = Error('dummy error stop iteration');
     39 
     40   var pyjslib_Iterator = function (theList) {
     41       this.last = 0;
     42       this.li = theList;
     43       this.next = function () {
     44         if(this.last == this.li.length) throw StopIteration;
     45         return this.li[this.last++];
     46       }
     47       return this;
     48     };
     49 
     50   var ord = function (str) {
     51       return str.charCodeAt(0)
     52     }
     53 
     54   var string_find = function (str, s) {
     55       return str.indexOf(s)
     56     }
     57 
     58   var assertFudge = function (condition, desc) {
     59       if(condition) return;
     60       if(desc) throw "python Assertion failed: " + desc;
     61       throw "(python) Assertion failed.";
     62     }
     63 
     64 
     65   var stringFromCharCode = function (uesc) {
     66       return String.fromCharCode(uesc);
     67     }
     68 
     69   var uripath_join = function (base, given) {
     70       return $rdf.Util.uri.join(given, base) // sad but true
     71     }
     72 
     73   var becauseSubexpression = null; // No reason needed
     74   var diag_tracking = 0;
     75   var diag_chatty_flag = 0;
     76   var diag_progress = function (str) {
     77       /*$rdf.log.debug(str);*/
     78     }
     79 
     80     // why_BecauseOfData = function(doc, reason) { return doc };
     81 
     82   var RDF_type_URI = "http://www.w3.org/1999/02/22-rdf-syntax-ns#type";
     83   var DAML_sameAs_URI = "http://www.w3.org/2002/07/owl#sameAs";
     84 
     85   /*
     86 function SyntaxError(details) {
     87     return new __SyntaxError(details);
     88 }
     89 */
     90 
     91   function __SyntaxError(details) {
     92     this.details = details
     93   }
     94 
     95   /*
     96 
     97 $Id: n3parser.js 14561 2008-02-23 06:37:26Z kennyluck $
     98 
     99 HAND EDITED FOR CONVERSION TO JAVASCRIPT
    100 
    101 This module implements a Nptation3 parser, and the final
    102 part of a notation3 serializer.
    103 
    104 See also:
    105 
    106 Notation 3
    107 http://www.w3.org/DesignIssues/Notation3
    108 
    109 Closed World Machine - and RDF Processor
    110 http://www.w3.org/2000/10/swap/cwm
    111 
    112 To DO: See also "@@" in comments
    113 
    114 - Clean up interfaces
    115 ______________________________________________
    116 
    117 Module originally by Dan Connolly, includeing notation3
    118 parser and RDF generator. TimBL added RDF stream model
    119 and N3 generation, replaced stream model with use
    120 of common store/formula API.  Yosi Scharf developped
    121 the module, including tests and test harness.
    122 
    123 */
    124 
    125   var ADDED_HASH = "#";
    126   var LOG_implies_URI = "http://www.w3.org/2000/10/swap/log#implies";
    127   var INTEGER_DATATYPE = "http://www.w3.org/2001/XMLSchema#integer";
    128   var FLOAT_DATATYPE = "http://www.w3.org/2001/XMLSchema#double";
    129   var DECIMAL_DATATYPE = "http://www.w3.org/2001/XMLSchema#decimal";
    130   var BOOLEAN_DATATYPE = "http://www.w3.org/2001/XMLSchema#boolean";
    131   var option_noregen = 0;
    132   var _notQNameChars = "\t\r\n !\"#$%&'()*.,+/;<=>?@[\\]^`{|}~";
    133   var _notNameChars = (_notQNameChars + ":");
    134   var _rdfns = "http://www.w3.org/1999/02/22-rdf-syntax-ns#";
    135   var N3CommentCharacter = "#";
    136   var eol = new RegExp("^[ \\t]*(#[^\\n]*)?\\r?\\n", 'g');
    137   var eof = new RegExp("^[ \\t]*(#[^\\n]*)?$", 'g');
    138   var ws = new RegExp("^[ \\t]*", 'g');
    139   var signed_integer = new RegExp("^[-+]?[0-9]+", 'g');
    140   var number_syntax = new RegExp("^([-+]?[0-9]+)(\\.[0-9]+)?(e[-+]?[0-9]+)?", 'g');
    141   var digitstring = new RegExp("^[0-9]+", 'g');
    142   var interesting = new RegExp("[\\\\\\r\\n\\\"]", 'g');
    143   var langcode = new RegExp("^[a-zA-Z0-9]+(-[a-zA-Z0-9]+)?", 'g');
    144 
    145   function SinkParser(store, openFormula, thisDoc, baseURI, genPrefix, metaURI, flags, why) {
    146     return new __SinkParser(store, openFormula, thisDoc, baseURI, genPrefix, metaURI, flags, why);
    147   }
    148 
    149   function __SinkParser(store, openFormula, thisDoc, baseURI, genPrefix, metaURI, flags, why) {
    150     if(typeof openFormula == 'undefined') openFormula = null;
    151     if(typeof thisDoc == 'undefined') thisDoc = "";
    152     if(typeof baseURI == 'undefined') baseURI = null;
    153     if(typeof genPrefix == 'undefined') genPrefix = "";
    154     if(typeof metaURI == 'undefined') metaURI = null;
    155     if(typeof flags == 'undefined') flags = "";
    156     if(typeof why == 'undefined') why = null;
    157     /*
    158     note: namespace names should *not* end in #;
    159     the # will get added during qname processing */
    160 
    161     this._bindings = new pyjslib_Dict([]);
    162     this._flags = flags;
    163     if((thisDoc != "")) {
    164       assertFudge((thisDoc.indexOf(":") >= 0), ("Document URI not absolute: " + thisDoc));
    165       this._bindings[""] = ((thisDoc + "#"));
    166     }
    167     this._store = store;
    168     if(genPrefix) {
    169       store.setGenPrefix(genPrefix);
    170     }
    171     this._thisDoc = thisDoc;
    172     this.source = store.sym(thisDoc);
    173     this.lines = 0;
    174     this.statementCount = 0;
    175     this.startOfLine = 0;
    176     this.previousLine = 0;
    177     this._genPrefix = genPrefix;
    178     this.keywords = new pyjslib_List(["a", "this", "bind", "has", "is", "of", "true", "false"]);
    179     this.keywordsSet = 0;
    180     this._anonymousNodes = new pyjslib_Dict([]);
    181     this._variables = new pyjslib_Dict([]);
    182     this._parentVariables = new pyjslib_Dict([]);
    183     this._reason = why;
    184     this._reason2 = null;
    185     if(diag_tracking) {
    186       this._reason2 = why_BecauseOfData(store.sym(thisDoc), this._reason);
    187     }
    188     if(baseURI) {
    189       this._baseURI = baseURI;
    190     } else {
    191       if(thisDoc) {
    192         this._baseURI = thisDoc;
    193       } else {
    194         this._baseURI = null;
    195       }
    196     }
    197     assertFudge(!(this._baseURI) || (this._baseURI.indexOf(":") >= 0));
    198     if(!(this._genPrefix)) {
    199       if(this._thisDoc) {
    200         this._genPrefix = (this._thisDoc + "#_g");
    201       } else {
    202         this._genPrefix = RDFSink_uniqueURI();
    203       }
    204     }
    205     if((openFormula == null)) {
    206       if(this._thisDoc) {
    207         this._formula = store.formula((thisDoc + "#_formula"));
    208       } else {
    209         this._formula = store.formula();
    210       }
    211     } else {
    212       this._formula = openFormula;
    213     }
    214     this._context = this._formula;
    215     this._parentContext = null;
    216   }
    217   __SinkParser.prototype.here = function (i) {
    218     return((((this._genPrefix + "_L") + this.lines) + "C") + ((i - this.startOfLine) + 1));
    219   };
    220   __SinkParser.prototype.formula = function () {
    221     return this._formula;
    222   };
    223   __SinkParser.prototype.loadStream = function (stream) {
    224     return this.loadBuf(stream.read());
    225   };
    226   __SinkParser.prototype.loadBuf = function (buf) {
    227     /*
    228     Parses a buffer and returns its top level formula*/
    229 
    230     this.startDoc();
    231     this.feed(buf);
    232     return this.endDoc();
    233   };
    234   __SinkParser.prototype.feed = function (octets) {
    235     /*
    236     Feed an octet stream tothe parser
    237     
    238     if BadSyntax is raised, the string
    239     passed in the exception object is the
    240     remainder after any statements have been parsed.
    241     So if there is more data to feed to the
    242     parser, it should be straightforward to recover.*/
    243 
    244     var str = octets;
    245     var i = 0;
    246     while((i >= 0)) {
    247       var j = this.skipSpace(str, i);
    248       if((j < 0)) {
    249         return;
    250       }
    251       var i = this.directiveOrStatement(str, j);
    252       if((i < 0)) {
    253         throw BadSyntax(this._thisDoc, this.lines, str, j, "expected directive or statement");
    254       }
    255     }
    256   };
    257   __SinkParser.prototype.directiveOrStatement = function (str, h) {
    258     var i = this.skipSpace(str, h);
    259     if((i < 0)) {
    260       return i;
    261     }
    262     var j = this.directive(str, i);
    263     if((j >= 0)) {
    264       return this.checkDot(str, j);
    265     }
    266     var j = this.statement(str, i);
    267     if((j >= 0)) {
    268       return this.checkDot(str, j);
    269     }
    270     return j;
    271   };
    272   __SinkParser.prototype.tok = function (tok, str, i) {
    273     /*
    274     Check for keyword.  Space must have been stripped on entry and
    275     we must not be at end of file.*/
    276     var whitespace = "\t\n\v\f\r ";
    277     if((pyjslib_slice(str, i, (i + 1)) == "@")) {
    278       var i = (i + 1);
    279     } else {
    280       if(($rdf.Util.ArrayIndexOf(this.keywords, tok) < 0)) {
    281         return -1;
    282       }
    283     }
    284     var k = (i + pyjslib_len(tok));
    285     if((pyjslib_slice(str, i, k) == tok) && (_notQNameChars.indexOf(str.charAt(k)) >= 0)) {
    286       return k;
    287     } else {
    288       return -1;
    289     }
    290   };
    291   __SinkParser.prototype.directive = function (str, i) {
    292     var j = this.skipSpace(str, i);
    293     if((j < 0)) {
    294       return j;
    295     }
    296     var res = new pyjslib_List([]);
    297     var j = this.tok("bind", str, i);
    298     if((j > 0)) {
    299       throw BadSyntax(this._thisDoc, this.lines, str, i, "keyword bind is obsolete: use @prefix");
    300     }
    301     var j = this.tok("keywords", str, i);
    302     if((j > 0)) {
    303       var i = this.commaSeparatedList(str, j, res, false);
    304       if((i < 0)) {
    305         throw BadSyntax(this._thisDoc, this.lines, str, i, "'@keywords' needs comma separated list of words");
    306       }
    307       this.setKeywords(pyjslib_slice(res, null, null));
    308       if((diag_chatty_flag > 80)) {
    309         diag_progress("Keywords ", this.keywords);
    310       }
    311       return i;
    312     }
    313     var j = this.tok("forAll", str, i);
    314     if((j > 0)) {
    315       var i = this.commaSeparatedList(str, j, res, true);
    316       if((i < 0)) {
    317         throw BadSyntax(this._thisDoc, this.lines, str, i, "Bad variable list after @forAll");
    318       }
    319 
    320       var __x = new pyjslib_Iterator(res);
    321       try {
    322         while(true) {
    323           var x = __x.next();
    324 
    325 
    326           if($rdf.Util.ArrayIndexOf(this._variables, x) < 0 || ($rdf.Util.ArrayIndexOf(this._parentVariables, x) >= 0)) {
    327             this._variables[x] = (this._context.newUniversal(x));
    328           }
    329 
    330         }
    331       } catch(e) {
    332         if(e != StopIteration) {
    333           throw e;
    334         }
    335       }
    336 
    337       return i;
    338     }
    339     var j = this.tok("forSome", str, i);
    340     if((j > 0)) {
    341       var i = this.commaSeparatedList(str, j, res, this.uri_ref2);
    342       if((i < 0)) {
    343         throw BadSyntax(this._thisDoc, this.lines, str, i, "Bad variable list after @forSome");
    344       }
    345 
    346       var __x = new pyjslib_Iterator(res);
    347       try {
    348         while(true) {
    349           var x = __x.next();
    350 
    351 
    352           this._context.declareExistential(x);
    353 
    354         }
    355       } catch(e) {
    356         if(e != StopIteration) {
    357           throw e;
    358         }
    359       }
    360 
    361       return i;
    362     }
    363     var j = this.tok("prefix", str, i);
    364     if((j >= 0)) {
    365       var t = new pyjslib_List([]);
    366       var i = this.qname(str, j, t);
    367       if((i < 0)) {
    368         throw BadSyntax(this._thisDoc, this.lines, str, j, "expected qname after @prefix");
    369       }
    370       var j = this.uri_ref2(str, i, t);
    371       if((j < 0)) {
    372         throw BadSyntax(this._thisDoc, this.lines, str, i, "expected <uriref> after @prefix _qname_");
    373       }
    374       var ns = t[1].uri;
    375       if(this._baseURI) {
    376         var ns = uripath_join(this._baseURI, ns);
    377       } else {
    378         assertFudge((ns.indexOf(":") >= 0), "With no base URI, cannot handle relative URI for NS");
    379       }
    380       assertFudge((ns.indexOf(":") >= 0));
    381       this._bindings[t[0][0]] = (ns);
    382 
    383       this.bind(t[0][0], hexify(ns));
    384       return j;
    385     }
    386     var j = this.tok("base", str, i);
    387     if((j >= 0)) {
    388       var t = new pyjslib_List([]);
    389       var i = this.uri_ref2(str, j, t);
    390       if((i < 0)) {
    391         throw BadSyntax(this._thisDoc, this.lines, str, j, "expected <uri> after @base ");
    392       }
    393       var ns = t[0].uri;
    394       if(this._baseURI) {
    395         var ns = uripath_join(this._baseURI, ns);
    396       } else {
    397         throw BadSyntax(this._thisDoc, this.lines, str, j, (("With no previous base URI, cannot use relative URI in @base  <" + ns) + ">"));
    398       }
    399       assertFudge((ns.indexOf(":") >= 0));
    400       this._baseURI = ns;
    401       return i;
    402     }
    403     return -1;
    404   };
    405   __SinkParser.prototype.bind = function (qn, uri) {
    406     if((qn == "")) {
    407     } else {
    408       this._store.setPrefixForURI(qn, uri);
    409     }
    410   };
    411   __SinkParser.prototype.setKeywords = function (k) {
    412     /*
    413     Takes a list of strings*/
    414 
    415     if((k == null)) {
    416       this.keywordsSet = 0;
    417     } else {
    418       this.keywords = k;
    419       this.keywordsSet = 1;
    420     }
    421   };
    422   __SinkParser.prototype.startDoc = function () {};
    423   __SinkParser.prototype.endDoc = function () {
    424     /*
    425     Signal end of document and stop parsing. returns formula*/
    426 
    427     return this._formula;
    428   };
    429   __SinkParser.prototype.makeStatement = function (quad) {
    430     quad[0].add(quad[2], quad[1], quad[3], this.source);
    431     this.statementCount += 1;
    432   };
    433   __SinkParser.prototype.statement = function (str, i) {
    434     var r = new pyjslib_List([]);
    435     var i = this.object(str, i, r);
    436     if((i < 0)) {
    437       return i;
    438     }
    439     var j = this.property_list(str, i, r[0]);
    440     if((j < 0)) {
    441       throw BadSyntax(this._thisDoc, this.lines, str, i, "expected propertylist");
    442     }
    443     return j;
    444   };
    445   __SinkParser.prototype.subject = function (str, i, res) {
    446     return this.item(str, i, res);
    447   };
    448   __SinkParser.prototype.verb = function (str, i, res) {
    449     /*
    450     has _prop_
    451     is _prop_ of
    452     a
    453     =
    454     _prop_
    455     >- prop ->
    456     <- prop -<
    457     _operator_*/
    458 
    459     var j = this.skipSpace(str, i);
    460     if((j < 0)) {
    461       return j;
    462     }
    463     var r = new pyjslib_List([]);
    464     var j = this.tok("has", str, i);
    465     if((j >= 0)) {
    466       var i = this.prop(str, j, r);
    467       if((i < 0)) {
    468         throw BadSyntax(this._thisDoc, this.lines, str, j, "expected property after 'has'");
    469       }
    470       res.push(new pyjslib_Tuple(["->", r[0]]));
    471       return i;
    472     }
    473     var j = this.tok("is", str, i);
    474     if((j >= 0)) {
    475       var i = this.prop(str, j, r);
    476       if((i < 0)) {
    477         throw BadSyntax(this._thisDoc, this.lines, str, j, "expected <property> after 'is'");
    478       }
    479       var j = this.skipSpace(str, i);
    480       if((j < 0)) {
    481         throw BadSyntax(this._thisDoc, this.lines, str, i, "End of file found, expected property after 'is'");
    482         return j;
    483       }
    484       var i = j;
    485       var j = this.tok("of", str, i);
    486       if((j < 0)) {
    487         throw BadSyntax(this._thisDoc, this.lines, str, i, "expected 'of' after 'is' <prop>");
    488       }
    489       res.push(new pyjslib_Tuple(["<-", r[0]]));
    490       return j;
    491     }
    492     var j = this.tok("a", str, i);
    493     if((j >= 0)) {
    494       res.push(new pyjslib_Tuple(["->", this._store.sym(RDF_type_URI)]));
    495       return j;
    496     }
    497     if((pyjslib_slice(str, i, (i + 2)) == "<=")) {
    498       res.push(new pyjslib_Tuple(["<-", this._store.sym((Logic_NS + "implies"))]));
    499       return(i + 2);
    500     }
    501     if((pyjslib_slice(str, i, (i + 1)) == "=")) {
    502       if((pyjslib_slice(str, (i + 1), (i + 2)) == ">")) {
    503         res.push(new pyjslib_Tuple(["->", this._store.sym((Logic_NS + "implies"))]));
    504         return(i + 2);
    505       }
    506       res.push(new pyjslib_Tuple(["->", this._store.sym(DAML_sameAs_URI)]));
    507       return(i + 1);
    508     }
    509     if((pyjslib_slice(str, i, (i + 2)) == ":=")) {
    510       res.push(new pyjslib_Tuple(["->", (Logic_NS + "becomes")]));
    511       return(i + 2);
    512     }
    513     var j = this.prop(str, i, r);
    514     if((j >= 0)) {
    515       res.push(new pyjslib_Tuple(["->", r[0]]));
    516       return j;
    517     }
    518     if((pyjslib_slice(str, i, (i + 2)) == ">-") || (pyjslib_slice(str, i, (i + 2)) == "<-")) {
    519       throw BadSyntax(this._thisDoc, this.lines, str, j, ">- ... -> syntax is obsolete.");
    520     }
    521     return -1;
    522   };
    523   __SinkParser.prototype.prop = function (str, i, res) {
    524     return this.item(str, i, res);
    525   };
    526   __SinkParser.prototype.item = function (str, i, res) {
    527     return this.path(str, i, res);
    528   };
    529   __SinkParser.prototype.blankNode = function (uri) {
    530     return this._context.bnode(uri, this._reason2);
    531   };
    532   __SinkParser.prototype.path = function (str, i, res) {
    533     /*
    534     Parse the path production.
    535     */
    536 
    537     var j = this.nodeOrLiteral(str, i, res);
    538     if((j < 0)) {
    539       return j;
    540     }
    541     while(("!^.".indexOf(pyjslib_slice(str, j, (j + 1))) >= 0)) {
    542       var ch = pyjslib_slice(str, j, (j + 1));
    543       if((ch == ".")) {
    544         var ahead = pyjslib_slice(str, (j + 1), (j + 2));
    545         if(!(ahead) || (_notNameChars.indexOf(ahead) >= 0) && (":?<[{(".indexOf(ahead) < 0)) {
    546           break;
    547         }
    548       }
    549       var subj = res.pop();
    550       var obj = this.blankNode(this.here(j));
    551       var j = this.node(str, (j + 1), res);
    552       if((j < 0)) {
    553         throw BadSyntax(this._thisDoc, this.lines, str, j, "EOF found in middle of path syntax");
    554       }
    555       var pred = res.pop();
    556       if((ch == "^")) {
    557         this.makeStatement(new pyjslib_Tuple([this._context, pred, obj, subj]));
    558       } else {
    559         this.makeStatement(new pyjslib_Tuple([this._context, pred, subj, obj]));
    560       }
    561       res.push(obj);
    562     }
    563     return j;
    564   };
    565   __SinkParser.prototype.anonymousNode = function (ln) {
    566     /*
    567     Remember or generate a term for one of these _: anonymous nodes*/
    568 
    569     var term = this._anonymousNodes[ln];
    570     if(term) {
    571       return term;
    572     }
    573     var term = this._store.bnode(this._context, this._reason2);
    574     this._anonymousNodes[ln] = (term);
    575     return term;
    576   };
    577   __SinkParser.prototype.node = function (str, i, res, subjectAlready) {
    578     if(typeof subjectAlready == 'undefined') subjectAlready = null;
    579     /*
    580     Parse the <node> production.
    581     Space is now skipped once at the beginning
    582     instead of in multipe calls to self.skipSpace().
    583     */
    584 
    585     var subj = subjectAlready;
    586     var j = this.skipSpace(str, i);
    587     if((j < 0)) {
    588       return j;
    589     }
    590     var i = j;
    591     var ch = pyjslib_slice(str, i, (i + 1));
    592     if((ch == "[")) {
    593       var bnodeID = this.here(i);
    594       var j = this.skipSpace(str, (i + 1));
    595       if((j < 0)) {
    596         throw BadSyntax(this._thisDoc, this.lines, str, i, "EOF after '['");
    597       }
    598       if((pyjslib_slice(str, j, (j + 1)) == "=")) {
    599         var i = (j + 1);
    600         var objs = new pyjslib_List([]);
    601         var j = this.objectList(str, i, objs);
    602 
    603         if((j >= 0)) {
    604           var subj = objs[0];
    605           if((pyjslib_len(objs) > 1)) {
    606 
    607             var __obj = new pyjslib_Iterator(objs);
    608             try {
    609               while(true) {
    610                 var obj = __obj.next();
    611 
    612 
    613                 this.makeStatement(new pyjslib_Tuple([this._context, this._store.sym(DAML_sameAs_URI), subj, obj]));
    614 
    615               }
    616             } catch(e) {
    617               if(e != StopIteration) {
    618                 throw e;
    619               }
    620             }
    621 
    622           }
    623           var j = this.skipSpace(str, j);
    624           if((j < 0)) {
    625             throw BadSyntax(this._thisDoc, this.lines, str, i, "EOF when objectList expected after [ = ");
    626           }
    627           if((pyjslib_slice(str, j, (j + 1)) == ";")) {
    628             var j = (j + 1);
    629           }
    630         } else {
    631           throw BadSyntax(this._thisDoc, this.lines, str, i, "objectList expected after [= ");
    632         }
    633       }
    634       if((subj == null)) {
    635         var subj = this.blankNode(bnodeID);
    636       }
    637       var i = this.property_list(str, j, subj);
    638       if((i < 0)) {
    639         throw BadSyntax(this._thisDoc, this.lines, str, j, "property_list expected");
    640       }
    641       var j = this.skipSpace(str, i);
    642       if((j < 0)) {
    643         throw BadSyntax(this._thisDoc, this.lines, str, i, "EOF when ']' expected after [ <propertyList>");
    644       }
    645       if((pyjslib_slice(str, j, (j + 1)) != "]")) {
    646         throw BadSyntax(this._thisDoc, this.lines, str, j, "']' expected");
    647       }
    648       res.push(subj);
    649       return(j + 1);
    650     }
    651     if((ch == "{")) {
    652       var ch2 = pyjslib_slice(str, (i + 1), (i + 2));
    653       if((ch2 == "$")) {
    654         i += 1;
    655         var j = (i + 1);
    656         var mylist = new pyjslib_List([]);
    657         var first_run = true;
    658         while(1) {
    659           var i = this.skipSpace(str, j);
    660           if((i < 0)) {
    661             throw BadSyntax(this._thisDoc, this.lines, str, i, "needed '$}', found end.");
    662           }
    663           if((pyjslib_slice(str, i, (i + 2)) == "$}")) {
    664             var j = (i + 2);
    665             break;
    666           }
    667           if(!(first_run)) {
    668             if((pyjslib_slice(str, i, (i + 1)) == ",")) {
    669               i += 1;
    670             } else {
    671               throw BadSyntax(this._thisDoc, this.lines, str, i, "expected: ','");
    672             }
    673           } else {
    674             var first_run = false;
    675           }
    676           var item = new pyjslib_List([]);
    677           var j = this.item(str, i, item);
    678           if((j < 0)) {
    679             throw BadSyntax(this._thisDoc, this.lines, str, i, "expected item in set or '$}'");
    680           }
    681           mylist.push(item[0]);
    682         }
    683         res.push(this._store.newSet(mylist, this._context));
    684         return j;
    685       } else {
    686         var j = (i + 1);
    687         var oldParentContext = this._parentContext;
    688         this._parentContext = this._context;
    689         var parentAnonymousNodes = this._anonymousNodes;
    690         var grandParentVariables = this._parentVariables;
    691         this._parentVariables = this._variables;
    692         this._anonymousNodes = new pyjslib_Dict([]);
    693         this._variables = this._variables.slice();
    694         var reason2 = this._reason2;
    695         this._reason2 = becauseSubexpression;
    696         if((subj == null)) {
    697           var subj = this._store.formula();
    698         }
    699         this._context = subj;
    700         while(1) {
    701           var i = this.skipSpace(str, j);
    702           if((i < 0)) {
    703             throw BadSyntax(this._thisDoc, this.lines, str, i, "needed '}', found end.");
    704           }
    705           if((pyjslib_slice(str, i, (i + 1)) == "}")) {
    706             var j = (i + 1);
    707             break;
    708           }
    709           var j = this.directiveOrStatement(str, i);
    710           if((j < 0)) {
    711             throw BadSyntax(this._thisDoc, this.lines, str, i, "expected statement or '}'");
    712           }
    713         }
    714         this._anonymousNodes = parentAnonymousNodes;
    715         this._variables = this._parentVariables;
    716         this._parentVariables = grandParentVariables;
    717         this._context = this._parentContext;
    718         this._reason2 = reason2;
    719         this._parentContext = oldParentContext;
    720         res.push(subj.close());
    721         return j;
    722       }
    723     }
    724     if((ch == "(")) {
    725       var thing_type = this._store.list;
    726       var ch2 = pyjslib_slice(str, (i + 1), (i + 2));
    727       if((ch2 == "$")) {
    728         var thing_type = this._store.newSet;
    729         i += 1;
    730       }
    731       var j = (i + 1);
    732       var mylist = new pyjslib_List([]);
    733       while(1) {
    734         var i = this.skipSpace(str, j);
    735         if((i < 0)) {
    736           throw BadSyntax(this._thisDoc, this.lines, str, i, "needed ')', found end.");
    737         }
    738         if((pyjslib_slice(str, i, (i + 1)) == ")")) {
    739           var j = (i + 1);
    740           break;
    741         }
    742         var item = new pyjslib_List([]);
    743         var j = this.item(str, i, item);
    744         if((j < 0)) {
    745           throw BadSyntax(this._thisDoc, this.lines, str, i, "expected item in list or ')'");
    746         }
    747         mylist.push(item[0]);
    748       }
    749       res.push(thing_type(mylist, this._context));
    750       return j;
    751     }
    752     var j = this.tok("this", str, i);
    753     if((j >= 0)) {
    754       throw BadSyntax(this._thisDoc, this.lines, str, i, "Keyword 'this' was ancient N3. Now use @forSome and @forAll keywords.");
    755       res.push(this._context);
    756       return j;
    757     }
    758     var j = this.tok("true", str, i);
    759     if((j >= 0)) {
    760       res.push(true);
    761       return j;
    762     }
    763     var j = this.tok("false", str, i);
    764     if((j >= 0)) {
    765       res.push(false);
    766       return j;
    767     }
    768     if((subj == null)) {
    769       var j = this.uri_ref2(str, i, res);
    770       if((j >= 0)) {
    771         return j;
    772       }
    773     }
    774     return -1;
    775   };
    776   __SinkParser.prototype.property_list = function (str, i, subj) {
    777     /*
    778     Parse property list
    779     Leaves the terminating punctuation in the buffer
    780     */
    781 
    782     while(1) {
    783       var j = this.skipSpace(str, i);
    784       if((j < 0)) {
    785         throw BadSyntax(this._thisDoc, this.lines, str, i, "EOF found when expected verb in property list");
    786         return j;
    787       }
    788       if((pyjslib_slice(str, j, (j + 2)) == ":-")) {
    789         var i = (j + 2);
    790         var res = new pyjslib_List([]);
    791         var j = this.node(str, i, res, subj);
    792         if((j < 0)) {
    793           throw BadSyntax(this._thisDoc, this.lines, str, i, "bad {} or () or [] node after :- ");
    794         }
    795         var i = j;
    796         continue;
    797       }
    798       var i = j;
    799       var v = new pyjslib_List([]);
    800       var j = this.verb(str, i, v);
    801       if((j <= 0)) {
    802         return i;
    803       }
    804       var objs = new pyjslib_List([]);
    805       var i = this.objectList(str, j, objs);
    806       if((i < 0)) {
    807         throw BadSyntax(this._thisDoc, this.lines, str, j, "objectList expected");
    808       }
    809 
    810       var __obj = new pyjslib_Iterator(objs);
    811       try {
    812         while(true) {
    813           var obj = __obj.next();
    814 
    815 
    816           var pairFudge = v[0];
    817           var dir = pairFudge[0];
    818           var sym = pairFudge[1];
    819           if((dir == "->")) {
    820             this.makeStatement(new pyjslib_Tuple([this._context, sym, subj, obj]));
    821           } else {
    822             this.makeStatement(new pyjslib_Tuple([this._context, sym, obj, subj]));
    823           }
    824 
    825         }
    826       } catch(e) {
    827         if(e != StopIteration) {
    828           throw e;
    829         }
    830       }
    831 
    832       var j = this.skipSpace(str, i);
    833       if((j < 0)) {
    834         throw BadSyntax(this._thisDoc, this.lines, str, j, "EOF found in list of objects");
    835         return j;
    836       }
    837       if((pyjslib_slice(str, i, (i + 1)) != ";")) {
    838         return i;
    839       }
    840       var i = (i + 1);
    841     }
    842   };
    843   __SinkParser.prototype.commaSeparatedList = function (str, j, res, ofUris) {
    844     /*
    845     return value: -1 bad syntax; >1 new position in str
    846     res has things found appended
    847     
    848     Used to use a final value of the function to be called, e.g. this.bareWord
    849     but passing the function didn't work fo js converion pyjs
    850     */
    851 
    852     var i = this.skipSpace(str, j);
    853     if((i < 0)) {
    854       throw BadSyntax(this._thisDoc, this.lines, str, i, "EOF found expecting comma sep list");
    855       return i;
    856     }
    857     if((str.charAt(i) == ".")) {
    858       return j;
    859     }
    860     if(ofUris) {
    861       var i = this.uri_ref2(str, i, res);
    862     } else {
    863       var i = this.bareWord(str, i, res);
    864     }
    865     if((i < 0)) {
    866       return -1;
    867     }
    868     while(1) {
    869       var j = this.skipSpace(str, i);
    870       if((j < 0)) {
    871         return j;
    872       }
    873       var ch = pyjslib_slice(str, j, (j + 1));
    874       if((ch != ",")) {
    875         if((ch != ".")) {
    876           return -1;
    877         }
    878         return j;
    879       }
    880       if(ofUris) {
    881         var i = this.uri_ref2(str, (j + 1), res);
    882       } else {
    883         var i = this.bareWord(str, (j + 1), res);
    884       }
    885       if((i < 0)) {
    886         throw BadSyntax(this._thisDoc, this.lines, str, i, "bad list content");
    887         return i;
    888       }
    889     }
    890   };
    891   __SinkParser.prototype.objectList = function (str, i, res) {
    892     var i = this.object(str, i, res);
    893     if((i < 0)) {
    894       return -1;
    895     }
    896     while(1) {
    897       var j = this.skipSpace(str, i);
    898       if((j < 0)) {
    899         throw BadSyntax(this._thisDoc, this.lines, str, j, "EOF found after object");
    900         return j;
    901       }
    902       if((pyjslib_slice(str, j, (j + 1)) != ",")) {
    903         return j;
    904       }
    905       var i = this.object(str, (j + 1), res);
    906       if((i < 0)) {
    907         return i;
    908       }
    909     }
    910   };
    911   __SinkParser.prototype.checkDot = function (str, i) {
    912     var j = this.skipSpace(str, i);
    913     if((j < 0)) {
    914       return j;
    915     }
    916     if((pyjslib_slice(str, j, (j + 1)) == ".")) {
    917       return(j + 1);
    918     }
    919     if((pyjslib_slice(str, j, (j + 1)) == "}")) {
    920       return j;
    921     }
    922     if((pyjslib_slice(str, j, (j + 1)) == "]")) {
    923       return j;
    924     }
    925     throw BadSyntax(this._thisDoc, this.lines, str, j, "expected '.' or '}' or ']' at end of statement");
    926     return i;
    927   };
    928   __SinkParser.prototype.uri_ref2 = function (str, i, res) {
    929     /*
    930     Generate uri from n3 representation.
    931     
    932     Note that the RDF convention of directly concatenating
    933     NS and local name is now used though I prefer inserting a '#'
    934     to make the namesapces look more like what XML folks expect.
    935     */
    936 
    937     var qn = new pyjslib_List([]);
    938     var j = this.qname(str, i, qn);
    939     if((j >= 0)) {
    940       var pairFudge = qn[0];
    941       var pfx = pairFudge[0];
    942       var ln = pairFudge[1];
    943       if((pfx == null)) {
    944         assertFudge(0, "not used?");
    945         var ns = (this._baseURI + ADDED_HASH);
    946       } else {
    947         var ns = this._bindings[pfx];
    948         if(!(ns)) {
    949           if((pfx == "_")) {
    950             res.push(this.anonymousNode(ln));
    951             return j;
    952           }
    953           throw BadSyntax(this._thisDoc, this.lines, str, i, (("Prefix " + pfx) + " not bound."));
    954         }
    955       }
    956       var symb = this._store.sym((ns + ln));
    957       if(($rdf.Util.ArrayIndexOf(this._variables, symb) >= 0)) {
    958         res.push(this._variables[symb]);
    959       } else {
    960         res.push(symb);
    961       }
    962       return j;
    963     }
    964     var i = this.skipSpace(str, i);
    965     if((i < 0)) {
    966       return -1;
    967     }
    968     if((str.charAt(i) == "?")) {
    969       var v = new pyjslib_List([]);
    970       var j = this.variable(str, i, v);
    971       if((j > 0)) {
    972         res.push(v[0]);
    973         return j;
    974       }
    975       return -1;
    976     } else if((str.charAt(i) == "<")) {
    977       var i = (i + 1);
    978       var st = i;
    979       while((i < pyjslib_len(str))) {
    980         if((str.charAt(i) == ">")) {
    981           var uref = pyjslib_slice(str, st, i);
    982           if(this._baseURI) {
    983             var uref = uripath_join(this._baseURI, uref);
    984           } else {
    985             assertFudge((uref.indexOf(":") >= 0), "With no base URI, cannot deal with relative URIs");
    986           }
    987           if((pyjslib_slice(str, (i - 1), i) == "#") && !((pyjslib_slice(uref, -1, null) == "#"))) {
    988             var uref = (uref + "#");
    989           }
    990           var symb = this._store.sym(uref);
    991           if(($rdf.Util.ArrayIndexOf(this._variables, symb) >= 0)) {
    992             res.push(this._variables[symb]);
    993           } else {
    994             res.push(symb);
    995           }
    996           return(i + 1);
    997         }
    998         var i = (i + 1);
    999       }
   1000       throw BadSyntax(this._thisDoc, this.lines, str, j, "unterminated URI reference");
   1001     } else if(this.keywordsSet) {
   1002       var v = new pyjslib_List([]);
   1003       var j = this.bareWord(str, i, v);
   1004       if((j < 0)) {
   1005         return -1;
   1006       }
   1007       if(($rdf.Util.ArrayIndexOf(this.keywords, v[0]) >= 0)) {
   1008         throw BadSyntax(this._thisDoc, this.lines, str, i, (("Keyword \"" + v[0]) + "\" not allowed here."));
   1009       }
   1010       res.push(this._store.sym((this._bindings[""] + v[0])));
   1011       return j;
   1012     } else {
   1013       return -1;
   1014     }
   1015   };
   1016   __SinkParser.prototype.skipSpace = function (str, i) {
   1017     /*
   1018     Skip white space, newlines and comments.
   1019     return -1 if EOF, else position of first non-ws character*/
   1020     var tmp = str;
   1021     var whitespace = ' \n\r\t\f\x0b\xa0\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u2028\u2029\u3000';
   1022     for(var j = (i ? i : 0); j < str.length; j++) {
   1023       if(whitespace.indexOf(str.charAt(j)) === -1) {
   1024         if(str.charAt(j) === '#') {
   1025           str = str.slice(i).replace(/^[^\n]*\n/, "");
   1026           i = 0;
   1027           j = -1;
   1028         } else {
   1029           break;
   1030         }
   1031       }
   1032     }
   1033     var val = (tmp.length - str.length) + j;
   1034     if(val === tmp.length) {
   1035       return -1;
   1036     }
   1037     return val;
   1038   };
   1039   __SinkParser.prototype.variable = function (str, i, res) {
   1040     /*
   1041     ?abc -> variable(:abc)
   1042     */
   1043 
   1044     var j = this.skipSpace(str, i);
   1045     if((j < 0)) {
   1046       return -1;
   1047     }
   1048     if((pyjslib_slice(str, j, (j + 1)) != "?")) {
   1049       return -1;
   1050     }
   1051     var j = (j + 1);
   1052     var i = j;
   1053     if(("0123456789-".indexOf(str.charAt(j)) >= 0)) {
   1054       throw BadSyntax(this._thisDoc, this.lines, str, j, (("Varible name can't start with '" + str.charAt(j)) + "s'"));
   1055       return -1;
   1056     }
   1057     while((i < pyjslib_len(str)) && (_notNameChars.indexOf(str.charAt(i)) < 0)) {
   1058       var i = (i + 1);
   1059     }
   1060     if((this._parentContext == null)) {
   1061       throw BadSyntax(this._thisDoc, this.lines, str, j, ("Can't use ?xxx syntax for variable in outermost level: " + pyjslib_slice(str, (j - 1), i)));
   1062     }
   1063     res.push(this._store.variable(pyjslib_slice(str, j, i)));
   1064     return i;
   1065   };
   1066   __SinkParser.prototype.bareWord = function (str, i, res) {
   1067     /*
   1068     abc -> :abc
   1069     */
   1070 
   1071     var j = this.skipSpace(str, i);
   1072     if((j < 0)) {
   1073       return -1;
   1074     }
   1075     var ch = str.charAt(j);
   1076     if(("0123456789-".indexOf(ch) >= 0)) {
   1077       return -1;
   1078     }
   1079     if((_notNameChars.indexOf(ch) >= 0)) {
   1080       return -1;
   1081     }
   1082     var i = j;
   1083     while((i < pyjslib_len(str)) && (_notNameChars.indexOf(str.charAt(i)) < 0)) {
   1084       var i = (i + 1);
   1085     }
   1086     res.push(pyjslib_slice(str, j, i));
   1087     return i;
   1088   };
   1089   __SinkParser.prototype.qname = function (str, i, res) {
   1090     /*
   1091     
   1092     xyz:def -> ('xyz', 'def')
   1093     If not in keywords and keywordsSet: def -> ('', 'def')
   1094     :def -> ('', 'def')    
   1095     */
   1096 
   1097     var i = this.skipSpace(str, i);
   1098     if((i < 0)) {
   1099       return -1;
   1100     }
   1101     var c = str.charAt(i);
   1102     if(("0123456789-+".indexOf(c) >= 0)) {
   1103       return -1;
   1104     }
   1105     if((_notNameChars.indexOf(c) < 0)) {
   1106       var ln = c;
   1107       var i = (i + 1);
   1108       while((i < pyjslib_len(str))) {
   1109         var c = str.charAt(i);
   1110         if((_notNameChars.indexOf(c) < 0)) {
   1111           var ln = (ln + c);
   1112           var i = (i + 1);
   1113         } else {
   1114           break;
   1115         }
   1116       }
   1117     } else {
   1118       var ln = "";
   1119     }
   1120     if((i < pyjslib_len(str)) && (str.charAt(i) == ":")) {
   1121       var pfx = ln;
   1122       var i = (i + 1);
   1123       var ln = "";
   1124       while((i < pyjslib_len(str))) {
   1125         var c = str.charAt(i);
   1126         if((_notNameChars.indexOf(c) < 0)) {
   1127           var ln = (ln + c);
   1128           var i = (i + 1);
   1129         } else {
   1130           break;
   1131         }
   1132       }
   1133       res.push(new pyjslib_Tuple([pfx, ln]));
   1134       return i;
   1135     } else {
   1136       if(ln && this.keywordsSet && ($rdf.Util.ArrayIndexOf(this.keywords, ln) < 0)) {
   1137         res.push(new pyjslib_Tuple(["", ln]));
   1138         return i;
   1139       }
   1140       return -1;
   1141     }
   1142   };
   1143   __SinkParser.prototype.object = function (str, i, res) {
   1144     var j = this.subject(str, i, res);
   1145     if((j >= 0)) {
   1146       return j;
   1147     } else {
   1148       var j = this.skipSpace(str, i);
   1149       if((j < 0)) {
   1150         return -1;
   1151       } else {
   1152         var i = j;
   1153       }
   1154       if((str.charAt(i) == "\"")) {
   1155         if((pyjslib_slice(str, i, (i + 3)) == "\"\"\"")) {
   1156           var delim = "\"\"\"";
   1157         } else {
   1158           var delim = "\"";
   1159         }
   1160         var i = (i + pyjslib_len(delim));
   1161         var pairFudge = this.strconst(str, i, delim);
   1162         var j = pairFudge[0];
   1163         var s = pairFudge[1];
   1164         res.push(this._store.literal(s));
   1165         diag_progress("New string const ", s, j);
   1166         return j;
   1167       } else {
   1168         return -1;
   1169       }
   1170     }
   1171   };
   1172   __SinkParser.prototype.nodeOrLiteral = function (str, i, res) {
   1173     var j = this.node(str, i, res);
   1174     if((j >= 0)) {
   1175       return j;
   1176     } else {
   1177       var j = this.skipSpace(str, i);
   1178       if((j < 0)) {
   1179         return -1;
   1180       } else {
   1181         var i = j;
   1182       }
   1183       var ch = str.charAt(i);
   1184       if(("-+0987654321".indexOf(ch) >= 0)) {
   1185         number_syntax.lastIndex = 0;
   1186         var m = number_syntax.exec(str.slice(i));
   1187         if((m == null)) {
   1188           throw BadSyntax(this._thisDoc, this.lines, str, i, "Bad number syntax");
   1189         }
   1190         var j = (i + number_syntax.lastIndex);
   1191         var val = pyjslib_slice(str, i, j);
   1192         if((val.indexOf("e") >= 0)) {
   1193           res.push(this._store.literal(parseFloat(val), undefined, this._store.sym(FLOAT_DATATYPE)));
   1194         } else if((pyjslib_slice(str, i, j).indexOf(".") >= 0)) {
   1195           res.push(this._store.literal(parseFloat(val), undefined, this._store.sym(DECIMAL_DATATYPE)));
   1196         } else {
   1197           res.push(this._store.literal(parseInt(val), undefined, this._store.sym(INTEGER_DATATYPE)));
   1198         }
   1199         return j;
   1200       }
   1201       if((str.charAt(i) == "\"")) {
   1202         if((pyjslib_slice(str, i, (i + 3)) == "\"\"\"")) {
   1203           var delim = "\"\"\"";
   1204         } else {
   1205           var delim = "\"";
   1206         }
   1207         var i = (i + pyjslib_len(delim));
   1208         var dt = null;
   1209         var pairFudge = this.strconst(str, i, delim);
   1210         var j = pairFudge[0];
   1211         var s = pairFudge[1];
   1212         var lang = null;
   1213         if((pyjslib_slice(str, j, (j + 1)) == "@")) {
   1214           langcode.lastIndex = 0;
   1215 
   1216           var m = langcode.exec(str.slice((j + 1)));
   1217           if((m == null)) {
   1218             throw BadSyntax(this._thisDoc, startline, str, i, "Bad language code syntax on string literal, after @");
   1219           }
   1220           var i = ((langcode.lastIndex + j) + 1);
   1221 
   1222           var lang = pyjslib_slice(str, (j + 1), i);
   1223           var j = i;
   1224         }
   1225         if((pyjslib_slice(str, j, (j + 2)) == "^^")) {
   1226           var res2 = new pyjslib_List([]);
   1227           var j = this.uri_ref2(str, (j + 2), res2);
   1228           var dt = res2[0];
   1229         }
   1230         res.push(this._store.literal(s, lang, dt));
   1231         return j;
   1232       } else {
   1233         return -1;
   1234       }
   1235     }
   1236   };
   1237   __SinkParser.prototype.strconst = function (str, i, delim) {
   1238     /*
   1239     parse an N3 string constant delimited by delim.
   1240     return index, val
   1241     */
   1242 
   1243     var j = i;
   1244     var ustr = "";
   1245     var startline = this.lines;
   1246     while((j < pyjslib_len(str))) {
   1247       var i = (j + pyjslib_len(delim));
   1248       if((pyjslib_slice(str, j, i) == delim)) {
   1249         return new pyjslib_Tuple([i, ustr]);
   1250       }
   1251       if((str.charAt(j) == "\"")) {
   1252         var ustr = (ustr + "\"");
   1253         var j = (j + 1);
   1254         continue;
   1255       }
   1256       interesting.lastIndex = 0;
   1257       var m = interesting.exec(str.slice(j));
   1258       if(!(m)) {
   1259         throw BadSyntax(this._thisDoc, startline, str, j, ((("Closing quote missing in string at ^ in " + pyjslib_slice(str, (j - 20), j)) + "^") + pyjslib_slice(str, j, (j + 20))));
   1260       }
   1261       var i = ((j + interesting.lastIndex) - 1);
   1262       var ustr = (ustr + pyjslib_slice(str, j, i));
   1263       var ch = str.charAt(i);
   1264       if((ch == "\"")) {
   1265         var j = i;
   1266         continue;
   1267       } else if((ch == "\r")) {
   1268         var j = (i + 1);
   1269         continue;
   1270       } else if((ch == "\n")) {
   1271         if((delim == "\"")) {
   1272           throw BadSyntax(this._thisDoc, startline, str, i, "newline found in string literal");
   1273         }
   1274         this.lines = (this.lines + 1);
   1275         var ustr = (ustr + ch);
   1276         var j = (i + 1);
   1277         this.previousLine = this.startOfLine;
   1278         this.startOfLine = j;
   1279       } else if((ch == "\\")) {
   1280         var j = (i + 1);
   1281         var ch = pyjslib_slice(str, j, (j + 1));
   1282         if(!(ch)) {
   1283           throw BadSyntax(this._thisDoc, startline, str, i, "unterminated string literal (2)");
   1284         }
   1285         var k = string_find("abfrtvn\\\"", ch);
   1286         if((k >= 0)) {
   1287           var uch = "\a\b\f\r\t\v\n\\\"".charAt(k);
   1288           var ustr = (ustr + uch);
   1289           var j = (j + 1);
   1290         } else if((ch == "u")) {
   1291           var pairFudge = this.uEscape(str, (j + 1), startline);
   1292           var j = pairFudge[0];
   1293           var ch = pairFudge[1];
   1294           var ustr = (ustr + ch);
   1295         } else if((ch == "U")) {
   1296           var pairFudge = this.UEscape(str, (j + 1), startline);
   1297           var j = pairFudge[0];
   1298           var ch = pairFudge[1];
   1299           var ustr = (ustr + ch);
   1300         } else {
   1301           throw BadSyntax(this._thisDoc, this.lines, str, i, "bad escape");
   1302         }
   1303       }
   1304     }
   1305     throw BadSyntax(this._thisDoc, this.lines, str, i, "unterminated string literal");
   1306   };
   1307   __SinkParser.prototype.uEscape = function (str, i, startline) {
   1308     var j = i;
   1309     var count = 0;
   1310     var value = 0;
   1311     while((count < 4)) {
   1312       var chFudge = pyjslib_slice(str, j, (j + 1));
   1313       var ch = chFudge.toLowerCase();
   1314       var j = (j + 1);
   1315       if((ch == "")) {
   1316         throw BadSyntax(this._thisDoc, startline, str, i, "unterminated string literal(3)");
   1317       }
   1318       var k = string_find("0123456789abcdef", ch);
   1319       if((k < 0)) {
   1320         throw BadSyntax(this._thisDoc, startline, str, i, "bad string literal hex escape");
   1321       }
   1322       var value = ((value * 16) + k);
   1323       var count = (count + 1);
   1324     }
   1325     var uch = String.fromCharCode(value);
   1326     return new pyjslib_Tuple([j, uch]);
   1327   };
   1328   __SinkParser.prototype.UEscape = function (str, i, startline) {
   1329     var j = i;
   1330     var count = 0;
   1331     var value = "\\U";
   1332     while((count < 8)) {
   1333       var chFudge = pyjslib_slice(str, j, (j + 1));
   1334       var ch = chFudge.toLowerCase();
   1335       var j = (j + 1);
   1336       if((ch == "")) {
   1337         throw BadSyntax(this._thisDoc, startline, str, i, "unterminated string literal(3)");
   1338       }
   1339       var k = string_find("0123456789abcdef", ch);
   1340       if((k < 0)) {
   1341         throw BadSyntax(this._thisDoc, startline, str, i, "bad string literal hex escape");
   1342       }
   1343       var value = (value + ch);
   1344       var count = (count + 1);
   1345     }
   1346     var uch = stringFromCharCode((("0x" + pyjslib_slice(value, 2, 10)) - 0));
   1347     return new pyjslib_Tuple([j, uch]);
   1348   };
   1349 
   1350   function BadSyntax(uri, lines, str, i, why) {
   1351     return(((((((("Line " + (lines + 1)) + " of <") + uri) + ">: Bad syntax: ") + why) + "\nat: \"") + pyjslib_slice(str, i, (i + 30))) + "\"");
   1352   }
   1353 
   1354 
   1355   function stripCR(str) {
   1356     var res = "";
   1357 
   1358     var __ch = new pyjslib_Iterator(str);
   1359     try {
   1360       while(true) {
   1361         var ch = __ch.next();
   1362 
   1363 
   1364         if((ch != "\r")) {
   1365           var res = (res + ch);
   1366         }
   1367 
   1368       }
   1369     } catch(e) {
   1370       if(e != StopIteration) {
   1371         throw e;
   1372       }
   1373     }
   1374 
   1375     return res;
   1376   }
   1377 
   1378 
   1379   function dummyWrite(x) {
   1380   }
   1381 
   1382   return SinkParser;
   1383 
   1384 }();