view w.c @ 0:e0bbaa717f41 draft default tip

lol J
author Jordi Gutiérrez Hermoso <jordigh@octave.org>
date Mon, 25 Nov 2013 11:56:30 -0500 (2013-11-25)
parents
children
line wrap: on
line source
/* Copyright 1990-2011, Jsoftware Inc.  All rights reserved. */
/* License in license.txt.                                   */
/*                                                                         */
/* Words: Word Formation                                                   */

#include "j.h"
#include "w.h"

#define SS              0    /* space                           */
#define SX              1    /* other                           */
#define SA              2    /* alphanumeric                    */
#define SN              3    /* N                               */
#define SNB             4    /* NB                              */
#define SNZ             5    /* NB.                             */
#define S9              6    /* numeric                         */
#define SQ              7    /* quote                           */
#define SQQ             8    /* even quotes                     */
#define SZ              9    /* trailing comment                */

#define EI              1    /* emit (b,i-1); b=.i              */
#define EN              2    /* b=.i                            */

typedef struct {C new,effect;} ST;

static ST state[10][9]={
/*SS */ {{SX,EN},{SS,0 },{SA,EN},{SN,EN},{SA,EN},{S9,EN},{SX,EN},{SX,EN},{SQ,EN}},
/*SX */ {{SX,EI},{SS,EI},{SA,EI},{SN,EI},{SA,EI},{S9,EI},{SX,0 },{SX,0 },{SQ,EI}},
/*SA */ {{SX,EI},{SS,EI},{SA,0 },{SA,0 },{SA,0 },{SA,0 },{SX,0 },{SX,0 },{SQ,EI}},
/*SN */ {{SX,EI},{SS,EI},{SA,0 },{SA,0 },{SNB,0},{SA,0 },{SX,0 },{SX,0 },{SQ,EI}},
/*SNB*/ {{SX,EI},{SS,EI},{SA,0 },{SA,0 },{SA,0 },{SA,0 },{SNZ,0},{SX,0 },{SQ,EI}},
/*SNZ*/ {{SZ,0 },{SZ,0 },{SZ,0 },{SZ,0 },{SZ,0 },{SZ,0 },{SX,0 },{SX,0 },{SZ,0 }},
/*S9 */ {{SX,EI},{SS,EI},{S9,0 },{S9,0 },{S9,0 },{S9,0 },{S9,0 },{SX,0 },{SQ,EI}},
/*SQ */ {{SQ,0 },{SQ,0 },{SQ,0 },{SQ,0 },{SQ,0 },{SQ,0 },{SQ,0 },{SQ,0 },{SQQ,0}},
/*SQQ*/ {{SX,EI},{SS,EI},{SA,EI},{SN,EI},{SA,EI},{S9,EI},{SX,EI},{SX,EI},{SQ,0 }},
/*SZ */ {{SZ,0 },{SZ,0 },{SZ,0 },{SZ,0 },{SZ,0 },{SZ,0 },{SZ,0 },{SZ,0 },{SZ,0 }}
};
/*         CX      CS      CA      CN      CB      C9      CD      CC      CQ   */

F1(jtwordil){A z;C e,nv,s,t=0;I b,i,m,n,*x,xb,xe;ST p;UC*v;
 RZ(w);
 nv=0; s=SS;
 n=AN(w); v=UAV(w); GA(z,INT,1+n+n,1,0); x=1+AV(z);
 for(i=0;i<n;++i){
  p=state[s][wtype[v[i]]]; e=p.effect;
  if(e==EI){
   t&=s==S9;
   if(t){if(!nv){nv=1; xb=b;} xe=i;}
   else{if(nv){nv=0; *x++=xb; *x++=xe-xb;} *x++=b; *x++=i-b;}
  }
  s=p.new;
  if(e){b=i; t=s==S9;}
 }
 if(s==SQ){jsignal3(EVOPENQ,w,b); R 0;}
 t&=s==S9;
 if(t){*x++=xb=nv?xb:b; *x++=n-xb;}
 else{if(nv){*x++=xb; *x++=xe-xb;} if(s!=SS){*x++=b; *x++=n-b;}}
 m=x-AV(z); *AV(z)=s==SZ||s==SNZ?-m/2:m/2;
 R z;
}    /* word index & length; z is (# words),(i0,l0),(i1,l1),... */

/* locals in wordil:                                            */
/* b:  beginning index of current word                          */
/* e:  current effect                                           */
/* i:  index of current character being scanned                 */
/* m:  2 * actual number of words                               */
/* n:  length of input string w                                 */
/* nv: 1 iff numeric constant vector being built                */
/* p:  state table entry per current state & character          */
/* s:  current state                                            */
/* t:  1 iff current state is S9                                */
/* v:  ptr to input string                                      */
/* x:  ptr to current element of z being computed               */
/* xb: beginning index of current numeric vector                */
/* xe: end index of current numeric vector                      */
/* z:  result; maximum of n words                               */

F1(jtwords){A t,*x,z;C*s;I k,n,*y;
 F1RANK(1,jtwords,0);
 RZ(w=vs(w));
 RZ(t=wordil(w));
 s=CAV(w); y=AV(t); n=*y++; n=0>n?-n:n;
 GA(z,BOX,n,1,0); x=AAV(z);
 DO(n, k=*y++; RZ(*x++=str(*y++,s+k)););
 R z;
}


static A jtconstr(J jt,I n,C*s){A z;C b,c,p,*t,*x;I m=0;
 p=0; t=s; DO(n-2, c=*++t; b=c==CQUOTE; if(!b||p)m++;    p=b&&!p;);
 if(0==m)R aqq; else if(1==m&&(z=chr[(UC)s[1]]))R z;
 GA(z,LIT,m,1!=m,0); x=CAV(z);
 p=0; t=s; DO(n-2, c=*++t; b=c==CQUOTE; if(!b||p)*x++=c; p=b&&!p;);
 R z;
}

#define TNAME(i)    (NAME&AT(v[i]))
#define TASGN(i)    (ASGN&AT(v[i]))
#define TRBRACE(i)  (y=v[i], CRBRACE==ID(y))
#define TVERB(i,c)  (y=v[i], c      ==ID(y))
#define TAIA(i,j)   (TASGN(1) && TNAME(i) && TNAME(j) && AN(v[i])==AN(v[j]) && \
                        !memcmp(NAV(v[i])->s,NAV(v[j])->s,AN(v[i])))

F2(jtenqueue){A*v,*x,y,z;B b;C d,e,p,*s,*wi;I i,n,*u,wl;UC c;
 RZ(a&&w);
 s=CAV(w); u=AV(a); n=*u++; n=0>n?-(1+n):n;
 GA(z,BOX,n,1,0); x=v=AAV(z);
 for(i=0;i<n;i++){
  wi=s+*u++; wl=*u++; c=e=*wi; p=ctype[c]; b=0;
  if(1<wl){d=*(wi+wl-1); if(b=p!=C9&&d==CESC1||d==CESC2)e=spellin(wl,wi);}
  if(128>c&&(y=ds(e)))*x++=y;
  else if(e==CFCONS)RZ(*x++=FCONS(connum(wl-1,wi)))
  else switch(b?0:p){
   default: jsignal3(EVSPELL,w,wi-s); R 0;
   case C9: RZ(*x++=connum(wl,wi));   break;
   case CQ: RZ(*x++=constr(wl,wi));   break;
   case CA: ASSERTN(vnm(wl,wi),EVILNAME,nfs(wl,wi)); RZ(*x++=nfs(wl,wi)); 
 }}
 if(6<=n && TAIA(0,n-1) && ((b=TRBRACE(n-2)) || RPAR&AT(v[n-2])&&TRBRACE(n-3))){I c,j,p,q;
  /* abc=:pqr xyz}abc  or  abc=:pqr (xyz})abc */
  j=2; p=q=0;
  DO(n-j, y=v[j++]; c=AT(y); if(c&LPAR)++p; else if(c&RPAR)--p; if(!p)break;);
  DO(n-j, y=v[j++]; c=AT(y); if(c&LPAR)++q; else if(c&RPAR)--q; if(!q)break;);
  if(!p&&!q&&j>=n-2)v[b+n-3]=ds(CAMIP);
 }else if(5<=n && TAIA(0,2)){
  if(TVERB(3,CCOMMA) && !(AT(v[4])&ADV+CONJ) && 
      !(AT(v[4])&NAME&&(y=symbrd(v[4]),jt->etxn=jt->jerr=0,y)&&AT(y)&ADV+CONJ))
   v[3]=ds(CAPIP);  /* abc=: abc,blah */
  else if(7<=n&&!(AT(v[3])&VERB+ADV+CONJ)){I c,j,q;
   /* abc=:abc xyz}~ pqr */
   j=3; q=0;
   DO(n-j, y=v[j++]; c=AT(y); if(c&LPAR)++q; else if(c&RPAR)--q; if(!q)break;);
   if(!q&&j<n-2&&TRBRACE(j)&&v[1+j]==ds(CTILDE))v[j]=ds(CAMIP);
 }}else if(7<=n && TNAME(0) && TASGN(1) && TNAME(2) && TRBRACE(3) && TVERB(n-2,CLAMIN)){A p,*yv,z1;I c,j,k,m;
  /* abc=: pqr}x,y,:z */
  b=1; m=(n-3)/2; 
  j=4;      DO(m,   if(!TNAME(j)       ){b=0; break;} j+=2;);
  j=5; if(b)DO(m-2, if(!TVERB(j,CCOMMA)){b=0; break;} j+=2;);
  if(b){
   GA(z1,BOX,4,1,0); x=AAV(z1);
   GA(y,BOX,m+3,1,0); yv=AAV(y);
   c=-1; k=AN(v[0]); s=NAV(v[0])->s;
   j=4; DO(m, yv[i]=p=v[j]; j+=2; if(AN(p)&&!memcmp(s,NAV(p)->s,k))c=i;);
   yv[m]=v[2]; RZ(yv[m+1]=sc(c)); yv[m+2]=z;
   x[0]=v[0]; x[1]=v[1]; x[2]=ds(CCASEV); x[3]=y;
   R z1;
 }}
 R z;
}    /* produce boxed list of words suitable for parsing */
                                                            
/* locals in enqueue:                                           */
/* b:  1 iff current word is a primitive spelled with . or :    */
/* c:  first character in current word                          */
/* d:  last  character in current word                          */
/* e:  first character in current word, after spellin           */
/* i:  index of current word                                    */
/* n:  number of words                                          */
/* p:  character type of current character                      */
/* s:  ptr to value part of input string w                      */
/* u:  ptr to value part of word index & length info a          */
/* v:  ptr to value part of z                                   */
/* wi: index of current word in input string                    */
/* wl: length of current word                                   */
/* x:  ptr to result word being built                           */
/* y:  array temp                                               */
/* z:  result array of boxed list of words                      */


F1(jttokens){R enqueue(wordil(w),w);}


#define CHKJ(j)             ASSERT(0<=(j),EVINDEX);
#define EXTZ(T,p)           while(uu<p+u){k=u-(T*)AV(z); RZ(z=ext(0,z)); u=k+(T*)AV(z); uu=(T*)AV(z)+AN(z);}

#define EMIT0c(T,j,i,r,c)   {CHKJ(j); p=(i)-(j); EXTZ(T,1); RZ(*u++=str(p,(j)+wv));}
#define EMIT0b(T,j,i,r,c)   {CHKJ(j); p=(i)-(j); EXTZ(T,1); RZ(*u++=vec(B01,p,(j)+wv));}
#define EMIT0x(T,j,i,r,c)   {CHKJ(j); p=(i)-(j); EXTZ(T,1); GA(x,t0,p*wm,wr,AS(w0));  \
                                *AS(x)=p; MC(AV(x),wv0+wk*(j),wk*p); *u++=x;}
#define EMIT1(T,j,i,r,c)    {CHKJ(j); p=(i)-(j);            cc=(j)+wv; DO(p, *u++=*cc++;);}
#define EMIT1x(T,j,i,r,c)   {CHKJ(j); p=wk*((i)-(j));       MC(u,wv0+j*wk,p); u+=p;}
#define EMIT2(T,j,i,r,c)    {CHKJ(j); p=(i)-(j); EXTZ(T,2); *u++=(j); *u++=p;}
#define EMIT3(T,j,i,r,c)    {CHKJ(j);            EXTZ(T,1);                   *u++=(c)+q*(r);}
#define EMIT4(T,j,i,r,c)    {CHKJ(j); p=(i)-(j); EXTZ(T,3); *u++=(j); *u++=p; *u++=(c)+q*(r);}
#define EMIT5(T,j,x,r,c)    {if(0>(j))i=n;}

#define DO_ONE(T,EMIT) \
 switch(e=v[1]){                                                          \
  case 6:         i=n; break;                                             \
  case 2: case 3: if(0<=vi){EMIT(T,vj,vi,vr,vc); vi=vr=-1;} EMIT(T,j,i,r,c);       j=2==e?i:-1; break;  \
  case 4: case 5: if(r!=vr){if(0<=vi)EMIT(T,vj,vi,vr,vc); vj=j; vr=r; vc=c;} vi=i; j=4==e?i:-1; break;  \
  case 1:         j=i;                                                    \
 }

#define ZVAx                {}
#define ZVA5                {*zv++=i; *zv++=j; *zv++=r; *zv++=c; *zv++=v[0]; *zv++=v[1];}

#define FSMF(T,zt,zr,zm,cexp,EMIT,ZVA)    \
 {T*u,*uu;                                                                  \
  RZ(z=exta((zt),(zr),(zm),1==f||5==f?n:n/3));                              \
  if(1<(zr)){I*s=AS(z); s[1]=(zm); if(1==f&&2<wr)ICPY(1+s,1+AS(w0),wr-1);}  \
  zv=AV(z); u=(T*)zv; uu=u+AN(z);                                           \
  for(;i<n;++i,r=*v){c=(cexp); v=sv+2*(c+r*q); ZVA; DO_ONE(T,EMIT);}        \
  if(6!=e){                                                                 \
   if(0<=d)         {c=d;      v=sv+2*(c+r*q); ZVA; DO_ONE(T,EMIT);}        \
   else{                                                                    \
    if(0<=vi      )EMIT(T,vj,r==vr?n:vi,vr,vc);                             \
    if(r!=vr&&0<=j)EMIT(T,j,n,r,c);                                         \
  }}                                                                        \
  if(5==f)u=(T*)zv;                                                         \
  i=AN(z); AN(z)=j=u-(T*)AV(z); *AS(z)=j/(zm); if(i>3*j)RZ(z=ca(z));        \
 }

static A jtfsmdo(J jt,I f,A s,A m,I*ijrd,A w,A w0){A x,z;C*cc,*wv0;
     I c,d,e,i,j,k,*mv,n,p,q,r,*sv,t,t0,*v,vc,vi,vj,vr,wk,wm,wr,*zv;
 n=IC(w); t=AT(w);
 q=*(1+AS(s));
 sv=AV(s); mv=AV(m);
 i=ijrd[0]; j=ijrd[1]; r=ijrd[2]; d=ijrd[3]; vi=vj=vr=vc=-1;
 if(t&INT){t0=AT(w0); wr=AR(w0); wm=aii(w0); wk=wm*bp(AT(w0)); wv0=CAV(w0);}
 switch(f+(t&B01?0:t&LIT?10:20)){
  case  0: {B *wv=BAV(w); FSMF(A,BOX,1, 1,   wv[i] ,EMIT0b,ZVAx);} break;
  case  1: {B *wv=UAV(w); FSMF(B,B01,1, 1,   wv[i] ,EMIT1, ZVAx);} break;
  case  2: {B *wv=BAV(w); FSMF(I,INT,2, 2,   wv[i] ,EMIT2, ZVAx);} break;
  case  3: {B *wv=BAV(w); FSMF(I,INT,1, 1,   wv[i] ,EMIT3, ZVAx);} break;
  case  4: {B *wv=BAV(w); FSMF(I,INT,2, 3,   wv[i] ,EMIT4, ZVAx);} break;
  case  5: {B *wv=BAV(w); FSMF(I,INT,2, 6,   wv[i] ,EMIT5, ZVA5);} break;

  case 10: {UC*wv=UAV(w); FSMF(A,BOX,1, 1,mv[wv[i]],EMIT0c,ZVAx);} break;
  case 11: {UC*wv=UAV(w); FSMF(C,LIT,1, 1,mv[wv[i]],EMIT1, ZVAx);} break;
  case 12: {UC*wv=UAV(w); FSMF(I,INT,2, 2,mv[wv[i]],EMIT2, ZVAx);} break;
  case 13: {UC*wv=UAV(w); FSMF(I,INT,1, 1,mv[wv[i]],EMIT3, ZVAx);} break;
  case 14: {UC*wv=UAV(w); FSMF(I,INT,2, 3,mv[wv[i]],EMIT4, ZVAx);} break;
  case 15: {UC*wv=UAV(w); FSMF(I,INT,2, 6,mv[wv[i]],EMIT5, ZVA5);} break;

  case 20: {I *wv= AV(w); FSMF(A,BOX,1, 1,   wv[i] ,EMIT0x,ZVAx);} break;
  case 21: {I *wv= AV(w); FSMF(C,t0, wr,wm,  wv[i] ,EMIT1x,ZVAx);} break;
  case 22: {I *wv= AV(w); FSMF(I,INT,2, 2,   wv[i] ,EMIT2, ZVAx);} break;
  case 23: {I *wv= AV(w); FSMF(I,INT,1, 1,   wv[i] ,EMIT3, ZVAx);} break;
  case 24: {I *wv= AV(w); FSMF(I,INT,2, 3,   wv[i] ,EMIT4, ZVAx);} break;
  case 25: {I *wv= AV(w); FSMF(I,INT,2, 6,   wv[i] ,EMIT5, ZVA5);}
 }
 R z;
}

F1(jtfsmvfya){PROLOG;A a,*av,m,s,x,z,*zv;I ad,an,c,e,f,ijrd[4],k,p,q,*sv,*v;
 RZ(a=w);
 ASSERT(1==AR(a),EVRANK);
 ASSERT(BOX&AT(a),EVDOMAIN);
 an=AN(a); av=AAV(a); ad=(I)a*ARELATIVE(a);
 ASSERT(2<=an&&an<=4,EVLENGTH);
 RE(f=i0(AVR(0)));
 ASSERT(0<=f&&f<=5,EVINDEX);
 RZ(s=vi(AVR(1))); sv=AV(s);
 ASSERT(3==AR(s),EVRANK);
 v=AS(s); p=v[0]; q=v[1]; ASSERT(2==v[2],EVLENGTH);
 v=sv; DO(p*q, k=*v++; e=*v++; ASSERT(0<=k&&k<p&&0<=e&&e<=6,EVINDEX););
 ijrd[0]=0; ijrd[1]=-1; ijrd[2]=0; ijrd[3]=-1;
 if(4==an){I d,i,j,n,r;
  RZ(x=vi(AVR(3))); n=AN(x); v=AV(x);
  ASSERT(1==AR(x),EVRANK);
  ASSERT(4>=n,EVLENGTH);
  if(1<=n) ijrd[0]=i=*v++;
  if(2<=n){ijrd[1]=j=*v++; ASSERT(j==-1||0<=j&&j<i,EVINDEX);}
  if(3<=n){ijrd[2]=r=*v++; ASSERT(       0<=r&&r<p,EVINDEX);}
  if(4==n){ijrd[3]=d=*v++; ASSERT(d==-1||0<=d&&d<q,EVINDEX);}
 }
 m=2==an?mtv:AVR(2); c=AN(m);
 ASSERT(1>=AR(m),EVRANK);
 if(!c&&1==AR(m)){   /* m is empty; w must be integer vector */  }
 else if(NUMERIC&AT(m)){
  ASSERT(c==AN(alp),EVLENGTH);
  RZ(m=vi(m)); v=AV(m); DO(c, k=v[i]; ASSERT(0<=k&&k<q,EVINDEX););
 }else ASSERT(BOX&AT(m),EVDOMAIN);
 GA(z,BOX,4,1,0); zv=AAV(z);
 RZ(zv[0]=sc(f)); zv[1]=s; zv[2]=m; RZ(zv[3]=vec(INT,4L,ijrd));
 R z;
}    /* check left argument of x;:y */

static A jtfsm0(J jt,A a,A w,C chka){PROLOG;A*av,m,s,x,w0=w;B b;I ad,c,f,*ijrd,k,md,n,p,q,*v;
 RZ(a&&w);
 if(chka)RZ(a=fsmvfya(a)); 
 av=AAV(a); ad=(I)a*ARELATIVE(a);
 f=i0(AVR(0)); s=AVR(1); m=AVR(2); ijrd=AV(AVR(3));
 n=AN(w); v=AS(s); p=v[0]; q=v[1];
 ASSERT(0<=ijrd[0]&&ijrd[0]<n,EVINDEX);
 b=1>=AR(w)&&(!n||LIT&AT(w)); c=AN(m);
 if(!c&&1==AR(m)){
  ASSERT(1>=AR(w),EVRANK);
  if(!(B01&AT(w))){RZ(w=w0=vi(w)); v=AV(w); DO(n, k=v[i]; ASSERT(0<=k&&k<q,EVINDEX););}
 }else if(NUMERIC&AT(m)){
  ASSERT(b,EVDOMAIN); 
  ASSERT(1>=AR(w),EVRANK);
 }else{A*mv,t,y;I j,r;
  ASSERT(BOX&AT(m),EVDOMAIN);
  RZ(y=raze(m)); r=AR(y); k=AN(y);
  ASSERT(r==AR(w)||r==1+AR(w),EVRANK);
  GA(x,INT,1+k,1,0); v=AV(x); v[k]=c; mv=AAV(m); md=(I)m*ARELATIVE(m); 
  DO(c, j=i; t=AADR(md,mv[i]); if(r&&r==AR(t))DO(*AS(t), *v++=j;) else *v++=j;);
  if(b){RZ(m=from(indexof(y,alp),x)); v=AV(m); DO(AN(alp), k=v[i]; ASSERT(0<=k&&k<q,EVINDEX););}
  else {ASSERT(q>c,EVINDEX); RZ(w=from(indexof(y,w),x));}
 }
 EPILOG(fsmdo(f,s,m,ijrd,w,w0));
}

F2(jtfsm){R fsm0(a,w,1);}
     /* x;:y */

DF1(jtfsmfx){RZ(w&&self); R fsm0(VAV(self)->f,w,0);}
     /* x&;: y */