@matdata/sparql-formatter 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,47 @@
1
+ /**
2
+ * SPARQL 1.2 lexer.
3
+ *
4
+ * Produces the significant tokens of a query together with the comments
5
+ * that surround them. Comments are not dropped: every comment is attached to
6
+ * a token, either as a *trailing* comment (it sits on the same line as the
7
+ * token that precedes it) or as a *leading* comment (it sits on a line of its
8
+ * own before the next token). The printer re-emits them relative to those
9
+ * tokens, which is what keeps comments in place after formatting.
10
+ *
11
+ * Terminals follow https://www.w3.org/TR/sparql12-query/#sparqlGrammar
12
+ */
13
+ export type TokenType = "IRIREF" | "PNAME_NS" | "PNAME_LN" | "BLANK_NODE_LABEL" | "VAR" | "LANG_DIR" | "INTEGER" | "DECIMAL" | "DOUBLE" | "STRING" | "NAME" | "PUNCT" | "EOF";
14
+ export interface Comment {
15
+ /** The comment text including the leading `#`, without the line break. */
16
+ text: string;
17
+ offset: number;
18
+ line: number;
19
+ column: number;
20
+ /** Number of blank lines between the previous token/comment and this comment. */
21
+ blankLinesBefore: number;
22
+ }
23
+ export interface Token {
24
+ type: TokenType;
25
+ /** The exact source text of the token. */
26
+ value: string;
27
+ offset: number;
28
+ end: number;
29
+ line: number;
30
+ column: number;
31
+ /** Index of this token in the token list. */
32
+ index: number;
33
+ /** Comments on their own line(s) before this token. */
34
+ leading: Comment[];
35
+ /** Comment on the same line after this token. */
36
+ trailing: Comment | null;
37
+ /** Number of blank lines between the previous token (or leading comment) and this token. */
38
+ blankLinesBefore: number;
39
+ /** Whether whitespace or a comment separates this token from the previous one. */
40
+ spaceBefore: boolean;
41
+ }
42
+ /**
43
+ * Split a query into tokens. Comments are attached to tokens (see module docs).
44
+ * The last token is always an `EOF` token that carries the comments at the end
45
+ * of the query.
46
+ */
47
+ export declare function tokenize(input: string): Token[];
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Recursive-descent parser for SPARQL 1.2 queries and updates.
3
+ *
4
+ * Grammar: https://www.w3.org/TR/sparql12-query/#sparqlGrammar
5
+ *
6
+ * The parser checks the syntax of the query (it rejects anything the grammar
7
+ * rejects), but it does not check the additional constraints of the spec that
8
+ * a formatter doesn't need, such as variable scoping or blank node label reuse.
9
+ */
10
+ import type * as A from "./ast.js";
11
+ /** Parse a SPARQL 1.2 query or update into a concrete syntax tree. */
12
+ export declare function parse(input: string): A.Ast;
@@ -0,0 +1,89 @@
1
+ /**
2
+ * Pretty-printer: turns the syntax tree back into SPARQL text.
3
+ */
4
+ import type * as A from "./ast.js";
5
+ export type Case = "upper" | "lower" | "preserve";
6
+ export interface FormatOptions {
7
+ /** Indentation: a number of spaces or the indent string itself (e.g. `"\t"`). Default: 2 */
8
+ indent?: number | string;
9
+ /** Case of keywords such as SELECT, WHERE, OPTIONAL. Default: `"upper"` */
10
+ keywordCase?: Case;
11
+ /** Case of built-in function names such as `regex`, `STR`, `COUNT`. Default: `"preserve"` */
12
+ functionCase?: Case;
13
+ /** Align the predicates of a subject that has several (`;`) under the first predicate. Default: true */
14
+ alignPredicates?: boolean;
15
+ /** Keep (at most one) blank line where the query has blank lines between statements. Default: true */
16
+ preserveBlankLines?: boolean;
17
+ /** Put small group graph patterns on one line: `OPTIONAL { ?s :p ?o }`. Default: false */
18
+ compact?: boolean;
19
+ /** Maximum line width used by `compact` and to wrap long `VALUES` lists. Default: 100 */
20
+ lineWidth?: number;
21
+ /** Always write `WHERE` before the group graph pattern of SELECT, CONSTRUCT and DESCRIBE. Default: true */
22
+ insertWhere?: boolean;
23
+ }
24
+ interface ResolvedOptions {
25
+ indent: string;
26
+ keywordCase: Case;
27
+ functionCase: Case;
28
+ alignPredicates: boolean;
29
+ preserveBlankLines: boolean;
30
+ compact: boolean;
31
+ lineWidth: number;
32
+ insertWhere: boolean;
33
+ }
34
+ export declare function resolveOptions(options?: FormatOptions): ResolvedOptions;
35
+ export declare class Printer {
36
+ private w;
37
+ private options;
38
+ constructor(options: ResolvedOptions);
39
+ private newWriter;
40
+ print(ast: A.Ast): {
41
+ text: string;
42
+ comments: number;
43
+ };
44
+ /**
45
+ * Render `fn` on a scratch writer and return the result if it fits on one
46
+ * line (no comments, no line breaks) within `width` characters.
47
+ */
48
+ private measure;
49
+ private remainingWidth;
50
+ private kw;
51
+ /** A keyword that was not in the source (e.g. an inserted WHERE). */
52
+ private synthKw;
53
+ private tok;
54
+ private sp;
55
+ private nl;
56
+ private prologue;
57
+ private query;
58
+ private selectClause;
59
+ private projection;
60
+ private datasets;
61
+ private whereClause;
62
+ private solutionModifier;
63
+ private condition;
64
+ private update;
65
+ private words;
66
+ private updateOperation;
67
+ /**
68
+ * Print `open`, the items on their own lines one level deeper, and `close`.
69
+ * Comments before `close` stay inside the block.
70
+ */
71
+ private block;
72
+ /** Try to print a block on a single line (compact mode). */
73
+ private inlineBlock;
74
+ group(g: A.GroupGraphPattern): void;
75
+ private triplesTemplate;
76
+ /** An item of a group: triples end with ` .`, other patterns have no dot. */
77
+ private patternItem;
78
+ private pattern;
79
+ /** Honour a blank line before the first token of a statement. */
80
+ private markBlank;
81
+ private values;
82
+ private valuesOneVar;
83
+ private triples;
84
+ private propertyList;
85
+ private term;
86
+ private node;
87
+ private expr;
88
+ }
89
+ export {};
@@ -0,0 +1,8 @@
1
+ /*! @matdata/sparql-formatter v1.0.0 | MIT | https://github.com/Matdata-eu/sparql-formatter#readme */
2
+ "use strict";(()=>{var V=Object.defineProperty;var W=(o,t)=>{for(var e in t)V(o,e,{get:t[e],enumerable:!0})};var D={};W(D,{SparqlSyntaxError:()=>k,default:()=>ft,format:()=>L,formatAst:()=>K,isValid:()=>ut,parse:()=>v,spfmt:()=>O,tokenize:()=>T});var k=class extends Error{constructor(t,e,s,i,r=[]){super(`${t} (line ${s}, column ${i})`),this.name="SparqlSyntaxError",this.offset=e,this.line=s,this.column=i,this.expected=r}};var B="A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\u{10000}-\\u{EFFFF}",x=B+"_",E=x+"\\-0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040",S="%[0-9A-Fa-f]{2}|\\\\[_~.\\-!$&'()*+,;=/?#@%]",$=`[${B}](?:[${E}.]*[${E}])?`,j=`(?:[${x}:0-9]|${S})(?:(?:[${E}.:]|${S})*(?:[${E}:]|${S}))?`,H=new RegExp(`(?:${$})?:(?:${j})?`,"uy"),Q=new RegExp(`[?$][${x}0-9][${x}0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*`,"uy"),q=new RegExp(`_:[${x}0-9](?:[${E}.]*[${E}])?`,"uy"),Y=/<(?:[^<>"{}|^`\\\u0000- ]|\\u[0-9A-Fa-f]{4}|\\U[0-9A-Fa-f]{8})*>/y,z=/@[a-zA-Z]+(?:-[a-zA-Z0-9]+)*(?:--[a-zA-Z]+)?/y,X=/(?:[0-9]+(?:\.[0-9]*)?|\.[0-9]+)[eE][+-]?[0-9]+/y,Z=/[0-9]*\.[0-9]+/y,J=/[0-9]+/y,tt=/[A-Za-z_][A-Za-z0-9_]*/y,R=String.raw`\\[tbnrf\\"']|\\u[0-9A-Fa-f]{4}|\\U[0-9A-Fa-f]{8}`,et=new RegExp(String.raw`'''(?:(?:'|'')?(?:[^'\\]|${R}))*'''`,"y"),st=new RegExp(String.raw`"""(?:(?:"|"")?(?:[^"\\]|${R}))*"""`,"y"),it=new RegExp(String.raw`'(?:[^'\\\n\r]|${R})*'`,"y"),rt=new RegExp(String.raw`"(?:[^"\\\n\r]|${R})*"`,"y"),nt=/\\(?:u|U0000)[dD][89a-fA-F][0-9a-fA-F]{2}/,ot=["<<(",")>>","<<",">>","{|","|}","^^","&&","||","!=","<=",">=","{","}","(",")","[","]",".",",",";","*","/","|","^","?","+","-","!","=","<",">","~"];function m(o,t,e){o.lastIndex=e;let s=o.exec(t);return s?s[0]:null}function T(o){let t=[],e=0,s=1,i=0,r=[],n=0,a=!1,h=null,p=-1,l=(c,w)=>{for(let A=c;A<w;A++){let f=o.charCodeAt(A);(f===10||f===13&&o.charCodeAt(A+1)!==10)&&(s++,i=A+1)}},d=c=>{throw new k(c,e,s,e-i+1)};for(;e<o.length;){let c=o[e];if(c===" "||c===" "||c==="\r"||c===`
3
+ `){(c===`
4
+ `||c==="\r"&&o[e+1]!==`
5
+ `)&&(n++,s++,i=e+1),a=!0,e++;continue}if(c==="#"){let y=e;for(;y<o.length&&o[y]!==`
6
+ `&&o[y]!=="\r";)y++;let g={text:o.slice(e,y).replace(/\s+$/,""),offset:e,line:s,column:e-i+1,blankLinesBefore:Math.max(0,n-1)};h&&p===s&&r.length===0&&!h.trailing?h.trailing=g:r.push(g),n=0,a=!0,e=y;continue}let w=s,A=e-i+1,f,u=null;if(c==="<")o.startsWith("<<(",e)?(f="PUNCT",u="<<("):o.startsWith("<<",e)?(f="PUNCT",u="<<"):(u=m(Y,o,e))?f="IRIREF":(f="PUNCT",u=o.startsWith("<=",e)?"<=":"<");else if(c==="?"||c==="$")if(u=m(Q,o,e),u)f="VAR";else if(c==="?")f="PUNCT",u="?";else return d("Invalid variable name");else if(c==='"'||c==="'"){if(u=c==='"'?m(st,o,e)??m(rt,o,e):m(et,o,e)??m(it,o,e),!u)return d("Unterminated or invalid string literal");f="STRING"}else if(c==="@"){if(u=m(z,o,e),!u)return d("Invalid language tag");f="LANG_DIR"}else if(c==="_"&&o[e+1]===":"){if(u=m(q,o,e),!u)return d("Invalid blank node label");f="BLANK_NODE_LABEL"}else if(c>="0"&&c<="9"||c==="."&&/[0-9]/.test(o[e+1]??""))(u=m(X,o,e))?f="DOUBLE":(u=m(Z,o,e))?f="DECIMAL":(u=m(J,o,e),f="INTEGER");else{let y=m(H,o,e);if(y)u=y,f=y.endsWith(":")&&y.indexOf(":")===y.length-1?"PNAME_NS":"PNAME_LN";else if(u=m(tt,o,e))f="NAME";else{if(u=ot.find(g=>o.startsWith(g,e))??null,!u)return d(`Unexpected character '${String.fromCodePoint(o.codePointAt(e))}'`);f="PUNCT"}}if((f==="STRING"||f==="IRIREF")&&nt.test(u))return d("Escape sequences for surrogate code points (U+D800 to U+DFFF) are not allowed");let P={type:f,value:u,offset:e,end:e+u.length,line:w,column:A,index:t.length,leading:r,trailing:null,blankLinesBefore:Math.max(0,n-1),spaceBefore:a};t.push(P),l(e,P.end),e=P.end,h=P,p=s,r=[],n=0,a=!1}return t.push({type:"EOF",value:"",offset:o.length,end:o.length,line:s,column:o.length-i+1,index:t.length,leading:r,trailing:null,blankLinesBefore:Math.max(0,n-1),spaceBefore:a}),t}var M=new Set(["COUNT","SUM","MIN","MAX","AVG","SAMPLE","GROUP_CONCAT","STR","LANG","LANGMATCHES","LANGDIR","DATATYPE","BOUND","IRI","URI","BNODE","RAND","ABS","CEIL","FLOOR","ROUND","CONCAT","SUBSTR","STRLEN","REPLACE","UCASE","LCASE","ENCODE_FOR_URI","CONTAINS","STRSTARTS","STRENDS","STRBEFORE","STRAFTER","YEAR","MONTH","DAY","HOURS","MINUTES","SECONDS","TIMEZONE","TZ","NOW","UUID","STRUUID","MD5","SHA1","SHA256","SHA384","SHA512","COALESCE","IF","STRLANG","STRLANGDIR","STRDT","SAMETERM","ISIRI","ISURI","ISBLANK","ISLITERAL","ISNUMERIC","HASLANG","HASLANGDIR","REGEX","ISTRIPLE","TRIPLE","SUBJECT","PREDICATE","OBJECT"]),at=new Set(["COUNT","SUM","MIN","MAX","AVG","SAMPLE","GROUP_CONCAT"]),ht=new Set(["RAND","NOW","UUID","STRUUID"]),U={LANGMATCHES:[2,2],CONTAINS:[2,2],STRSTARTS:[2,2],STRENDS:[2,2],STRBEFORE:[2,2],STRAFTER:[2,2],STRLANG:[2,2],STRDT:[2,2],SAMETERM:[2,2],IF:[3,3],STRLANGDIR:[3,3],TRIPLE:[3,3],REGEX:[2,3],SUBSTR:[2,3],REPLACE:[3,4],CONCAT:[0,1/0],COALESCE:[0,1/0],BNODE:[0,1]},pt=new Set(["SELECT","CONSTRUCT","DESCRIBE","ASK"]),lt=new Set(["LOAD","CLEAR","DROP","CREATE","ADD","MOVE","COPY","INSERT","DELETE","WITH"]);function v(o){return new b(T(o)).parseUnit()}var b=class{constructor(t){this.pos=0;this.tokens=t}peek(t=0){return this.tokens[Math.min(this.pos+t,this.tokens.length-1)]}next(){let t=this.tokens[this.pos];return t.type!=="EOF"&&this.pos++,t}isKw(t,...e){return t.type==="NAME"&&e.includes(t.value.toUpperCase())}isPunct(t,...e){return t.type==="PUNCT"&&e.includes(t.value)}fail(t,e){let s=t.type==="EOF"?"end of input":`'${t.value}'`;throw new k(`Expected ${e} but found ${s}`,t.offset,t.line,t.column,[e])}expectKw(t){let e=this.peek();return this.isKw(e,t)||this.fail(e,t),this.next()}expectPunct(t){let e=this.peek();return this.isPunct(e,t)||this.fail(e,`'${t}'`),this.next()}optKw(...t){return this.isKw(this.peek(),...t)?this.next():null}optPunct(t){return this.isPunct(this.peek(),t)?this.next():null}term(...t){return{type:"Term",tokens:t}}isEmptyPair(t,e){return this.isPunct(this.peek(),t)&&this.isPunct(this.peek(1),e)}parseUnit(){let t=this.pos,e=this.parsePrologue();if(pt.has(this.peek().type==="NAME"?this.peek().value.toUpperCase():"")){let s=this.parseQueryForm(),i=this.isKw(this.peek(),"VALUES")?this.parseValues():null,r=this.peek();return r.type!=="EOF"&&this.fail(r,"end of query"),{type:"Query",prologue:e,form:s,values:i,eof:r}}return this.pos=t,this.parseUpdate()}parsePrologue(){let t=[];for(;;){let e=this.peek();if(this.isKw(e,"BASE")){let s=this.next(),i=this.next();i.type!=="IRIREF"&&this.fail(i,"an IRI"),t.push({type:"Base",keyword:s,prefix:null,value:i})}else if(this.isKw(e,"PREFIX")){let s=this.next(),i=this.next();i.type!=="PNAME_NS"&&this.fail(i,"a prefix name such as 'ex:'");let r=this.next();r.type!=="IRIREF"&&this.fail(r,"an IRI"),t.push({type:"Prefix",keyword:s,prefix:i,value:r})}else if(this.isKw(e,"VERSION")){let s=this.next(),i=this.next();(i.type!=="STRING"||i.value.startsWith("'''")||i.value.startsWith('"""'))&&this.fail(i,"a version string"),t.push({type:"Version",keyword:s,prefix:null,value:i})}else return t}}parseQueryForm(){switch(this.peek().value.toUpperCase()){case"SELECT":return this.parseSelect();case"CONSTRUCT":return this.parseConstruct();case"DESCRIBE":return this.parseDescribe();default:return this.parseAsk()}}parseSelectClause(){let t=this.expectKw("SELECT"),e=this.optKw("DISTINCT","REDUCED"),s=this.optPunct("*"),i=[];if(!s){for(;;){let r=this.peek();if(r.type==="VAR")i.push(this.term(this.next()));else if(this.isPunct(r,"(")){let n=this.next(),a=this.parseExpression(),h=this.expectKw("AS"),p=this.parseVar(),l=this.expectPunct(")");i.push({type:"Projection",open:n,expression:a,as:h,variable:p,close:l})}else break}i.length===0&&this.fail(this.peek(),"'*', a variable or '(' after SELECT")}return{type:"SelectClause",keyword:t,modifier:e,star:s,items:i}}parseSelect(){let t=this.parseSelectClause(),e=this.parseDatasets(),s=this.parseWhereClause(!0),i=this.parseSolutionModifier();return{type:"Select",select:t,datasets:e,where:s,modifiers:i}}parseSubSelect(){let t=this.parseSelectClause(),e=this.parseWhereClause(!0),s=this.parseSolutionModifier(),i=this.isKw(this.peek(),"VALUES")?this.parseValues():null;return{type:"SubSelect",select:t,datasets:[],where:e,modifiers:s,values:i}}parseConstruct(){let t=this.expectKw("CONSTRUCT");if(this.isPunct(this.peek(),"{")){let n=this.parseTriplesTemplate(!1),a=this.parseDatasets(),h=this.parseWhereClause(!0),p=this.parseSolutionModifier();return{type:"Construct",keyword:t,template:n,datasets:a,where:h,shortForm:null,modifiers:p}}let e=this.parseDatasets(),s=this.expectKw("WHERE"),i=this.parseTriplesTemplate(!1),r=this.parseSolutionModifier();return{type:"Construct",keyword:t,template:null,datasets:e,where:null,shortForm:{keyword:s,template:i},modifiers:r}}parseDescribe(){let t=this.expectKw("DESCRIBE"),e=this.optPunct("*"),s=[];if(!e){for(;this.isVarOrIri(this.peek());)s.push(this.term(this.next()));s.length===0&&this.fail(this.peek(),"'*', a variable or an IRI after DESCRIBE")}let i=this.parseDatasets(),r=this.isKw(this.peek(),"WHERE")||this.isPunct(this.peek(),"{")?this.parseWhereClause(!0):null,n=this.parseSolutionModifier();return{type:"Describe",keyword:t,star:e,items:s,datasets:i,where:r,modifiers:n}}parseAsk(){let t=this.expectKw("ASK"),e=this.parseDatasets(),s=this.parseWhereClause(!0),i=this.parseSolutionModifier();return{type:"Ask",keyword:t,datasets:e,where:s,modifiers:i}}parseDatasets(){let t=[];for(;this.isKw(this.peek(),"FROM");){let e=this.next(),s=this.optKw("NAMED");t.push({type:"DatasetClause",from:e,named:s,iri:this.parseIri()})}return t}parseWhereClause(t){return{keyword:t?this.optKw("WHERE"):this.expectKw("WHERE"),group:this.parseGroupGraphPattern()}}parseSolutionModifier(){let t={groupBy:null,having:null,orderBy:null,limitOffset:[]};if(this.isKw(this.peek(),"GROUP")){let s=this.next(),i=this.expectKw("BY"),r=[];for(;this.startsCondition(this.peek());)if(this.isPunct(this.peek(),"(")){let n=this.next(),a=this.parseExpression(),h=this.optKw("AS"),p=h?this.parseVar():null,l=this.expectPunct(")");r.push({type:"Projection",open:n,expression:a,as:h,variable:p,close:l})}else this.peek().type==="VAR"?r.push(this.term(this.next())):r.push(this.parseConstraint());r.length===0&&this.fail(this.peek(),"a GROUP BY condition"),t.groupBy={group:s,by:i,conditions:r}}if(this.isKw(this.peek(),"HAVING")){let s=this.next(),i=[];for(;this.startsCondition(this.peek())&&this.peek().type!=="VAR";)i.push(this.parseConstraint());i.length===0&&this.fail(this.peek(),"a HAVING condition"),t.having={keyword:s,conditions:i}}if(this.isKw(this.peek(),"ORDER")){let s=this.next(),i=this.expectKw("BY"),r=[];for(;;){let n=this.peek();if(this.isKw(n,"ASC","DESC")){let a=this.next();r.push({type:"OrderCondition",direction:a,expression:this.parseBracketed()})}else if(n.type==="VAR")r.push(this.term(this.next()));else if(this.startsCondition(n))r.push(this.parseConstraint());else break}r.length===0&&this.fail(this.peek(),"an ORDER BY condition"),t.orderBy={order:s,by:i,conditions:r}}let e=this.optKw("LIMIT","OFFSET");if(e){t.limitOffset.push({keyword:e,value:this.parseInteger()});let s=this.optKw(this.isKw(e,"LIMIT")?"OFFSET":"LIMIT");s&&t.limitOffset.push({keyword:s,value:this.parseInteger()})}return t}parseInteger(){let t=this.peek();return t.type!=="INTEGER"&&this.fail(t,"an integer"),this.next()}startsCondition(t){return t.type==="VAR"||this.isPunct(t,"(")||t.type==="IRIREF"||t.type==="PNAME_LN"||t.type==="PNAME_NS"||t.type==="NAME"&&(M.has(t.value.toUpperCase())||this.isKw(t,"EXISTS","NOT"))}parseConstraint(){let t=this.peek();if(this.isPunct(t,"("))return this.parseBracketed();if(t.type==="NAME")return this.parseBuiltInCall();if(t.type==="IRIREF"||t.type==="PNAME_LN"||t.type==="PNAME_NS"){let e=this.parseIri();return this.isPunct(this.peek(),"(")||this.fail(this.peek(),"'(' of a function call"),this.parseArgList(e,!1)}return this.fail(t,"'(', a built-in call or a function call")}parseUpdate(){let t=[];for(;;){let s=this.parsePrologue(),i=this.peek(),r=null;i.type==="NAME"&&lt.has(i.value.toUpperCase())?r=this.parseUpdateOperation():i.type!=="EOF"&&this.fail(i,t.length===0&&s.length===0?"a query or update":"an update operation");let n=r?this.optPunct(";"):null;if(t.push({prologue:s,operation:r,semicolon:n}),!n)break}let e=this.peek();return e.type!=="EOF"&&this.fail(e,"';' or end of update"),{type:"Update",parts:t,eof:e}}parseUpdateOperation(){let e=this.peek().value.toUpperCase();switch(e){case"LOAD":{let s=this.next(),i=this.optKw("SILENT"),r=this.parseIri(),n=null;if(this.isKw(this.peek(),"INTO")){let a=this.next(),h=this.expectKw("GRAPH");n={type:"Words",tokens:[a,h,this.parseIri()]}}return{type:"Load",keyword:s,silent:i,iri:r,into:n}}case"CLEAR":case"DROP":case"CREATE":{let s=this.next(),i=this.optKw("SILENT"),r;return e!=="CREATE"&&this.isKw(this.peek(),"DEFAULT","NAMED","ALL")?r={type:"Words",tokens:[this.next()]}:r={type:"Words",tokens:[this.expectKw("GRAPH"),this.parseIri()]},{type:"GraphManagement",keyword:s,silent:i,target:r}}case"ADD":case"MOVE":case"COPY":{let s=this.next(),i=this.optKw("SILENT"),r=this.parseGraphOrDefault(),n=this.expectKw("TO"),a=this.parseGraphOrDefault();return{type:"GraphTransfer",keyword:s,silent:i,from:r,to:n,target:a}}case"INSERT":return this.isKw(this.peek(1),"DATA")?{type:"QuadData",keywords:[this.next(),this.next()],quads:this.checkQuads(this.parseQuads(),!0,!1)}:this.parseModify();case"DELETE":{if(this.isKw(this.peek(1),"DATA","WHERE")){let s=[this.next(),this.next()],i=this.isKw(s[1],"DATA");return{type:"QuadData",keywords:s,quads:this.checkQuads(this.parseQuads(),i,!0)}}return this.parseModify()}default:return this.parseModify()}}parseGraphOrDefault(){if(this.isKw(this.peek(),"DEFAULT"))return{type:"Words",tokens:[this.next()]};let t=this.optKw("GRAPH"),e=this.parseIri();return{type:"Words",tokens:t?[t,e]:[e]}}parseModify(){let t=null;this.isKw(this.peek(),"WITH")&&(t={keyword:this.next(),iri:this.parseIri()});let e=null,s=null;this.isKw(this.peek(),"DELETE")&&(e={keyword:this.next(),quads:this.checkQuads(this.parseQuads(),!1,!0)}),this.isKw(this.peek(),"INSERT")&&(s={keyword:this.next(),quads:this.parseQuads()}),!e&&!s&&this.fail(this.peek(),"DELETE or INSERT");let i=[];for(;this.isKw(this.peek(),"USING");){let n=this.next(),a=this.optKw("NAMED");i.push({keyword:n,named:a,iri:this.parseIri()})}let r=this.parseWhereClause(!1);return{type:"Modify",with:t,delete:e,insert:s,using:i,where:r}}parseTriplesTemplate(t){let e=this.expectPunct("{"),s=[];for(;!this.isPunct(this.peek(),"}");){this.startsTriples(this.peek())||this.fail(this.peek(),"a triple pattern or '}'");let r=this.parseTriplesSameSubject(t),n=this.optPunct(".");s.push({node:r,dot:n}),!n&&!this.isPunct(this.peek(),"}")&&this.fail(this.peek(),"'.' or '}'")}let i=this.next();return{type:"TriplesTemplate",open:e,items:s,close:i}}checkQuads(t,e,s){let i=(n,a)=>{throw new k(`${a} are not allowed here`,n.offset,n.line,n.column)},r=n=>{if(n===null||typeof n!="object")return;if(Array.isArray(n)){n.forEach((h,p)=>{s&&h?.type==="AnnotationBlock"&&(p===0||n[p-1].type!=="Reifier")&&i(h.open,"Blank nodes"),r(h)});return}let a=n;if(typeof a.offset=="number"&&typeof a.value=="string"){let h=a;e&&h.type==="VAR"&&i(h,"Variables"),s&&(h.type==="BLANK_NODE_LABEL"||this.isPunct(h,"["))&&i(h,"Blank nodes");return}s&&a.type==="Reifier"&&!a.id&&i(a.tilde,"Blank nodes"),s&&a.type==="ReifiedTriple"&&!a.reifier&&i(a.open,"Blank nodes");for(let h of Object.values(a))r(h)};return r(t.items),t}parseQuads(){let t=this.expectPunct("{"),e=[];for(;!this.isPunct(this.peek(),"}");)if(this.isKw(this.peek(),"GRAPH")){let i=this.next(),r=this.parseVarOrIri(),n=this.parseTriplesTemplate(!1);e.push({node:{type:"QuadsGraph",keyword:i,name:r,template:n},dot:this.optPunct(".")})}else if(this.startsTriples(this.peek())){let i=this.parseTriplesSameSubject(!1),r=this.optPunct(".");e.push({node:i,dot:r}),!r&&!this.isPunct(this.peek(),"}")&&!this.isKw(this.peek(),"GRAPH")&&this.fail(this.peek(),"'.' or '}'")}else this.fail(this.peek(),"a triple pattern, GRAPH or '}'");let s=this.next();return{type:"TriplesTemplate",open:t,items:e,close:s}}parseGroupGraphPattern(){let t=this.expectPunct("{");if(this.isKw(this.peek(),"SELECT")){let r=this.parseSubSelect(),n=this.expectPunct("}");return{type:"GroupGraphPattern",open:t,subSelect:r,items:[],close:n}}let e=[],s=!1;for(;;){let r=this.peek();if(this.isPunct(r,"}"))break;if(this.startsTriples(r)){s&&this.fail(r,"'.' before the next triple pattern");let n=this.parseTriplesSameSubject(!0),a=this.optPunct(".");e.push({node:n,dot:a}),s=!a}else{let n=this.parseGraphPatternNotTriples();e.push({node:n,dot:this.optPunct(".")}),s=!1}}let i=this.next();return{type:"GroupGraphPattern",open:t,subSelect:null,items:e,close:i}}parseGraphPatternNotTriples(){let t=this.peek();if(this.isPunct(t,"{")){let e=[this.parseGroupGraphPattern()],s=[];for(;this.isKw(this.peek(),"UNION");)s.push(this.next()),e.push(this.parseGroupGraphPattern());return e.length===1?e[0]:{type:"Union",groups:e,keywords:s}}if(t.type==="NAME")switch(t.value.toUpperCase()){case"OPTIONAL":return{type:"Optional",keyword:this.next(),group:this.parseGroupGraphPattern()};case"MINUS":return{type:"Minus",keyword:this.next(),group:this.parseGroupGraphPattern()};case"GRAPH":{let e=this.next(),s=this.parseVarOrIri();return{type:"Graph",keyword:e,name:s,group:this.parseGroupGraphPattern()}}case"SERVICE":{let e=this.next(),s=this.optKw("SILENT"),i=this.parseVarOrIri();return{type:"Service",keyword:e,silent:s,name:i,group:this.parseGroupGraphPattern()}}case"FILTER":return{type:"Filter",keyword:this.next(),constraint:this.parseConstraint()};case"BIND":{let e=this.next(),s=this.expectPunct("("),i=this.parseExpression(),r=this.expectKw("AS"),n=this.parseVar(),a=this.expectPunct(")");return{type:"Bind",keyword:e,open:s,expression:i,as:r,variable:n,close:a}}case"VALUES":return this.parseValues()}return this.fail(t,"a triple pattern, a graph pattern or '}'")}parseValues(){return{type:"Values",keyword:this.expectKw("VALUES"),block:this.parseDataBlock()}}parseDataBlock(){if(this.peek().type==="VAR"){let h=this.term(this.next()),p=this.expectPunct("{"),l=[];for(;!this.isPunct(this.peek(),"}");)l.push(this.parseDataBlockValue());let d=this.next();return{type:"DataBlock",variable:h,variables:null,open:p,values:l,rows:[],close:d}}let e=this.expectPunct("("),s=[];for(;this.peek().type==="VAR";)s.push(this.term(this.next()));let i=this.expectPunct(")"),r=this.expectPunct("{"),n=[];for(;!this.isPunct(this.peek(),"}");){let h=this.expectPunct("("),p=[];for(;!this.isPunct(this.peek(),")");)p.push(this.parseDataBlockValue());if(p.length!==s.length)throw new k(`Expected ${s.length} value(s) in this VALUES row, found ${p.length}`,h.offset,h.line,h.column);n.push({open:h,values:p,close:this.next()})}let a=this.next();return{type:"DataBlock",variable:null,variables:{open:e,vars:s,close:i},open:r,values:[],rows:n,close:a}}parseDataBlockValue(){let t=this.peek();if(this.isKw(t,"UNDEF"))return this.term(this.next());if(this.isPunct(t,"<<("))return this.parseTripleTerm("data");if(t.type==="IRIREF"||t.type==="PNAME_LN"||t.type==="PNAME_NS")return this.parseIri();let e=this.tryParseLiteral();return e||this.fail(t,"a data value (IRI, literal, UNDEF or triple term)")}startsTriples(t){switch(t.type){case"VAR":case"IRIREF":case"PNAME_LN":case"PNAME_NS":case"BLANK_NODE_LABEL":case"STRING":case"INTEGER":case"DECIMAL":case"DOUBLE":return!0;case"NAME":return this.isKw(t,"TRUE","FALSE");case"PUNCT":return["(","[","<<","<<(","+","-"].includes(t.value);default:return!1}}parseTriplesSameSubject(t){let e=this.peek(),s,i=!0;this.isPunct(e,"[")&&!this.isEmptyPair("[","]")?(s=this.parseBlankNodePropertyList(t),i=!1):this.isPunct(e,"(")&&!this.isEmptyPair("(",")")?(s=this.parseCollection(t),i=!1):this.isPunct(e,"<<")?(s=this.parseReifiedTriple(),i=!1):s=this.parseVarOrTerm();let r=i||this.startsVerb(this.peek(),t)?this.parsePropertyListNotEmpty(t):null;return{type:"Triples",subject:s,properties:r}}startsVerb(t,e){return t.type==="VAR"||t.type==="IRIREF"||t.type==="PNAME_LN"||t.type==="PNAME_NS"||t.type==="NAME"&&t.value==="a"?!0:e&&this.isPunct(t,"^","!","(")}parsePropertyListNotEmpty(t){let e=[];for(;;){let s=this.parseVerb(t),i=[];for(;;){let n=this.parseGraphNode(t),a=this.parseAnnotations(t);if(a.length>0&&s.type!=="Term"){let p=a[0].type==="Reifier"?a[0].tilde:a[0].open;throw new k("A reifier or annotation can only follow a simple predicate, not a property path",p.offset,p.line,p.column)}let h={node:n,annotations:a,comma:this.optPunct(",")};if(i.push(h),!h.comma)break}let r=[];for(;this.isPunct(this.peek(),";");)r.push(this.next());if(e.push({verb:s,objects:i,semicolons:r}),r.length===0||!this.startsVerb(this.peek(),t))break}return{type:"PropertyList",entries:e}}parseVerb(t){let e=this.peek();return e.type==="VAR"?this.term(this.next()):t?this.parsePath():e.type==="NAME"&&e.value==="a"?this.term(this.next()):this.parseIri("a predicate")}parseSimpleVerb(t){let e=this.peek();return e.type==="VAR"&&t?this.term(this.next()):e.type==="NAME"&&e.value==="a"?this.term(this.next()):this.parseIri("a predicate")}parseAnnotations(t){let e=[];for(;;){let s=this.peek();if(this.isPunct(s,"~"))e.push(this.parseReifier());else if(this.isPunct(s,"{|")){let i=this.next(),r=this.parsePropertyListNotEmpty(t),n=this.expectPunct("|}");e.push({type:"AnnotationBlock",open:i,properties:r,close:n})}else return e}}parseReifier(){let t=this.expectPunct("~"),e=this.peek(),s=null;return e.type==="VAR"||e.type==="IRIREF"||e.type==="PNAME_LN"||e.type==="PNAME_NS"?s=this.term(this.next()):e.type==="BLANK_NODE_LABEL"?s=this.term(this.next()):this.isEmptyPair("[","]")&&(s=this.term(this.next(),this.next())),{type:"Reifier",tilde:t,id:s}}parseGraphNode(t){let e=this.peek();return this.isPunct(e,"[")&&!this.isEmptyPair("[","]")?this.parseBlankNodePropertyList(t):this.isPunct(e,"(")&&!this.isEmptyPair("(",")")?this.parseCollection(t):this.isPunct(e,"<<")?this.parseReifiedTriple():this.parseVarOrTerm()}parseBlankNodePropertyList(t){let e=this.expectPunct("["),s=this.parsePropertyListNotEmpty(t),i=this.expectPunct("]");return{type:"BlankNodePropertyList",open:e,properties:s,close:i}}parseCollection(t){let e=this.expectPunct("("),s=[];for(;!this.isPunct(this.peek(),")");)s.push(this.parseGraphNode(t));let i=this.next();return{type:"Collection",open:e,items:s,close:i}}parseReifiedTriple(){let t=this.expectPunct("<<"),e=this.parseReifiedTripleTerm(),s=this.parseSimpleVerb(!0),i=this.parseReifiedTripleTerm(),r=this.isPunct(this.peek(),"~")?this.parseReifier():null,n=this.expectPunct(">>");return{type:"ReifiedTriple",open:t,subject:e,predicate:s,object:i,reifier:r,close:n}}parseReifiedTripleTerm(){let t=this.peek();return this.isPunct(t,"<<")?this.parseReifiedTriple():this.isPunct(t,"<<(")?this.parseTripleTerm("pattern"):(this.isPunct(t,"(")&&this.fail(t,"a variable, IRI, literal, blank node or triple"),this.isPunct(t,"[")&&!this.isEmptyPair("[","]")&&this.fail(t,"a variable, IRI, literal, blank node or triple"),this.parseVarOrTerm())}parseTripleTerm(t){let e=this.expectPunct("<<("),s=h=>{let p=this.peek();if(this.isPunct(p,"<<("))return h&&t!=="pattern"&&this.fail(p,"an IRI or variable"),this.parseTripleTerm(t);if(p.type==="VAR")return t==="data"&&this.fail(p,"an IRI or literal (variables are not allowed in VALUES)"),this.term(this.next());if(p.type==="IRIREF"||p.type==="PNAME_LN"||p.type==="PNAME_NS")return this.parseIri();if(p.type==="BLANK_NODE_LABEL"||this.isEmptyPair("[","]"))return t!=="pattern"&&this.fail(p,"an IRI, literal or variable"),p.type==="BLANK_NODE_LABEL"?this.term(this.next()):this.term(this.next(),this.next());h&&t!=="pattern"&&this.fail(p,t==="data"?"an IRI":"an IRI or variable");let l=this.tryParseLiteral();return l||this.fail(p,"an RDF term")},i=s(!0),r=this.parseSimpleVerb(t!=="data"),n=s(!1),a=this.expectPunct(")>>");return{type:"TripleTerm",open:e,subject:i,predicate:r,object:n,close:a}}isVarOrIri(t){return t.type==="VAR"||t.type==="IRIREF"||t.type==="PNAME_LN"||t.type==="PNAME_NS"}parseVar(){let t=this.peek();return t.type!=="VAR"&&this.fail(t,"a variable"),this.term(this.next())}parseIri(t="an IRI"){let e=this.peek();return e.type!=="IRIREF"&&e.type!=="PNAME_LN"&&e.type!=="PNAME_NS"&&this.fail(e,t),this.term(this.next())}parseVarOrIri(){let t=this.peek();return this.isVarOrIri(t)||this.fail(t,"a variable or an IRI"),this.term(this.next())}tryParseLiteral(){let t=this.peek();if(t.type==="STRING"){let e=[this.next()],s=this.peek();return s.type==="LANG_DIR"?e.push(this.next()):this.isPunct(s,"^^")&&(e.push(this.next()),e.push(...this.parseIri().tokens)),this.term(...e)}if(t.type==="INTEGER"||t.type==="DECIMAL"||t.type==="DOUBLE")return this.term(this.next());if(this.isPunct(t,"+","-")){let e=this.peek(1);return(e.type==="INTEGER"||e.type==="DECIMAL"||e.type==="DOUBLE")&&!e.spaceBefore?this.term(this.next(),this.next()):null}return t.type==="NAME"&&this.isKw(t,"TRUE","FALSE")?this.term(this.next()):null}parseVarOrTerm(){let t=this.peek();switch(t.type){case"VAR":case"IRIREF":case"PNAME_LN":case"PNAME_NS":case"BLANK_NODE_LABEL":return this.term(this.next())}if(this.isEmptyPair("(",")")||this.isEmptyPair("[","]"))return this.term(this.next(),this.next());if(this.isPunct(t,"<<("))return this.parseTripleTerm("pattern");let e=this.tryParseLiteral();return e||this.fail(t,"an RDF term or a variable")}parsePath(){let t=[this.parsePathSequence()],e=[];for(;this.isPunct(this.peek(),"|");)e.push(this.next()),t.push(this.parsePathSequence());return t.length===1?t[0]:{type:"PathAlternative",items:t,separators:e}}parsePathSequence(){let t=[this.parsePathEltOrInverse()],e=[];for(;this.isPunct(this.peek(),"/");)e.push(this.next()),t.push(this.parsePathEltOrInverse());return t.length===1?t[0]:{type:"PathSequence",items:t,separators:e}}parsePathEltOrInverse(){return this.isPunct(this.peek(),"^")?{type:"PathInverse",caret:this.next(),item:this.parsePathElt()}:this.parsePathElt()}parsePathElt(){let t=this.parsePathPrimary(),e=this.peek();return this.isPunct(e,"?","*","+")&&!this.isPathModAmbiguous(e)?{type:"PathModified",item:t,modifier:this.next()}:t}isPathModAmbiguous(t){if(this.isPunct(t,"+","-")){let e=this.peek(1);return(e.type==="INTEGER"||e.type==="DECIMAL"||e.type==="DOUBLE")&&!e.spaceBefore}return!1}parsePathPrimary(){let t=this.peek();if(t.type==="NAME"&&t.value==="a")return this.term(this.next());if(this.isPunct(t,"!"))return{type:"PathNegated",bang:this.next(),item:this.parsePathNegatedPropertySet()};if(this.isPunct(t,"(")){let e=this.next(),s=this.parsePath(),i=this.expectPunct(")");return{type:"PathGroup",open:e,path:s,close:i}}return this.parseIri("a predicate or property path")}parsePathNegatedPropertySet(){if(this.isPunct(this.peek(),"(")){let t=this.next();if(this.isPunct(this.peek(),")"))return{type:"PathGroup",open:t,path:null,close:this.next()};let e=[this.parsePathOneInPropertySet()],s=[];for(;this.isPunct(this.peek(),"|");)s.push(this.next()),e.push(this.parsePathOneInPropertySet());let i=this.expectPunct(")"),r=e.length===1?e[0]:{type:"PathAlternative",items:e,separators:s};return{type:"PathGroup",open:t,path:r,close:i}}return this.parsePathOneInPropertySet()}parsePathOneInPropertySet(){let t=this.peek();if(this.isPunct(t,"^")){let e=this.next(),s=this.peek(),i=s.type==="NAME"&&s.value==="a"?this.term(this.next()):this.parseIri();return{type:"PathInverse",caret:e,item:i}}return t.type==="NAME"&&t.value==="a"?this.term(this.next()):this.parseIri()}parseExpression(){let t=this.parseAnd();for(;this.isPunct(this.peek(),"||");){let e=this.next();t={type:"Binary",left:t,operator:e,right:this.parseAnd()}}return t}parseAnd(){let t=this.parseRelational();for(;this.isPunct(this.peek(),"&&");){let e=this.next();t={type:"Binary",left:t,operator:e,right:this.parseRelational()}}return t}parseRelational(){let t=this.parseAdditive(),e=this.peek();if(this.isPunct(e,"=","!=","<",">","<=",">=")){let s=this.next();return{type:"Binary",left:t,operator:s,right:this.parseAdditive()}}if(this.isKw(e,"IN")){let s=this.next();return{type:"In",expression:t,not:null,in:s,list:this.parseExpressionList()}}if(this.isKw(e,"NOT")&&this.isKw(this.peek(1),"IN")){let s=this.next(),i=this.next();return{type:"In",expression:t,not:s,in:i,list:this.parseExpressionList()}}return t}parseAdditive(){let t=this.parseMultiplicative();for(;this.isPunct(this.peek(),"+","-");){let e=this.next();t={type:"Binary",left:t,operator:e,right:this.parseMultiplicative()}}return t}parseMultiplicative(){let t=this.parseUnary();for(;this.isPunct(this.peek(),"*","/");){let e=this.next();t={type:"Binary",left:t,operator:e,right:this.parseUnary()}}return t}parseUnary(){let t=this.peek();if(this.isPunct(t,"!"))return{type:"Unary",operator:this.next(),expression:this.parseUnary()};if(this.isPunct(t,"+","-")){let e=this.peek(1);return(e.type==="INTEGER"||e.type==="DECIMAL"||e.type==="DOUBLE")&&!e.spaceBefore?this.term(this.next(),this.next()):{type:"Unary",operator:this.next(),expression:this.parsePrimary()}}return this.parsePrimary()}parsePrimary(){let t=this.peek();if(this.isPunct(t,"("))return this.parseBracketed();if(this.isPunct(t,"<<("))return this.parseTripleTerm("expression");if(t.type==="VAR")return this.term(this.next());if(t.type==="IRIREF"||t.type==="PNAME_LN"||t.type==="PNAME_NS"){let s=this.parseIri();return this.isPunct(this.peek(),"(")?this.parseArgList(s,!1):s}if(t.type==="NAME"&&!this.isKw(t,"TRUE","FALSE"))return this.parseBuiltInCall();let e=this.tryParseLiteral();return e||this.fail(t,"an expression")}parseBracketed(){let t=this.expectPunct("("),e=this.parseExpression(),s=this.expectPunct(")");return{type:"Bracketed",open:t,expression:e,close:s}}parseExpressionList(){let t=this.expectPunct("("),e=[],s=[];if(!this.isPunct(this.peek(),")"))for(e.push(this.parseExpression());this.isPunct(this.peek(),",");)s.push(this.next()),e.push(this.parseExpression());let i=this.expectPunct(")");return{type:"ExpressionList",open:t,items:e,commas:s,close:i}}parseBuiltInCall(){let t=this.peek(),e=t.value.toUpperCase();if(e==="EXISTS")return{type:"Exists",not:null,keyword:this.next(),group:this.parseGroupGraphPattern()};if(e==="NOT"&&this.isKw(this.peek(1),"EXISTS")){let n=this.next(),a=this.next();return{type:"Exists",not:n,keyword:a,group:this.parseGroupGraphPattern()}}if(t.type!=="NAME"||!M.has(e))return this.fail(t,"an expression");let s=this.next();this.isPunct(this.peek(),"(")||this.fail(this.peek(),`'(' after ${s.value}`);let i=this.parseArgList(s,!0),r=i.args.length;if(ht.has(e))r>0&&this.fail(i.args.length?this.tokenOf(i.args[0]):i.close,"')'");else if(U[e]){let[n,a]=U[e];if(r<n||r>a)throw new k(`${s.value} expects ${n===a?n:`${n} to ${a}`} argument(s), found ${r}`,s.offset,s.line,s.column)}else if(r!==1)throw new k(`${s.value} expects 1 argument, found ${r}`,s.offset,s.line,s.column);return i.distinct&&!at.has(e)&&this.fail(i.distinct,"an expression"),i.separator&&e!=="GROUP_CONCAT"&&this.fail(i.separator.semicolon,"')'"),e==="BOUND"&&(i.args[0].type!=="Term"||i.args[0].tokens[0].type!=="VAR")&&this.fail(this.tokenOf(i.args[0]),"a variable"),i}tokenOf(t){switch(t.type){case"Term":return t.tokens[0];case"Binary":return this.tokenOf(t.left);case"In":return this.tokenOf(t.expression);case"Call":return t.name.type==="Term"?t.name.tokens[0]:t.name;default:return"open"in t?t.open:this.peek()}}parseArgList(t,e){let s=this.expectPunct("("),i=t.type==="Term"?"":t.value.toUpperCase(),r=this.optKw("DISTINCT"),n=[],a=[],h=null;if(this.isPunct(this.peek(),")"))r&&this.fail(this.peek(),"an expression");else{for(i==="COUNT"&&this.isPunct(this.peek(),"*")?n.push(this.term(this.next())):n.push(this.parseExpression());this.isPunct(this.peek(),",");)a.push(this.next()),n.push(this.parseExpression());if(this.isPunct(this.peek(),";")){let l=this.next(),d=this.expectKw("SEPARATOR"),c=this.expectPunct("="),w=this.peek();w.type!=="STRING"&&this.fail(w,"a string"),h={semicolon:l,keyword:d,equals:c,value:this.term(this.next())}}}let p=this.expectPunct(")");return{type:"Call",name:t,builtin:e,open:s,distinct:r,args:n,commas:a,separator:h,close:p}}};var G=new Set([".",",",";"]),N=class{constructor(t){this.lines=[];this.current="";this.currentIndent="";this.level=0;this.nextIndent=null;this.pendingSpace=!1;this.pendingTrailing=[];this.leadingDone=new Set;this.deferred=[];this.commentCount=0;this.options=t}get atLineStart(){return this.current===""}indent(){this.level++}dedent(){this.level--}structuralIndent(){return this.options.indent.repeat(this.level)}column(){return this.atLineStart?(this.nextIndent??this.structuralIndent()).length:this.currentIndent.length+this.current.length+(this.pendingSpace?1:0)}space(){this.atLineStart||(this.pendingSpace=!0)}newline(){if(this.atLineStart&&this.pendingTrailing.length===0){this.nextIndent=null;return}let[t,...e]=this.pendingTrailing,s=this.current;t!==void 0&&(s=s===""?t.text:`${s} ${t.text}`,this.commentCount++),this.lines.push((this.currentIndent+s).replace(/\s+$/,"")),this.current="",this.pendingSpace=!1,this.pendingTrailing=[],this.deferred.push(...e)}lineIndent(){return this.atLineStart?this.nextIndent??this.structuralIndent():this.currentIndent}alignment(){let t=this.lineIndent();return t+" ".repeat(Math.max(0,this.column()-t.length))}continuation(){return this.lineIndent()+this.options.indent}newlineWith(t){this.newline(),this.nextIndent=t}blankLine(){this.newline();let t=this.lines[this.lines.length-1];t===void 0||t===""||/[{(\[]$/.test(t)||this.lines.push("")}breakLine(){this.atLineStart||(this.newline(),this.nextIndent=this.structuralIndent()+this.options.indent)}write(t){t!==""&&(this.atLineStart?(this.currentIndent=this.nextIndent??this.structuralIndent(),this.nextIndent=null,this.current=t):this.current+=(this.pendingSpace?" ":"")+t,this.pendingSpace=!1)}leadingComments(t,e){if(this.options.ignoreComments)return;let s=[...this.deferred];if(this.deferred=[],t&&t.leading.length>0&&!this.leadingDone.has(t)&&(this.leadingDone.add(t),s.push(...t.leading)),s.length>0){this.breakLine();let i=this.nextIndent;for(let r of s)r.blankLinesBefore>0&&this.options.preserveBlankLines&&this.blankLine(),this.nextIndent=i,this.write(r.text),this.commentCount++,this.newline();this.nextIndent=i}t&&e&&t.blankLinesBefore>0&&this.options.preserveBlankLines&&this.atLineStart&&this.blankLine()}trailingComment(t){this.options.ignoreComments||t.trailing&&this.pendingTrailing.push(t.trailing)}token(t,e=t.value,s=!1){this.pendingTrailing.length>0&&!G.has(e)&&this.breakLine(),this.leadingComments(t,s),this.write(e),this.trailingComment(t)}drop(t){this.options.ignoreComments||(this.leadingDone.has(t)||(this.leadingDone.add(t),this.deferred.push(...t.leading)),this.deferred.length>0&&t.trailing?this.deferred.push(t.trailing):this.trailingComment(t))}commentsBefore(t){this.leadingComments(t,!1)}text(t){this.pendingTrailing.length>0&&!G.has(t)&&this.breakLine(),this.deferred.length>0&&this.leadingComments(null,!1),this.write(t)}get isEmpty(){return this.lines.length===0&&this.atLineStart}singleLine(){return this.lines.length>0||this.pendingTrailing.length>0||this.deferred.length>0||this.commentCount>0?null:this.current}toString(){for(this.leadingComments(null,!1),this.newline();this.lines.length>0&&this.lines[this.lines.length-1]==="";)this.lines.pop();return this.lines.join(`
7
+ `)}};function F(o={}){return{indent:typeof o.indent=="string"?o.indent:" ".repeat(Math.max(0,Math.floor(o.indent??2))),keywordCase:o.keywordCase??"upper",functionCase:o.functionCase??"preserve",alignPredicates:o.alignPredicates??!0,preserveBlankLines:o.preserveBlankLines??!0,compact:o.compact??!1,lineWidth:o.lineWidth??100,insertWhere:o.insertWhere??!0}}function C(o,t){return t==="upper"?o.toUpperCase():t==="lower"?o.toLowerCase():o}var I=class{constructor(t){this.options=t,this.w=this.newWriter()}newWriter(t=!1){return new N({indent:this.options.indent,preserveBlankLines:this.options.preserveBlankLines,ignoreComments:t})}print(t){return t.type==="Query"?this.query(t):this.update(t),{text:this.w.toString(),comments:this.w.commentCount}}measure(t,e,s=!1){let i=this.w;this.w=this.newWriter(s);try{t();let r=this.w.singleLine();return r!==null&&r.length<=e?r:null}finally{this.w=i}}remainingWidth(){return this.options.lineWidth-this.w.column()}kw(t,e=!1){this.w.token(t,C(t.value,this.options.keywordCase),e)}synthKw(t){this.w.text(C(t,this.options.keywordCase))}tok(t,e=!1){this.w.token(t,t.value,e)}sp(){this.w.space()}nl(){this.w.newline()}prologue(t){for(let e of t)this.nl(),this.kw(e.keyword,!0),this.sp(),e.prefix&&(this.tok(e.prefix),this.sp()),this.tok(e.value);t.length>0&&this.w.blankLine()}query(t){this.prologue(t.prologue);let e=t.form;switch(e.type){case"Select":this.selectClause(e.select),this.datasets(e.datasets),this.whereClause(e.where,this.options.insertWhere),this.solutionModifier(e.modifiers);break;case"Construct":this.nl(),this.kw(e.keyword),e.template?(this.sp(),this.triplesTemplate(e.template),this.datasets(e.datasets),this.whereClause(e.where,this.options.insertWhere)):(this.datasets(e.datasets),this.nl(),this.kw(e.shortForm.keyword),this.sp(),this.triplesTemplate(e.shortForm.template)),this.solutionModifier(e.modifiers);break;case"Describe":this.nl(),this.kw(e.keyword),e.star&&(this.sp(),this.tok(e.star));for(let s of e.items)this.sp(),this.term(s);this.datasets(e.datasets),e.where&&this.whereClause(e.where,this.options.insertWhere),this.solutionModifier(e.modifiers);break;case"Ask":this.nl(),this.kw(e.keyword),e.datasets.length===0&&!e.where.keyword?(this.sp(),this.group(e.where.group)):(this.datasets(e.datasets),this.whereClause(e.where,!0)),this.solutionModifier(e.modifiers);break}t.values&&(this.nl(),this.values(t.values)),this.nl(),this.w.drop(t.eof)}selectClause(t){this.nl(),this.kw(t.keyword),t.modifier&&(this.sp(),this.kw(t.modifier)),t.star&&(this.sp(),this.tok(t.star));for(let e of t.items)this.sp(),e.type==="Term"?this.term(e):this.projection(e)}projection(t){this.tok(t.open),this.expr(t.expression),t.as&&t.variable&&(this.sp(),this.kw(t.as),this.sp(),this.term(t.variable)),this.tok(t.close)}datasets(t){for(let e of t)this.nl(),this.kw(e.from),e.named&&(this.sp(),this.kw(e.named)),this.sp(),this.term(e.iri)}whereClause(t,e){this.nl(),t.keyword?(this.kw(t.keyword),this.sp()):e&&(this.synthKw("WHERE"),this.sp()),this.group(t.group)}solutionModifier(t){if(t.groupBy){this.nl(),this.kw(t.groupBy.group),this.sp(),this.kw(t.groupBy.by);for(let e of t.groupBy.conditions)this.sp(),this.condition(e)}if(t.having){this.nl(),this.kw(t.having.keyword);for(let e of t.having.conditions)this.sp(),this.condition(e)}if(t.orderBy){this.nl(),this.kw(t.orderBy.order),this.sp(),this.kw(t.orderBy.by);for(let e of t.orderBy.conditions)this.sp(),this.condition(e)}for(let e of t.limitOffset)this.nl(),this.kw(e.keyword),this.sp(),this.tok(e.value)}condition(t){t.type==="Projection"?this.projection(t):t.type==="OrderCondition"?(t.direction&&this.kw(t.direction),this.expr(t.expression)):this.expr(t)}update(t){let e=!0;for(let s of t.parts)!e&&(s.prologue.length>0||s.operation)&&this.w.blankLine(),this.prologue(s.prologue),s.operation&&(this.updateOperation(s.operation),e=!1),s.semicolon&&(this.sp(),this.tok(s.semicolon));this.nl(),this.w.drop(t.eof)}words(t){t.tokens.forEach((e,s)=>{s>0&&this.sp(),"tokens"in e?this.term(e):this.kw(e)})}updateOperation(t){switch(this.nl(),t.type){case"Load":this.kw(t.keyword),t.silent&&(this.sp(),this.kw(t.silent)),this.sp(),this.term(t.iri),t.into&&(this.sp(),this.words(t.into));break;case"GraphManagement":this.kw(t.keyword),t.silent&&(this.sp(),this.kw(t.silent)),this.sp(),this.words(t.target);break;case"GraphTransfer":this.kw(t.keyword),t.silent&&(this.sp(),this.kw(t.silent)),this.sp(),this.words(t.from),this.sp(),this.kw(t.to),this.sp(),this.words(t.target);break;case"QuadData":this.kw(t.keywords[0]),this.sp(),this.kw(t.keywords[1]),this.sp(),this.triplesTemplate(t.quads);break;case"Modify":t.with&&(this.kw(t.with.keyword),this.sp(),this.term(t.with.iri),this.nl()),t.delete&&(this.kw(t.delete.keyword),this.sp(),this.triplesTemplate(t.delete.quads),this.nl()),t.insert&&(this.kw(t.insert.keyword),this.sp(),this.triplesTemplate(t.insert.quads),this.nl());for(let e of t.using)this.kw(e.keyword),e.named&&(this.sp(),this.kw(e.named)),this.sp(),this.term(e.iri),this.nl();this.whereClause(t.where,!0);break}}block(t,e,s,i,r=t.value){if(this.w.token(t,r),s&&e.leading.length===0&&!t.trailing){this.tok(e);return}this.w.indent(),i(),this.nl(),this.w.commentsBefore(e),this.w.dedent(),this.nl(),this.tok(e)}inlineBlock(t,e,s){return!this.options.compact||this.measure(()=>{this.tok(t),this.sp(),s(),this.sp(),this.tok(e)},this.remainingWidth())===null?!1:(this.tok(t),this.sp(),s(),this.sp(),this.tok(e),!0)}group(t){if(t.subSelect){let e=t.subSelect;this.block(t.open,t.close,!1,()=>{this.selectClause(e.select),this.whereClause(e.where,this.options.insertWhere),this.solutionModifier(e.modifiers),e.values&&(this.nl(),this.values(e.values))});return}t.items.length===1&&t.items[0].node.type==="Triples"&&this.inlineBlock(t.open,t.close,()=>this.patternItem(t.items[0],!0))||this.block(t.open,t.close,t.items.length===0,()=>{t.items.forEach(e=>{this.nl(),this.patternItem(e,!1)})})}triplesTemplate(t){t.items.length===1&&t.items[0].node.type==="Triples"&&this.inlineBlock(t.open,t.close,()=>this.patternItem(t.items[0],!0))||this.block(t.open,t.close,t.items.length===0,()=>{for(let e of t.items)this.nl(),this.patternItem(e,!1)})}patternItem(t,e){let s=t.node;if(s.type==="Triples"){this.triples(s,!0),e?t.dot&&this.w.drop(t.dot):(this.sp(),t.dot?this.tok(t.dot):this.w.text("."));return}this.pattern(s,!0),t.dot&&this.w.drop(t.dot)}pattern(t,e){switch(t.type){case"GroupGraphPattern":this.markBlank(t.open,e),this.group(t);break;case"Union":t.groups.forEach((s,i)=>{i>0?(this.nl(),this.kw(t.keywords[i-1]),this.nl(),this.group(s)):(this.markBlank(s.open,e),this.group(s))});break;case"Optional":case"Minus":this.kw(t.keyword,e),this.sp(),this.group(t.group);break;case"Graph":this.kw(t.keyword,e),this.sp(),this.term(t.name),this.sp(),this.group(t.group);break;case"Service":this.kw(t.keyword,e),t.silent&&(this.sp(),this.kw(t.silent)),this.sp(),this.term(t.name),this.sp(),this.group(t.group);break;case"Filter":this.kw(t.keyword,e),this.sp(),this.expr(t.constraint);break;case"Bind":this.kw(t.keyword,e),this.sp(),this.tok(t.open),this.expr(t.expression),this.sp(),this.kw(t.as),this.sp(),this.term(t.variable),this.tok(t.close);break;case"Values":this.markBlank(t.keyword,e),this.values(t);break;case"QuadsGraph":this.kw(t.keyword,e),this.sp(),this.term(t.name),this.sp(),this.triplesTemplate(t.template);break;default:throw new Error(`Unexpected pattern ${t.type}`)}}markBlank(t,e){e&&t.blankLinesBefore>0&&this.options.preserveBlankLines&&this.w.atLineStart&&(this.w.commentsBefore(t),this.w.blankLine())}values(t){this.kw(t.keyword,!0),this.sp();let e=t.block;if(e.variable){this.term(e.variable),this.sp();let i=e.values;this.measure(()=>this.valuesOneVar(e,!0),this.remainingWidth())!==null||i.length===0?this.valuesOneVar(e,!0):this.valuesOneVar(e,!1);return}let s=e.variables;this.tok(s.open),s.vars.forEach((i,r)=>{r>0&&this.sp(),this.term(i)}),this.tok(s.close),this.sp(),this.block(e.open,e.close,e.rows.length===0,()=>{for(let i of e.rows)this.nl(),this.tok(i.open),i.values.forEach((r,n)=>{n>0&&this.sp(),this.node(r)}),this.tok(i.close)})}valuesOneVar(t,e){if(e){this.tok(t.open);for(let s of t.values)this.sp(),this.node(s);t.values.length>0&&this.sp(),this.tok(t.close);return}this.block(t.open,t.close,!1,()=>{for(let s of t.values)this.nl(),this.node(s)})}triples(t,e){this.node(t.subject,e),t.properties&&(this.sp(),this.propertyList(t.properties))}propertyList(t,e=!1){let s=this.options.alignPredicates?this.w.alignment():this.w.continuation();t.entries.forEach((i,r)=>{r>0&&(e?this.sp():this.w.newlineWith(s)),this.node(i.verb),this.sp();let n=l=>{this.node(l.node);for(let d of l.annotations)this.sp(),this.node(d);l.comma&&this.tok(l.comma)},a=!e&&i.objects.length>1&&this.measure(()=>i.objects.forEach((l,d)=>(d>0&&this.sp(),n(l))),this.remainingWidth()-2,!0)===null,h=a?this.w.alignment():"";i.objects.forEach((l,d)=>{d>0&&(a?this.w.newlineWith(h):this.sp()),n(l)});let p=r===t.entries.length-1;i.semicolons.forEach((l,d)=>{!p&&d===0?(this.sp(),this.tok(l)):this.w.drop(l)})})}term(t,e=!1){t.tokens.forEach((s,i)=>{s.type==="NAME"&&s.value!=="a"&&!/^(true|false)$/i.test(s.value)?this.kw(s,e&&i===0):this.tok(s,e&&i===0)})}node(t,e=!1){switch(t.type){case"Term":this.term(t,e);break;case"TripleTerm":this.tok(t.open,e),this.sp(),this.node(t.subject),this.sp(),this.term(t.predicate),this.sp(),this.node(t.object),this.sp(),this.tok(t.close);break;case"ReifiedTriple":this.tok(t.open,e),this.sp(),this.node(t.subject),this.sp(),this.term(t.predicate),this.sp(),this.node(t.object),t.reifier&&(this.sp(),this.node(t.reifier)),this.sp(),this.tok(t.close);break;case"Reifier":this.tok(t.tilde),t.id&&(this.sp(),this.term(t.id));break;case"AnnotationBlock":{let s=i=>{this.tok(t.open),this.sp(),this.propertyList(t.properties,i),this.sp(),this.tok(t.close)};s(this.measure(()=>s(!0),this.remainingWidth())!==null);break}case"BlankNodePropertyList":this.tok(t.open,e),this.sp(),this.propertyList(t.properties),this.sp(),this.tok(t.close);break;case"Collection":this.tok(t.open,e);for(let s of t.items)this.sp(),this.node(s);this.sp(),this.tok(t.close);break;case"PathAlternative":case"PathSequence":t.items.forEach((s,i)=>{i>0&&this.tok(t.separators[i-1]),this.node(s)});break;case"PathInverse":this.tok(t.caret),this.node(t.item);break;case"PathModified":this.node(t.item),this.tok(t.modifier);break;case"PathNegated":this.tok(t.bang),this.node(t.item);break;case"PathGroup":this.tok(t.open),t.path&&this.node(t.path),this.tok(t.close);break;default:this.expr(t)}}expr(t){switch(t.type){case"Binary":this.expr(t.left),this.sp(),this.tok(t.operator),this.sp(),this.expr(t.right);break;case"In":this.expr(t.expression),this.sp(),t.not&&(this.kw(t.not),this.sp()),this.kw(t.in),this.sp(),this.expr(t.list);break;case"Unary":this.tok(t.operator),this.expr(t.expression);break;case"Bracketed":this.tok(t.open),this.expr(t.expression),this.tok(t.close);break;case"ExpressionList":this.tok(t.open),t.items.forEach((e,s)=>{s>0&&(this.tok(t.commas[s-1]),this.sp()),this.expr(e)}),this.tok(t.close);break;case"Call":t.name.type==="Term"?this.term(t.name):this.w.token(t.name,C(t.name.value,this.options.functionCase)),this.tok(t.open),t.distinct&&(this.kw(t.distinct),this.sp()),t.args.forEach((e,s)=>{s>0&&(this.tok(t.commas[s-1]),this.sp()),this.expr(e)}),t.separator&&(this.tok(t.separator.semicolon),this.sp(),this.kw(t.separator.keyword),this.sp(),this.tok(t.separator.equals),this.sp(),this.term(t.separator.value)),this.tok(t.close);break;case"Exists":t.not&&(this.kw(t.not),this.sp()),this.kw(t.keyword),this.sp(),this.group(t.group);break;case"OrderCondition":case"Projection":this.condition(t);break;case"TripleTerm":case"Term":this.node(t);break;default:throw new Error(`Unexpected expression ${t.type}`)}}};function ct(o){let t=0,e=new Set,s=i=>{if(i===null||typeof i!="object"||e.has(i))return;if(e.add(i),Array.isArray(i)){i.forEach(s);return}let r=i;if(typeof r.offset=="number"&&Array.isArray(r.leading)){t+=r.leading.length+(r.trailing?1:0);return}Object.values(r).forEach(s)};return s(o),t}function K(o,t){let{text:e,comments:s}=new I(F(t)).print(o),i=ct(o);if(s!==i)throw new Error(`Internal formatter error: ${i-s} comment(s) could not be placed`);return e}function L(o,t){return K(v(o),t)}function ut(o){try{return v(o),!0}catch{return!1}}var O={parse:v,tokenize:T,format(o,t="default",e=2){if(t!=="default"&&t!=="compact")throw new Error(`Unsupported formatting mode: ${t}`);return L(o,{indent:e,compact:t==="compact"})}},ft=L;var _=globalThis;_.spfmt=O;_.sparqlFormatter=D;})();
8
+ //# sourceMappingURL=spfmt.min.js.map
@@ -0,0 +1,73 @@
1
+ /**
2
+ * Line-oriented output buffer that knows about comments.
3
+ *
4
+ * Every source token passes through the writer exactly once, either printed
5
+ * (`token`) or dropped (`drop`, e.g. a superfluous `.`). Either way the
6
+ * comments attached to the token are written: leading comments on their own
7
+ * lines before the token, a trailing comment at the end of the line the token
8
+ * ends up on. This is what keeps comments next to the code they belong to.
9
+ */
10
+ import type { Token } from "./lexer.js";
11
+ export interface WriterOptions {
12
+ indent: string;
13
+ preserveBlankLines: boolean;
14
+ /** Leave comments out (used to measure the width of code). */
15
+ ignoreComments?: boolean;
16
+ }
17
+ export declare class Writer {
18
+ private lines;
19
+ private current;
20
+ private currentIndent;
21
+ private level;
22
+ /** Indent to use for the next line instead of the structural indent (alignment). */
23
+ private nextIndent;
24
+ private pendingSpace;
25
+ private pendingTrailing;
26
+ private leadingDone;
27
+ /** Leading comments of dropped tokens, written before the next output. */
28
+ private deferred;
29
+ private options;
30
+ /** Number of comments written; used to check that no comment was lost. */
31
+ commentCount: number;
32
+ constructor(options: WriterOptions);
33
+ get atLineStart(): boolean;
34
+ indent(): void;
35
+ dedent(): void;
36
+ private structuralIndent;
37
+ /** Column (0-based) at which the next text will be written. */
38
+ column(): number;
39
+ space(): void;
40
+ /** End the current line. Does nothing on an empty line unless comments are pending. */
41
+ newline(): void;
42
+ /** Indentation of the current line (or of the next line when nothing was written yet). */
43
+ private lineIndent;
44
+ /** Indent string that aligns a new line with the current column. */
45
+ alignment(): string;
46
+ /** Indent string one level deeper than the current line. */
47
+ continuation(): string;
48
+ /** Start a new line with the given indent string (from `alignment()` or `continuation()`). */
49
+ newlineWith(indent: string): void;
50
+ /** Make sure the output ends with exactly one empty line (unless at the very start or after an opening brace). */
51
+ blankLine(): void;
52
+ /** Continue the current statement on a new line (used when a comment forces a break). */
53
+ private breakLine;
54
+ private write;
55
+ private leadingComments;
56
+ private trailingComment;
57
+ /**
58
+ * Write a source token (optionally spelled differently, e.g. upper-cased).
59
+ * `blank`: keep a blank line that precedes the token in the source.
60
+ */
61
+ token(t: Token, text?: string, blank?: boolean): void;
62
+ /** Write only the comments of a token that is not printed. */
63
+ drop(t: Token): void;
64
+ /** Write only the leading comments of a token (used before closing brackets at the inner indent). */
65
+ commentsBefore(t: Token): void;
66
+ /** Write text that doesn't come from a source token. */
67
+ text(text: string): void;
68
+ /** Has anything been written to the current line or earlier? */
69
+ get isEmpty(): boolean;
70
+ /** The text written so far, if it fits on a single line without comments. */
71
+ singleLine(): string | null;
72
+ toString(): string;
73
+ }
package/package.json ADDED
@@ -0,0 +1,70 @@
1
+ {
2
+ "name": "@matdata/sparql-formatter",
3
+ "version": "1.0.0",
4
+ "description": "SPARQL 1.2 query and update formatter that keeps your comments where you put them",
5
+ "keywords": [
6
+ "sparql",
7
+ "sparql-1.2",
8
+ "sparql-star",
9
+ "rdf",
10
+ "rdf-star",
11
+ "formatter",
12
+ "pretty-print",
13
+ "prettier",
14
+ "yasgui",
15
+ "matgui"
16
+ ],
17
+ "homepage": "https://github.com/Matdata-eu/sparql-formatter#readme",
18
+ "bugs": {
19
+ "url": "https://github.com/Matdata-eu/sparql-formatter/issues"
20
+ },
21
+ "repository": {
22
+ "type": "git",
23
+ "url": "git+https://github.com/Matdata-eu/sparql-formatter.git"
24
+ },
25
+ "license": "MIT",
26
+ "author": "Matdata",
27
+ "type": "module",
28
+ "sideEffects": false,
29
+ "main": "./dist/index.cjs",
30
+ "module": "./dist/index.js",
31
+ "types": "./dist/index.d.ts",
32
+ "unpkg": "./dist/spfmt.min.js",
33
+ "jsdelivr": "./dist/spfmt.min.js",
34
+ "exports": {
35
+ ".": {
36
+ "types": "./dist/index.d.ts",
37
+ "import": "./dist/index.js",
38
+ "require": "./dist/index.cjs"
39
+ },
40
+ "./browser": "./dist/spfmt.min.js",
41
+ "./package.json": "./package.json"
42
+ },
43
+ "bin": {
44
+ "sparql-formatter": "dist/cli.js"
45
+ },
46
+ "files": [
47
+ "dist",
48
+ "!dist/**/*.map",
49
+ "README.md",
50
+ "LICENSE"
51
+ ],
52
+ "engines": {
53
+ "node": ">=18"
54
+ },
55
+ "scripts": {
56
+ "build": "node scripts/build.mjs",
57
+ "typecheck": "tsc -p tsconfig.test.json",
58
+ "test": "node --experimental-strip-types --no-warnings --test \"test/**/*.test.ts\"",
59
+ "test:dist": "node scripts/smoke-test.mjs",
60
+ "lint": "prettier --check .",
61
+ "format": "prettier --write .",
62
+ "prepublishOnly": "npm run build && npm test && npm run test:dist"
63
+ },
64
+ "devDependencies": {
65
+ "@types/node": "^24.0.0",
66
+ "esbuild": "^0.27.0",
67
+ "prettier": "^3.8.1",
68
+ "typescript": "^6.0.3"
69
+ }
70
+ }