@barishnamazov/gsql 0.1.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.
- package/README.md +203 -0
- package/dist/cli.js +174 -0
- package/dist/index.js +33 -0
- package/package.json +50 -0
- package/src/cli.ts +206 -0
- package/src/compiler.ts +73 -0
- package/src/generator.ts +547 -0
- package/src/index.ts +11 -0
- package/src/lexer.ts +636 -0
- package/src/parser.ts +1241 -0
- package/src/types.ts +165 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import{CstParser as Ce}from"chevrotain";import{createToken as o,Lexer as w}from"chevrotain";var me=o({name:"WhiteSpace",pattern:/\s+/,group:w.SKIPPED}),ue=o({name:"LineComment",pattern:/\/\/[^\n]*/,group:w.SKIPPED}),Ee=o({name:"BlockComment",pattern:/\/\*[\s\S]*?\*\//,group:w.SKIPPED}),r=o({name:"Identifier",pattern:/[a-zA-Z_][a-zA-Z0-9_]*/}),x=o({name:"TemplateIdentifier",pattern:/\{[a-zA-Z_][a-zA-Z0-9_]*\}/}),F=o({name:"Concept",pattern:/concept/,longer_alt:r}),j=o({name:"Schema",pattern:/schema/,longer_alt:r}),z=o({name:"Mixin",pattern:/mixin/,longer_alt:r}),Y=o({name:"Enum",pattern:/enum/,longer_alt:r}),Q=o({name:"Extension",pattern:/extension/,longer_alt:r}),H=o({name:"Function",pattern:/function/,longer_alt:r}),K=o({name:"Func",pattern:/func/,longer_alt:r}),Z=o({name:"Trigger",pattern:/trigger/,longer_alt:r}),D=o({name:"Index",pattern:/index/,longer_alt:r}),R=o({name:"Check",pattern:/check/,longer_alt:r}),J=o({name:"Before",pattern:/before/,longer_alt:r}),V=o({name:"After",pattern:/after/,longer_alt:r}),W=o({name:"Ondelete",pattern:/ondelete/,longer_alt:r}),X=o({name:"On",pattern:/on/,longer_alt:r}),tt=o({name:"Each",pattern:/each/,longer_alt:r}),et=o({name:"Row",pattern:/row/,longer_alt:r}),nt=o({name:"Statement",pattern:/statement/,longer_alt:r}),it=o({name:"Execute",pattern:/execute/,longer_alt:r}),d=o({name:"Unique",pattern:/unique/,longer_alt:r}),I=o({name:"Gin",pattern:/gin/,longer_alt:r}),y=o({name:"Gist",pattern:/gist/,longer_alt:r}),v=o({name:"Btree",pattern:/btree/,longer_alt:r}),b=o({name:"Hash",pattern:/hash/,longer_alt:r}),st=o({name:"Pkey",pattern:/pkey/,longer_alt:r}),rt=o({name:"Nonull",pattern:/nonull/,longer_alt:r}),ot=o({name:"Default",pattern:/default/,longer_alt:r}),at=o({name:"Ref",pattern:/ref/,longer_alt:r}),ct=o({name:"Cascade",pattern:/cascade/,longer_alt:r}),lt=o({name:"Restrict",pattern:/restrict/,longer_alt:r}),ht=o({name:"SetNull",pattern:/setnull/,longer_alt:r}),pt=o({name:"SetDefault",pattern:/setdefault/,longer_alt:r}),mt=o({name:"NoAction",pattern:/noaction/,longer_alt:r}),ut=o({name:"Update",pattern:/update/,longer_alt:r}),Et=o({name:"Insert",pattern:/insert/,longer_alt:r}),St=o({name:"Delete",pattern:/delete/,longer_alt:r}),Ct=o({name:"Return",pattern:/return/,longer_alt:r}),k=o({name:"New",pattern:/NEW/,longer_alt:r}),B=o({name:"Old",pattern:/OLD/,longer_alt:r}),ft=o({name:"Serial",pattern:/serial/i,longer_alt:r}),Nt=o({name:"BigSerial",pattern:/bigserial/i,longer_alt:r}),Ut=o({name:"Integer",pattern:/integer/i,longer_alt:r}),Lt=o({name:"Bigint",pattern:/bigint/i,longer_alt:r}),gt=o({name:"SmallInt",pattern:/smallint/i,longer_alt:r}),Ot=o({name:"Text",pattern:/text/i,longer_alt:r}),Tt=o({name:"Varchar",pattern:/varchar/i,longer_alt:r}),dt=o({name:"Char",pattern:/char/i,longer_alt:r}),Mt=o({name:"Boolean",pattern:/boolean/i,longer_alt:r}),At=o({name:"Timestamptz",pattern:/timestamptz/i,longer_alt:r}),xt=o({name:"Timestamp",pattern:/timestamp/i,longer_alt:r}),Dt=o({name:"Date",pattern:/date/i,longer_alt:r}),Rt=o({name:"Time",pattern:/time/i,longer_alt:r}),It=o({name:"Jsonb",pattern:/jsonb/i,longer_alt:r}),yt=o({name:"Json",pattern:/json/i,longer_alt:r}),vt=o({name:"Uuid",pattern:/uuid/i,longer_alt:r}),bt=o({name:"Inet",pattern:/inet/i,longer_alt:r}),kt=o({name:"Citext",pattern:/citext/i,longer_alt:r}),Bt=o({name:"Decimal",pattern:/decimal/i,longer_alt:r}),_t=o({name:"Numeric",pattern:/numeric/i,longer_alt:r}),$t=o({name:"Real",pattern:/real/i,longer_alt:r}),qt=o({name:"DoublePrecision",pattern:/double\s+precision/i,longer_alt:r}),Pt=o({name:"Bytea",pattern:/bytea/i,longer_alt:r}),Gt=o({name:"StringLiteral",pattern:/'(?:[^'\\]|\\.)*'/}),_=o({name:"NumberLiteral",pattern:/-?\d+(?:\.\d+)?/}),wt=o({name:"BooleanLiteral",pattern:/true|false/,longer_alt:r}),Ft=o({name:"NullLiteral",pattern:/null/i,longer_alt:r}),Ht=o({name:"Arrow",pattern:/->/}),jt=o({name:"DoubleColon",pattern:/::/}),M=o({name:"LBrace",pattern:/\{/}),A=o({name:"RBrace",pattern:/\}/}),S=o({name:"LParen",pattern:/\(/}),C=o({name:"RParen",pattern:/\)/}),zt=o({name:"LBracket",pattern:/\[/}),Yt=o({name:"RBracket",pattern:/\]/}),$=o({name:"LAngle",pattern:/</}),q=o({name:"RAngle",pattern:/>/}),N=o({name:"Semicolon",pattern:/;/}),O=o({name:"Comma",pattern:/,/}),P=o({name:"Dot",pattern:/\./}),G=o({name:"Equals",pattern:/=/}),Kt=[me,ue,Ee,Ht,jt,F,j,z,Y,Q,H,K,Z,D,R,J,V,W,X,tt,et,nt,it,d,I,y,v,b,st,rt,ot,at,pt,ht,ct,lt,mt,ut,Et,St,Ct,k,B,qt,At,xt,Nt,ft,gt,Lt,Ut,Tt,dt,Ot,Mt,Dt,Rt,It,yt,vt,bt,kt,Bt,_t,$t,Pt,Gt,_,wt,Ft,x,r,M,A,S,C,zt,Yt,$,q,N,O,P,G],Se=new w(Kt,{ensureOptimizations:!0});function ie(i){return Se.tokenize(i)}var Vt=class extends Ce{constructor(){super(Kt,{recoveryEnabled:!0,maxLookahead:3}),this.performSelfAnalysis()}anyIdentifier=this.RULE("anyIdentifier",()=>{this.OR([{ALT:()=>this.CONSUME(r)},{ALT:()=>this.CONSUME(F)},{ALT:()=>this.CONSUME(j)},{ALT:()=>this.CONSUME(z)},{ALT:()=>this.CONSUME(Y)},{ALT:()=>this.CONSUME(Q)},{ALT:()=>this.CONSUME(K)},{ALT:()=>this.CONSUME(Z)},{ALT:()=>this.CONSUME(D)},{ALT:()=>this.CONSUME(R)},{ALT:()=>this.CONSUME(J)},{ALT:()=>this.CONSUME(V)},{ALT:()=>this.CONSUME(X)},{ALT:()=>this.CONSUME(tt)},{ALT:()=>this.CONSUME(et)},{ALT:()=>this.CONSUME(nt)},{ALT:()=>this.CONSUME(it)},{ALT:()=>this.CONSUME(H)},{ALT:()=>this.CONSUME(Ct)},{ALT:()=>this.CONSUME(k)},{ALT:()=>this.CONSUME(B)},{ALT:()=>this.CONSUME(ut)},{ALT:()=>this.CONSUME(Et)},{ALT:()=>this.CONSUME(St)},{ALT:()=>this.CONSUME(d)},{ALT:()=>this.CONSUME(st)},{ALT:()=>this.CONSUME(rt)},{ALT:()=>this.CONSUME(ot)},{ALT:()=>this.CONSUME(at)},{ALT:()=>this.CONSUME(W)},{ALT:()=>this.CONSUME(ct)},{ALT:()=>this.CONSUME(lt)},{ALT:()=>this.CONSUME(ht)},{ALT:()=>this.CONSUME(pt)},{ALT:()=>this.CONSUME(mt)},{ALT:()=>this.CONSUME(I)},{ALT:()=>this.CONSUME(y)},{ALT:()=>this.CONSUME(v)},{ALT:()=>this.CONSUME(b)},{ALT:()=>this.CONSUME(ft)},{ALT:()=>this.CONSUME(Nt)},{ALT:()=>this.CONSUME(Ut)},{ALT:()=>this.CONSUME(Lt)},{ALT:()=>this.CONSUME(gt)},{ALT:()=>this.CONSUME(Ot)},{ALT:()=>this.CONSUME(Tt)},{ALT:()=>this.CONSUME(dt)},{ALT:()=>this.CONSUME(Mt)},{ALT:()=>this.CONSUME(At)},{ALT:()=>this.CONSUME(xt)},{ALT:()=>this.CONSUME(Dt)},{ALT:()=>this.CONSUME(Rt)},{ALT:()=>this.CONSUME(It)},{ALT:()=>this.CONSUME(yt)},{ALT:()=>this.CONSUME(vt)},{ALT:()=>this.CONSUME(bt)},{ALT:()=>this.CONSUME(kt)},{ALT:()=>this.CONSUME(Bt)},{ALT:()=>this.CONSUME(_t)},{ALT:()=>this.CONSUME($t)},{ALT:()=>this.CONSUME(qt)},{ALT:()=>this.CONSUME(Pt)}])});program=this.RULE("program",()=>{this.MANY(()=>{this.SUBRULE(this.topLevelDeclaration)})});topLevelDeclaration=this.RULE("topLevelDeclaration",()=>{this.OR([{ALT:()=>this.SUBRULE(this.extensionDecl)},{ALT:()=>this.SUBRULE(this.functionDecl)},{ALT:()=>this.SUBRULE(this.conceptDecl)},{ALT:()=>this.SUBRULE(this.enumDecl)},{ALT:()=>this.SUBRULE(this.schemaDecl)},{ALT:()=>this.SUBRULE(this.instantiation)},{ALT:()=>this.SUBRULE(this.perInstanceIndex)}])});extensionDecl=this.RULE("extensionDecl",()=>{this.CONSUME(Q),this.SUBRULE(this.anyIdentifier),this.CONSUME(N)});functionDecl=this.RULE("functionDecl",()=>{this.CONSUME(K),this.SUBRULE(this.anyIdentifier),this.CONSUME(S),this.CONSUME(C),this.CONSUME(Ht),this.SUBRULE2(this.anyIdentifier),this.SUBRULE(this.functionBody)});functionBody=this.RULE("functionBody",()=>{this.CONSUME(M),this.MANY(()=>{this.SUBRULE(this.functionStatement)}),this.CONSUME(A)});functionStatement=this.RULE("functionStatement",()=>{this.OR([{ALT:()=>this.SUBRULE(this.returnStatement)},{ALT:()=>this.SUBRULE(this.assignmentStatement)}])});returnStatement=this.RULE("returnStatement",()=>{this.CONSUME(Ct),this.OR([{ALT:()=>this.CONSUME(k)},{ALT:()=>this.CONSUME(B)},{ALT:()=>this.CONSUME(r)}]),this.CONSUME(N)});assignmentStatement=this.RULE("assignmentStatement",()=>{this.OR([{ALT:()=>this.CONSUME(k)},{ALT:()=>this.CONSUME(B)},{ALT:()=>this.CONSUME(r)}]),this.CONSUME(P),this.SUBRULE(this.anyIdentifier),this.CONSUME(G),this.SUBRULE(this.functionCallExpr),this.CONSUME(N)});functionCallExpr=this.RULE("functionCallExpr",()=>{this.CONSUME(r),this.CONSUME(S),this.CONSUME(C)});conceptDecl=this.RULE("conceptDecl",()=>{this.CONSUME(F),this.CONSUME(r),this.OPTION(()=>{this.SUBRULE(this.typeParamList)}),this.CONSUME(M),this.MANY(()=>{this.OR([{ALT:()=>this.SUBRULE(this.enumDecl)},{ALT:()=>this.SUBRULE(this.schemaDecl)}])}),this.CONSUME(A)});typeParamList=this.RULE("typeParamList",()=>{this.CONSUME($),this.CONSUME(r),this.MANY(()=>{this.CONSUME(O),this.CONSUME2(r)}),this.CONSUME(q)});enumDecl=this.RULE("enumDecl",()=>{this.CONSUME(Y),this.SUBRULE(this.anyIdentifier),this.CONSUME(M),this.MANY(()=>{this.SUBRULE2(this.anyIdentifier),this.CONSUME(N)}),this.CONSUME(A)});schemaDecl=this.RULE("schemaDecl",()=>{this.CONSUME(j),this.CONSUME(r),this.OPTION(()=>{this.SUBRULE(this.mixinList)}),this.CONSUME(M),this.MANY(()=>{this.SUBRULE(this.schemaBodyItem)}),this.CONSUME(A)});mixinList=this.RULE("mixinList",()=>{this.CONSUME(z),this.CONSUME(r),this.MANY(()=>{this.CONSUME(O),this.CONSUME2(r)})});schemaBodyItem=this.RULE("schemaBodyItem",()=>{this.OR([{ALT:()=>this.SUBRULE(this.indexDef)},{ALT:()=>this.SUBRULE(this.checkDef)},{ALT:()=>this.SUBRULE(this.triggerDef)},{ALT:()=>this.SUBRULE(this.columnDef)}])});columnDef=this.RULE("columnDef",()=>{this.SUBRULE(this.columnName),this.SUBRULE(this.dataType),this.MANY(()=>{this.SUBRULE(this.columnConstraint)}),this.CONSUME(N)});columnName=this.RULE("columnName",()=>{this.OR([{ALT:()=>{this.CONSUME(x),this.OPTION(()=>{this.CONSUME(r)})}},{ALT:()=>this.CONSUME2(r)}])});dataType=this.RULE("dataType",()=>{this.OR([{ALT:()=>this.CONSUME(ft)},{ALT:()=>this.CONSUME(Nt)},{ALT:()=>this.CONSUME(Ut)},{ALT:()=>this.CONSUME(Lt)},{ALT:()=>this.CONSUME(gt)},{ALT:()=>this.CONSUME(Ot)},{ALT:()=>this.CONSUME(Tt)},{ALT:()=>this.CONSUME(dt)},{ALT:()=>this.CONSUME(Mt)},{ALT:()=>this.CONSUME(At)},{ALT:()=>this.CONSUME(xt)},{ALT:()=>this.CONSUME(Dt)},{ALT:()=>this.CONSUME(Rt)},{ALT:()=>this.CONSUME(It)},{ALT:()=>this.CONSUME(yt)},{ALT:()=>this.CONSUME(vt)},{ALT:()=>this.CONSUME(bt)},{ALT:()=>this.CONSUME(kt)},{ALT:()=>this.CONSUME(Bt)},{ALT:()=>this.CONSUME(_t)},{ALT:()=>this.CONSUME($t)},{ALT:()=>this.CONSUME(qt)},{ALT:()=>this.CONSUME(Pt)},{ALT:()=>this.CONSUME(r)}]),this.OPTION(()=>{this.CONSUME(S),this.CONSUME(_),this.CONSUME(C)})});columnConstraint=this.RULE("columnConstraint",()=>{this.OR([{ALT:()=>this.CONSUME(st)},{ALT:()=>this.CONSUME(rt)},{ALT:()=>this.CONSUME(d)},{ALT:()=>this.SUBRULE(this.defaultConstraint)},{ALT:()=>this.SUBRULE(this.refConstraint)},{ALT:()=>this.SUBRULE(this.checkConstraint)},{ALT:()=>this.SUBRULE(this.onDeleteConstraint)}])});defaultConstraint=this.RULE("defaultConstraint",()=>{this.CONSUME(ot),this.CONSUME(S),this.SUBRULE(this.defaultValue),this.CONSUME(C)});defaultValue=this.RULE("defaultValue",()=>{this.OR([{ALT:()=>this.CONSUME(Gt)},{ALT:()=>this.CONSUME(_)},{ALT:()=>this.CONSUME(wt)},{ALT:()=>this.CONSUME(Ft)},{ALT:()=>this.SUBRULE(this.functionCallExpr)},{ALT:()=>{this.SUBRULE(this.anyIdentifier),this.CONSUME(jt),this.SUBRULE2(this.anyIdentifier)}},{ALT:()=>this.SUBRULE3(this.anyIdentifier)}])});refConstraint=this.RULE("refConstraint",()=>{this.CONSUME(at),this.CONSUME(S),this.CONSUME(r),this.CONSUME(P),this.CONSUME2(r),this.CONSUME(C)});checkConstraint=this.RULE("checkConstraint",()=>{this.CONSUME(R),this.CONSUME(S),this.SUBRULE(this.checkExpression),this.CONSUME(C)});checkExpression=this.RULE("checkExpression",()=>{this.MANY(()=>{this.OR([{ALT:()=>{this.CONSUME(S),this.SUBRULE(this.checkExpression),this.CONSUME(C)}},{ALT:()=>this.CONSUME(r)},{ALT:()=>this.CONSUME(x)},{ALT:()=>this.CONSUME(_)},{ALT:()=>this.CONSUME(Gt)},{ALT:()=>this.CONSUME(wt)},{ALT:()=>this.CONSUME(Ft)},{ALT:()=>this.CONSUME(jt)},{ALT:()=>this.CONSUME(G)},{ALT:()=>this.CONSUME(O)},{ALT:()=>this.CONSUME(P)},{ALT:()=>this.CONSUME($)},{ALT:()=>this.CONSUME(q)}])})});onDeleteConstraint=this.RULE("onDeleteConstraint",()=>{this.CONSUME(W),this.CONSUME(S),this.OR([{ALT:()=>this.CONSUME(ct)},{ALT:()=>this.CONSUME(lt)},{ALT:()=>this.CONSUME(ht)},{ALT:()=>this.CONSUME(pt)},{ALT:()=>this.CONSUME(mt)}]),this.CONSUME(C)});indexDef=this.RULE("indexDef",()=>{this.CONSUME(D),this.CONSUME(S),this.SUBRULE(this.indexColumnList),this.CONSUME(C),this.MANY(()=>{this.OR([{ALT:()=>this.CONSUME(d)},{ALT:()=>this.CONSUME(I)},{ALT:()=>this.CONSUME(y)},{ALT:()=>this.CONSUME(v)},{ALT:()=>this.CONSUME(b)}])}),this.CONSUME(N)});indexColumnList=this.RULE("indexColumnList",()=>{this.SUBRULE(this.indexColumn),this.MANY(()=>{this.CONSUME(O),this.SUBRULE2(this.indexColumn)})});indexColumn=this.RULE("indexColumn",()=>{this.OR([{ALT:()=>this.CONSUME(x)},{ALT:()=>this.CONSUME(r)}]),this.OPTION(()=>{this.CONSUME2(r)})});checkDef=this.RULE("checkDef",()=>{this.CONSUME(R),this.CONSUME(S),this.SUBRULE(this.checkExpression),this.CONSUME(C),this.CONSUME(N)});triggerDef=this.RULE("triggerDef",()=>{this.CONSUME(Z),this.CONSUME(r),this.OR([{ALT:()=>this.CONSUME(J)},{ALT:()=>this.CONSUME(V)}]),this.OR2([{ALT:()=>this.CONSUME(ut)},{ALT:()=>this.CONSUME(Et)},{ALT:()=>this.CONSUME(St)}]),this.CONSUME(X),this.CONSUME(tt),this.OR3([{ALT:()=>this.CONSUME(et)},{ALT:()=>this.CONSUME(nt)}]),this.CONSUME(it),this.CONSUME(H),this.CONSUME2(r),this.CONSUME(S),this.CONSUME(C),this.CONSUME(N)});instantiation=this.RULE("instantiation",()=>{this.SUBRULE(this.instantiationTargetList),this.CONSUME(G),this.SUBRULE(this.conceptReference),this.CONSUME(N)});instantiationTargetList=this.RULE("instantiationTargetList",()=>{this.SUBRULE(this.instantiationTarget),this.MANY(()=>{this.CONSUME(O),this.SUBRULE2(this.instantiationTarget)})});instantiationTarget=this.RULE("instantiationTarget",()=>{this.CONSUME(r),this.OPTION(()=>{this.CONSUME(zt),this.CONSUME2(r),this.CONSUME(Yt)})});conceptReference=this.RULE("conceptReference",()=>{this.CONSUME(r),this.OPTION(()=>{this.CONSUME($),this.SUBRULE(this.typeArgList),this.CONSUME(q)})});typeArgList=this.RULE("typeArgList",()=>{this.SUBRULE(this.typeArg),this.MANY(()=>{this.CONSUME(O),this.SUBRULE2(this.typeArg)})});typeArg=this.RULE("typeArg",()=>{this.CONSUME(r),this.OPTION(()=>{this.CONSUME(zt),this.CONSUME2(r),this.CONSUME(Yt)})});perInstanceIndex=this.RULE("perInstanceIndex",()=>{this.CONSUME(D),this.CONSUME(S),this.CONSUME(r),this.CONSUME(O),this.CONSUME2(r),this.MANY(()=>{this.CONSUME2(O),this.CONSUME3(r)}),this.CONSUME(C),this.MANY2(()=>{this.OR([{ALT:()=>this.CONSUME(d)},{ALT:()=>this.CONSUME(I)},{ALT:()=>this.CONSUME(y)},{ALT:()=>this.CONSUME(v)},{ALT:()=>this.CONSUME(b)}])}),this.CONSUME(N)})},Zt=new Vt;function u(i,t){let e=i.children[t];if(e&&e.length>0){let s=e[0];if(s&&"image"in s)return s.image}return""}function T(i,t){let e=i.children[t];return e?e.map(s=>"image"in s?s.image:"").filter(s=>s!==""):[]}function m(i,t){let s=i.children[t]?.[0];if(s&&"children"in s)return s}function L(i,t){let e=i.children[t];return e?e.filter(s=>"children"in s):[]}function se(i){let e=L(i,"anyIdentifier")[0];if(e)for(let s of Object.keys(e.children)){let l=e.children[s]?.[0];if(l&&"image"in l)return l.image}return""}function Jt(i){let t=L(i,"anyIdentifier"),e=[];for(let s of t)for(let a of Object.keys(s.children)){let n=s.children[a]?.[0];if(n&&"image"in n){e.push(n.image);break}}return e}var Wt=class{visit(t){let e=[],s=L(t,"topLevelDeclaration");for(let a of s){let l=this.visitTopLevelDeclaration(a);l&&e.push(l)}return{type:"Program",declarations:e}}visitTopLevelDeclaration(t){let e=m(t,"extensionDecl");if(e)return this.visitExtensionDecl(e);let s=m(t,"functionDecl");if(s)return this.visitFunctionDecl(s);let a=m(t,"conceptDecl");if(a)return this.visitConceptDecl(a);let l=m(t,"enumDecl");if(l)return this.visitEnumDecl(l);let n=m(t,"schemaDecl");if(n)return this.visitSchemaDecl(n);let c=m(t,"instantiation");if(c)return this.visitInstantiation(c);let h=m(t,"perInstanceIndex");return h?this.visitPerInstanceIndex(h):null}visitExtensionDecl(t){return{type:"ExtensionDecl",name:se(t)}}visitFunctionDecl(t){let e=Jt(t),s=e[0]??"",a=e[1]??"",l=m(t,"functionBody"),n="";if(l){let c=L(l,"functionStatement"),h=[];for(let p of c){let f=m(p,"returnStatement");if(f){let E=u(f,"Identifier");E||(E=u(f,"New")),E||(E=u(f,"Old")),h.push(`RETURN ${E};`)}let g=m(p,"assignmentStatement");if(g){let E=u(g,"Identifier");E||(E=u(g,"New")),E||(E=u(g,"Old"));let Qt=se(g),U=m(g,"functionCallExpr"),pe=U?u(U,"Identifier"):"";h.push(`${E}.${Qt} := ${pe}();`)}}n=h.join(`
|
|
2
|
+
`)}return{type:"FunctionDecl",name:s,returnType:a,body:n}}visitConceptDecl(t){let e=u(t,"Identifier"),s=[],a=m(t,"typeParamList");a&&s.push(...T(a,"Identifier"));let l=[],n=L(t,"schemaDecl");for(let h of n){let p=this.visitSchemaDecl(h);p.conceptScope=e,l.push(p)}let c=L(t,"enumDecl");for(let h of c){let p=this.visitEnumDecl(h);p.conceptScope=e,l.push(p)}return{type:"ConceptDecl",name:e,typeParams:s,members:l}}visitEnumDecl(t){let e=Jt(t),s=e[0]??"",a=e.slice(1);return{type:"EnumDecl",name:s,values:a}}visitSchemaDecl(t){let e=u(t,"Identifier"),s=[],a=m(t,"mixinList");a&&s.push(...T(a,"Identifier"));let l=[],n=L(t,"schemaBodyItem");for(let c of n){let h=this.visitSchemaBodyItem(c);h&&l.push(h)}return{type:"SchemaDecl",name:e,mixins:s,members:l}}visitSchemaBodyItem(t){let e=m(t,"columnDef");if(e)return this.visitColumnDef(e);let s=m(t,"indexDef");if(s)return this.visitIndexDef(s);let a=m(t,"checkDef");if(a)return this.visitCheckDef(a);let l=m(t,"triggerDef");return l?this.visitTriggerDef(l):null}visitColumnDef(t){let e=m(t,"columnName"),s="";if(e){let h=u(e,"TemplateIdentifier"),p=u(e,"Identifier");s=h?h+p:p}let a=m(t,"dataType"),l="";if(a){for(let f of Object.keys(a.children)){let E=a.children[f]?.[0];if(E&&"image"in E){l=E.image;break}}let p=a.children.NumberLiteral?.[0];p&&"image"in p&&(l+=`(${p.image})`)}let n=[],c=L(t,"columnConstraint");for(let h of c){let p=this.visitColumnConstraint(h);p&&n.push(p)}return{type:"ColumnDef",name:s,dataType:l,constraints:n}}visitColumnConstraint(t){if(t.children.Pkey)return{type:"PrimaryKey"};if(t.children.Nonull)return{type:"NotNull"};if(t.children.Unique)return{type:"Unique"};let e=m(t,"defaultConstraint");if(e){let n=m(e,"defaultValue"),c="";if(n){let h=u(n,"StringLiteral"),p=u(n,"NumberLiteral"),f=u(n,"BooleanLiteral"),g=u(n,"NullLiteral"),E=m(n,"functionCallExpr"),Qt=u(n,"DoubleColon"),U=Jt(n);h?c=h:p?c=p:f?c=f:g?c=g:E?c=u(E,"Identifier")+"()":Qt&&U.length===2&&U[0]&&U[1]?c=`${U[0]}::${U[1]}`:U.length>0&&U[0]&&(c=U[0])}return{type:"Default",value:c}}let s=m(t,"refConstraint");if(s){let n=T(s,"Identifier");return{type:"Reference",table:n[0]??"",column:n[1]??""}}let a=m(t,"checkConstraint");if(a){let n=m(a,"checkExpression");return{type:"Check",value:n?this.reconstructCheckExpression(n):""}}let l=m(t,"onDeleteConstraint");if(l){let n={Cascade:"CASCADE",Restrict:"RESTRICT",SetNull:"SET NULL",SetDefault:"SET DEFAULT",NoAction:"NO ACTION"};for(let[c,h]of Object.entries(n))if(l.children[c])return{type:"OnDelete",action:h}}return null}reconstructCheckExpression(t){let e=[];for(let s of Object.keys(t.children)){let a=t.children[s];if(a){for(let l of a)if("image"in l)e.push(l.image);else if("children"in l&&s==="checkExpression"){let n=this.reconstructCheckExpression(l);n&&e.push(`(${n})`)}}}return e.join(" ")}visitIndexDef(t){let e=[],s=m(t,"indexColumnList");if(s){let n=L(s,"indexColumn");for(let c of n){let h=u(c,"TemplateIdentifier"),p=u(c,"Identifier");e.push(h?h+p:p)}}let a=t.children.Unique!==void 0,l;return t.children.Gin&&(l="gin"),t.children.Gist&&(l="gist"),t.children.Btree&&(l="btree"),t.children.Hash&&(l="hash"),{type:"IndexDef",columns:e,unique:a,using:l}}visitCheckDef(t){let e=m(t,"checkExpression");return{type:"CheckDef",expression:e?this.reconstructCheckExpression(e):""}}visitTriggerDef(t){let e=T(t,"Identifier"),s=e[0]??"",a=e[1]??"",l=t.children.Before?"before":"after",n="update";t.children.Insert&&(n="insert"),t.children.Delete&&(n="delete");let c=t.children.Row?"row":"statement";return{type:"TriggerDef",name:s,timing:l,event:n,forEach:c,executeFunction:a}}visitInstantiation(t){let e=[],s=m(t,"instantiationTargetList");if(s){let c=L(s,"instantiationTarget");for(let h of c){let p=T(h,"Identifier");e.push({tableName:p[0]??"",alias:p[1]})}}let a=m(t,"conceptReference"),l="",n=[];if(a){l=u(a,"Identifier");let c=m(a,"typeArgList");if(c){let h=L(c,"typeArg");for(let p of h){let f=T(p,"Identifier");n.push({tableName:f[0]??"",alias:f[1]})}}}return{type:"Instantiation",targets:e,conceptName:l,typeArgs:n}}visitPerInstanceIndex(t){let e=T(t,"Identifier"),s=e[0]??"",a=e.slice(1),l=t.children.Unique!==void 0,n;return t.children.Gin&&(n="gin"),t.children.Gist&&(n="gist"),t.children.Btree&&(n="btree"),t.children.Hash&&(n="hash"),{type:"PerInstanceIndex",tableName:s,columns:a,unique:l,using:n}}};function Xt(i){let t=ie(i),e=[];for(let n of t.errors)e.push({message:n.message,location:{start:{line:n.line??0,column:n.column??0,offset:n.offset},end:{line:n.line??0,column:n.column??0,offset:n.offset}},severity:"error"});if(e.length>0)return{ast:null,errors:e};Zt.input=t.tokens;let s=Zt.program();for(let n of Zt.errors){let c=n.token;e.push({message:n.message,location:{start:{line:c.startLine??0,column:c.startColumn??0,offset:c.startOffset},end:{line:c.endLine??0,column:c.endColumn??0,offset:c.endOffset??c.startOffset}},severity:"error"})}return e.length>0?{ast:null,errors:e}:{ast:new Wt().visit(s),errors:e}}function te(i){return i.replace(/([A-Z]+)([A-Z][a-z])/g,"$1_$2").replace(/([a-z\d])([A-Z])/g,"$1_$2").toLowerCase()}function fe(){return{concepts:new Map,schemas:new Map,enums:new Map,tableToSchema:new Map,templateSubs:new Map,enumSql:[],tableSql:[],indexSql:[],triggerSql:[],extensionSql:[],functionSql:[],perInstanceIndexSql:[],generatedEnums:new Set,generatedTables:new Set}}function Ne(i,t){for(let e of i.declarations)switch(e.type){case"ConceptDecl":t.concepts.set(e.name,e);break;case"SchemaDecl":t.schemas.set(e.name,e);break;case"EnumDecl":t.enums.set(e.name,e);break}}function ee(i,t){let e=i.match(/^\{([^}]+)\}(.*)$/);if(e){let[,s,a]=e,l;for(let[n,c]of t.templateSubs)if(n===s){l=c;break}return(l??te(s??""))+(a??"")}return i}function Ue(i){return i.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function ae(i,t){let e=i;for(let[s,a]of t.templateSubs){let l=Ue(s),n=new RegExp(`\\{${l}\\}`,"g");e=e.replace(n,a)}return e=e.replace(/(\w+)::(\w+)/g,"'$2'::$1"),e}function ce(i,t){let e=i.name;if(t.generatedEnums.has(e))return;t.generatedEnums.add(e);let s=i.values.map(a=>`'${a}'`).join(", ");t.enumSql.push(`DO $$ BEGIN
|
|
3
|
+
CREATE TYPE ${e} AS ENUM (${s});
|
|
4
|
+
EXCEPTION
|
|
5
|
+
WHEN duplicate_object THEN null;
|
|
6
|
+
END $$;`)}function Le(i,t){let e=ee(i.name,t),s=i.dataType.toUpperCase(),a=[` ${e} ${s}`],l=[];for(let n of i.constraints)switch(n.type){case"PrimaryKey":a.push("PRIMARY KEY");break;case"NotNull":a.push("NOT NULL");break;case"Unique":a.push("UNIQUE");break;case"Default":a.push(`DEFAULT ${n.value??"NULL"}`);break;case"Reference":{let c=n.table??"";t.tableToSchema.has(c)&&(c=t.tableToSchema.get(c)??c),l.push(`REFERENCES ${c}(${n.column??"id"})`);break}case"Check":a.push(`CHECK (${ae(n.value??"",t)})`);break;case"OnDelete":l.push(`ON DELETE ${n.action??"NO ACTION"}`);break}return[...a,...l].join(" ")}function ge(i,t,e){let s=t.columns.map(h=>ee(h,e)).join(", "),a=t.columns.map(h=>ee(h,e)).join("_"),l=`idx_${i}_${a}`,n=t.unique===!0?"UNIQUE ":"",c=t.using?`USING ${t.using} `:"";return`CREATE ${n}INDEX ${l} ON ${i} ${c}(${s});`}function Oe(i,t,e){return` CHECK (${ae(t.expression,e)})`}function Te(i,t,e){let s=t.timing.toUpperCase(),a=t.event.toUpperCase(),l=t.forEach==="row"?"FOR EACH ROW":"FOR EACH STATEMENT";return`CREATE TRIGGER ${t.name}_${i}
|
|
7
|
+
${s} ${a} ON ${i}
|
|
8
|
+
${l} EXECUTE FUNCTION ${t.executeFunction}();`}function le(i,t){let e=[];for(let s of i.mixins){let a=t.schemas.get(s);a&&e.push(...le(a,t))}return e.push(...i.members),e}function re(i,t,e){let s=le(i,e),a=[],l=[],n=[],c=[];for(let h of s)switch(h.type){case"ColumnDef":a.push(h);break;case"IndexDef":l.push(h);break;case"CheckDef":n.push(h);break;case"TriggerDef":c.push(h);break}return{tableName:t,columns:a,indexes:l,checks:n,triggers:c}}function oe(i,t){if(t.generatedTables.has(i.tableName))return;t.generatedTables.add(i.tableName);let e=i.columns.map(n=>Le(n,t)),s=i.checks.map(n=>Oe(i.tableName,n,t)),l=[...e,...s].join(`,
|
|
9
|
+
`);t.tableSql.push(`CREATE TABLE ${i.tableName} (
|
|
10
|
+
${l}
|
|
11
|
+
);`);for(let n of i.indexes)t.indexSql.push(ge(i.tableName,n,t));for(let n of i.triggers)t.triggerSql.push(Te(i.tableName,n,t))}function de(i,t){t.extensionSql.push(`CREATE EXTENSION IF NOT EXISTS "${i.name}";`)}function Me(i,t){t.functionSql.push(`CREATE OR REPLACE FUNCTION ${i.name}()
|
|
12
|
+
RETURNS TRIGGER AS $$
|
|
13
|
+
BEGIN
|
|
14
|
+
${i.body}
|
|
15
|
+
END;
|
|
16
|
+
$$ LANGUAGE plpgsql;`)}function Ae(i,t){ce(i,t)}function xe(i,t){t.schemas.set(i.name,i)}function De(i,t){let e=t.concepts.get(i.conceptName);if(!e){let n=t.schemas.get(i.conceptName);if(n){let c=i.targets[0];if(c){let h=c.tableName;t.tableToSchema.set(n.name,h);let p=re(n,h,t);oe(p,t)}}return}t.templateSubs.clear();for(let n=0;n<e.typeParams.length;n++){let c=e.typeParams[n],h=i.typeArgs[n];c&&h&&(t.templateSubs.set(c,h.alias??te(c)),t.tableToSchema.set(c,h.tableName))}let s=e.members.filter(n=>n.type==="SchemaDecl"),a=new Map;for(let n=0;n<i.targets.length&&n<s.length;n++){let c=i.targets[n],h=s[n];c&&h&&(a.set(h.name,{name:c.tableName,alias:c.alias}),t.tableToSchema.set(h.name,c.tableName),c.alias?t.templateSubs.set(h.name,c.alias):t.templateSubs.set(h.name,te(h.name)))}let l=e.members.filter(n=>n.type==="EnumDecl");for(let n of l)ce(n,t);for(let n of s){let c=a.get(n.name);if(c){let h=re(n,c.name,t);oe(h,t)}}}function Re(i,t){let e=i.columns.join(", "),s=`idx_${i.tableName}_${i.columns.join("_")}`,a=i.unique===!0?"UNIQUE ":"",l=i.using?`USING ${i.using} `:"";t.perInstanceIndexSql.push(`CREATE ${a}INDEX ${s} ON ${i.tableName} ${l}(${e});`)}function ne(i){let t=fe();Ne(i,t);for(let a of i.declarations)Ie(a,t);let e=[];t.extensionSql.length>0&&e.push(t.extensionSql.join(`
|
|
17
|
+
|
|
18
|
+
`)),t.functionSql.length>0&&e.push(t.functionSql.join(`
|
|
19
|
+
|
|
20
|
+
`)),t.enumSql.length>0&&e.push(t.enumSql.join(`
|
|
21
|
+
|
|
22
|
+
`));let s=[];for(let a of t.tableSql){a&&s.push(a);let l=a.match(/CREATE TABLE (\w+)/);if(l){let n=l[1]??"";for(let c of t.indexSql)c.includes(` ON ${n} `)&&s.push(c);for(let c of t.triggerSql)c.includes(` ON ${n}`)&&s.push(c)}}return s.length>0&&e.push(s.join(`
|
|
23
|
+
|
|
24
|
+
`)),t.perInstanceIndexSql.length>0&&e.push(t.perInstanceIndexSql.join(`
|
|
25
|
+
|
|
26
|
+
`)),`-- Generated SQL from Schema DSL
|
|
27
|
+
|
|
28
|
+
`+e.join(`
|
|
29
|
+
|
|
30
|
+
`)+`
|
|
31
|
+
`}function Ie(i,t){switch(i.type){case"ExtensionDecl":de(i,t);break;case"FunctionDecl":Me(i,t);break;case"EnumDecl":Ae(i,t);break;case"SchemaDecl":xe(i,t);break;case"ConceptDecl":break;case"Instantiation":De(i,t);break;case"PerInstanceIndex":Re(i,t);break}}function he(i){let t=[],e=Xt(i);if(e.errors.length>0)return{success:!1,errors:e.errors,ast:e.ast??void 0};if(!e.ast)return t.push({message:"Failed to parse source code",severity:"error"}),{success:!1,errors:t};try{return{success:!0,sql:ne(e.ast),errors:[],ast:e.ast}}catch(s){let a=s instanceof Error?s.message:String(s);return t.push({message:`Code generation failed: ${a}`,severity:"error"}),{success:!1,errors:t,ast:e.ast}}}function ye(i){let t=he(i);if(!t.success||!t.sql){let e=t.errors.map(s=>s.message).join(`
|
|
32
|
+
`);throw new Error(`Compilation failed:
|
|
33
|
+
${e}`)}return t.sql}export{he as compile,ye as compileToSQL,ne as generate,Xt as parse};
|
package/package.json
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@barishnamazov/gsql",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Generic SQL - Parametric Polymorphism for SQL Schemas",
|
|
5
|
+
"module": "src/index.ts",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"main": "dist/index.js",
|
|
8
|
+
"bin": {
|
|
9
|
+
"gsql": "dist/cli.js"
|
|
10
|
+
},
|
|
11
|
+
"scripts": {
|
|
12
|
+
"build": "npm run build:lib && npm run build:cli && npm run make-cli-executable",
|
|
13
|
+
"build:lib": "esbuild src/index.ts --bundle --outdir=dist --format=esm --platform=browser --minify --external:chevrotain",
|
|
14
|
+
"build:cli": "esbuild src/cli.ts --bundle --outfile=dist/cli.js --format=esm --platform=node --minify",
|
|
15
|
+
"make-cli-executable": "echo '#!/usr/bin/env node' | cat - dist/cli.js > dist/cli.tmp && mv dist/cli.tmp dist/cli.js && chmod +x dist/cli.js",
|
|
16
|
+
"test": "vitest run",
|
|
17
|
+
"test:watch": "vitest",
|
|
18
|
+
"lint": "eslint .",
|
|
19
|
+
"format": "prettier --write --check \"src/**/*.ts\" \"test/**/*.ts\"",
|
|
20
|
+
"typecheck": "tsc --noEmit"
|
|
21
|
+
},
|
|
22
|
+
"devDependencies": {
|
|
23
|
+
"@types/node": "^20.0.0",
|
|
24
|
+
"esbuild": "^0.25.12",
|
|
25
|
+
"typescript": "^5.7.2",
|
|
26
|
+
"vitest": "^2.1.8"
|
|
27
|
+
},
|
|
28
|
+
"dependencies": {
|
|
29
|
+
"chevrotain": "^11.0.3"
|
|
30
|
+
},
|
|
31
|
+
"keywords": [
|
|
32
|
+
"sql",
|
|
33
|
+
"schema",
|
|
34
|
+
"generics",
|
|
35
|
+
"database",
|
|
36
|
+
"postgres",
|
|
37
|
+
"compiler"
|
|
38
|
+
],
|
|
39
|
+
"license": "MIT",
|
|
40
|
+
"repository": {
|
|
41
|
+
"type": "git",
|
|
42
|
+
"url": "https://github.com/BarishNamazov/gsql-dev",
|
|
43
|
+
"directory": "packages/gsql"
|
|
44
|
+
},
|
|
45
|
+
"files": [
|
|
46
|
+
"dist",
|
|
47
|
+
"src",
|
|
48
|
+
"README.md"
|
|
49
|
+
]
|
|
50
|
+
}
|
package/src/cli.ts
ADDED
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GSQL CLI
|
|
3
|
+
*
|
|
4
|
+
* Command-line interface for the GSQL compiler.
|
|
5
|
+
* Usage: gsql compile <file.gsql> [-o output.sql]
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { readFileSync, writeFileSync, existsSync } from "node:fs";
|
|
9
|
+
import { resolve, basename, dirname, join } from "node:path";
|
|
10
|
+
import { fileURLToPath } from "node:url";
|
|
11
|
+
import { compile } from "./compiler.ts";
|
|
12
|
+
|
|
13
|
+
interface CLIOptions {
|
|
14
|
+
command: string;
|
|
15
|
+
inputFile: string;
|
|
16
|
+
outputFile: string | null;
|
|
17
|
+
verbose: boolean;
|
|
18
|
+
help: boolean;
|
|
19
|
+
version: boolean;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
23
|
+
const packageJson = JSON.parse(readFileSync(join(__dirname, "..", "package.json"), "utf-8")) as {
|
|
24
|
+
version: string;
|
|
25
|
+
};
|
|
26
|
+
const VERSION = packageJson.version;
|
|
27
|
+
|
|
28
|
+
const HELP_TEXT = `
|
|
29
|
+
GSQL - Generic SQL Compiler
|
|
30
|
+
Parametric polymorphism for SQL schemas
|
|
31
|
+
|
|
32
|
+
Usage:
|
|
33
|
+
gsql compile <file.gsql> [-o output.sql]
|
|
34
|
+
gsql --help
|
|
35
|
+
gsql --version
|
|
36
|
+
|
|
37
|
+
Commands:
|
|
38
|
+
compile Compile a GSQL file to SQL
|
|
39
|
+
|
|
40
|
+
Options:
|
|
41
|
+
-o, --output <file> Write output to file (default: stdout)
|
|
42
|
+
-v, --verbose Show verbose output
|
|
43
|
+
-h, --help Show this help message
|
|
44
|
+
--version Show version number
|
|
45
|
+
|
|
46
|
+
Examples:
|
|
47
|
+
gsql compile schema.gsql
|
|
48
|
+
gsql compile schema.gsql -o schema.sql
|
|
49
|
+
gsql compile schema.gsql > schema.sql
|
|
50
|
+
`;
|
|
51
|
+
|
|
52
|
+
class ArgParser {
|
|
53
|
+
private index = 0;
|
|
54
|
+
|
|
55
|
+
constructor(private args: string[]) {}
|
|
56
|
+
|
|
57
|
+
current(): string | undefined {
|
|
58
|
+
return this.args[this.index];
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
next(): string | undefined {
|
|
62
|
+
this.index++;
|
|
63
|
+
return this.args[this.index];
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
advance(): void {
|
|
67
|
+
this.index++;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
hasMore(): boolean {
|
|
71
|
+
return this.index < this.args.length;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function parseArgs(args: string[]): CLIOptions {
|
|
76
|
+
const options: CLIOptions = {
|
|
77
|
+
command: "",
|
|
78
|
+
inputFile: "",
|
|
79
|
+
outputFile: null,
|
|
80
|
+
verbose: false,
|
|
81
|
+
help: false,
|
|
82
|
+
version: false,
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
const parser = new ArgParser(args);
|
|
86
|
+
|
|
87
|
+
while (parser.hasMore()) {
|
|
88
|
+
const arg = parser.current();
|
|
89
|
+
if (!arg) {
|
|
90
|
+
parser.advance();
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if (arg === "-h" || arg === "--help") {
|
|
95
|
+
options.help = true;
|
|
96
|
+
} else if (arg === "--version") {
|
|
97
|
+
options.version = true;
|
|
98
|
+
} else if (arg === "-v" || arg === "--verbose") {
|
|
99
|
+
options.verbose = true;
|
|
100
|
+
} else if (arg === "-o" || arg === "--output") {
|
|
101
|
+
const nextArg = parser.next();
|
|
102
|
+
if (nextArg) {
|
|
103
|
+
options.outputFile = nextArg;
|
|
104
|
+
}
|
|
105
|
+
} else if (!arg.startsWith("-")) {
|
|
106
|
+
if (!options.command) {
|
|
107
|
+
options.command = arg;
|
|
108
|
+
} else if (!options.inputFile) {
|
|
109
|
+
options.inputFile = arg;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
parser.advance();
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
return options;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function formatError(message: string, line?: number, column?: number): string {
|
|
119
|
+
let result = `Error: ${message}`;
|
|
120
|
+
if (line !== undefined && column !== undefined) {
|
|
121
|
+
result = `Error [${line}:${column}]: ${message}`;
|
|
122
|
+
}
|
|
123
|
+
return result;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function main(): void {
|
|
127
|
+
const args = process.argv.slice(2);
|
|
128
|
+
const options = parseArgs(args);
|
|
129
|
+
|
|
130
|
+
if (options.help) {
|
|
131
|
+
console.log(HELP_TEXT);
|
|
132
|
+
process.exit(0);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
if (options.version) {
|
|
136
|
+
console.log(`gsql version ${VERSION}`);
|
|
137
|
+
process.exit(0);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
if (!options.command) {
|
|
141
|
+
console.error("Error: No command specified");
|
|
142
|
+
console.log(HELP_TEXT);
|
|
143
|
+
process.exit(1);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
if (options.command !== "compile") {
|
|
147
|
+
console.error(`Error: Unknown command '${options.command}'`);
|
|
148
|
+
console.log(HELP_TEXT);
|
|
149
|
+
process.exit(1);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
if (!options.inputFile) {
|
|
153
|
+
console.error("Error: No input file specified");
|
|
154
|
+
console.log(HELP_TEXT);
|
|
155
|
+
process.exit(1);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
const inputPath = resolve(process.cwd(), options.inputFile);
|
|
159
|
+
|
|
160
|
+
if (!existsSync(inputPath)) {
|
|
161
|
+
console.error(`Error: File not found: ${options.inputFile}`);
|
|
162
|
+
process.exit(1);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
let source: string;
|
|
166
|
+
try {
|
|
167
|
+
source = readFileSync(inputPath, "utf-8");
|
|
168
|
+
} catch (err) {
|
|
169
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
170
|
+
console.error(`Error reading file: ${message}`);
|
|
171
|
+
process.exit(1);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
if (options.verbose) {
|
|
175
|
+
console.error(`Compiling ${basename(inputPath)}...`);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
const result = compile(source);
|
|
179
|
+
|
|
180
|
+
if (!result.success) {
|
|
181
|
+
for (const error of result.errors) {
|
|
182
|
+
console.error(
|
|
183
|
+
formatError(error.message, error.location?.start.line, error.location?.start.column)
|
|
184
|
+
);
|
|
185
|
+
}
|
|
186
|
+
process.exit(1);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
if (options.outputFile) {
|
|
190
|
+
const outputPath = resolve(process.cwd(), options.outputFile);
|
|
191
|
+
try {
|
|
192
|
+
writeFileSync(outputPath, result.sql ?? "");
|
|
193
|
+
if (options.verbose) {
|
|
194
|
+
console.error(`Output written to ${options.outputFile}`);
|
|
195
|
+
}
|
|
196
|
+
} catch (err) {
|
|
197
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
198
|
+
console.error(`Error writing file: ${message}`);
|
|
199
|
+
process.exit(1);
|
|
200
|
+
}
|
|
201
|
+
} else {
|
|
202
|
+
console.log(result.sql);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
main();
|
package/src/compiler.ts
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GSQL Compiler
|
|
3
|
+
*
|
|
4
|
+
* Main entry point for compiling GSQL source code to SQL.
|
|
5
|
+
* Provides both high-level and detailed compilation APIs.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { parse } from "./parser.ts";
|
|
9
|
+
import { generate } from "./generator.ts";
|
|
10
|
+
import type { CompileResult, CompileError } from "./types.ts";
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Compile GSQL source code to SQL.
|
|
14
|
+
*
|
|
15
|
+
* @param source - GSQL source code
|
|
16
|
+
* @returns CompileResult with success status, SQL output, errors, and optionally AST
|
|
17
|
+
*/
|
|
18
|
+
export function compile(source: string): CompileResult {
|
|
19
|
+
const errors: CompileError[] = [];
|
|
20
|
+
|
|
21
|
+
const parseResult = parse(source);
|
|
22
|
+
|
|
23
|
+
if (parseResult.errors.length > 0) {
|
|
24
|
+
return {
|
|
25
|
+
success: false,
|
|
26
|
+
errors: parseResult.errors,
|
|
27
|
+
ast: parseResult.ast ?? undefined,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (!parseResult.ast) {
|
|
32
|
+
errors.push({
|
|
33
|
+
message: "Failed to parse source code",
|
|
34
|
+
severity: "error",
|
|
35
|
+
});
|
|
36
|
+
return { success: false, errors };
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
try {
|
|
40
|
+
const sql = generate(parseResult.ast);
|
|
41
|
+
return {
|
|
42
|
+
success: true,
|
|
43
|
+
sql,
|
|
44
|
+
errors: [],
|
|
45
|
+
ast: parseResult.ast,
|
|
46
|
+
};
|
|
47
|
+
} catch (error) {
|
|
48
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
49
|
+
errors.push({
|
|
50
|
+
message: `Code generation failed: ${message}`,
|
|
51
|
+
severity: "error",
|
|
52
|
+
});
|
|
53
|
+
return { success: false, errors, ast: parseResult.ast };
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Convenience function that returns just the SQL string or throws on error.
|
|
59
|
+
*
|
|
60
|
+
* @param source - GSQL source code
|
|
61
|
+
* @returns Generated SQL
|
|
62
|
+
* @throws Error if compilation fails
|
|
63
|
+
*/
|
|
64
|
+
export function compileToSQL(source: string): string {
|
|
65
|
+
const result = compile(source);
|
|
66
|
+
|
|
67
|
+
if (!result.success || !result.sql) {
|
|
68
|
+
const errorMessages = result.errors.map((e) => e.message).join("\n");
|
|
69
|
+
throw new Error(`Compilation failed:\n${errorMessages}`);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return result.sql;
|
|
73
|
+
}
|