pike.git / lib / modules / Parser.pmod / Tabular.pike

version» Context lines:

pike.git/lib/modules/Parser.pmod/Tabular.pike:1:   //! This is a parser for line and block oriented data.   //! It provides a flexible record-description language to support   //! character/column/delimiter-organised records.   //!   //! @seealso   //! @[Parser.LR]      #pike __REAL_VERSION__      private Stdio.FILE in; - private array alread=({}); - private mapping|array fms; - private int eol; +    private int prefetch=1024; // TODO: Document and make this available    // through compile(). -  + private String.Buffer alread=String.Buffer(prefetch); + private mapping|array fms; + private int eol;   private Regexp simple=Regexp("^[^[\\](){}<>^$|+*?\\\\]+$");   private Regexp emptyline=Regexp("^[ \t\v\r\x1a]*$");   private mixed severity=1;   private int verb=0;   private int recordcount=1;      //! This function initialises the parser specifying the input stream or   //! string, the format to be used (either precompiled or not),   //! and the verbosity level.   //!
pike.git/lib/modules/Parser.pmod/Tabular.pike:62:    (in=Stdio.FILE())->assign(input);    else    in=input;   }      #if 0 // Currently unused function   private int getchar()   { int c=in->getchar();    if(c<0)    throw(severity); -  if(catch(alread[sizeof(alread)-1]+=({c}))) -  alread+=({({c})}); +  alread->putchar(c);    return c;   }   #endif      private string read(int n)   { string s;    s=in->read(n); -  alread+=({s}); +  alread->add(s);    if(sizeof(s)!=n)    throw(severity);    return s;   }      private string gets(int n)   { string s;    if(n)    { s=read(n);    if(has_value(s,"\n"))    throw(severity);    }    else    { s=in->gets();    if(!s)    throw(severity); -  alread+=({s,"\n"}); +  alread->add(s);alread->putchar('\n');    if(has_suffix(s,"\r"))    s=s[..<1];    eol=1;    }    return s;   }      private class checkpoint - { private array oldalread; + { private string oldalread;       void create() -  { oldalread=alread; -  alread=({}); +  { oldalread=alread->get();    }       final void release() -  { alread=oldalread+alread; +  { string s=alread->get(); +  alread->add(oldalread); +  alread->add(s);    oldalread=0;    }       protected void destroy()    { if(oldalread) -  { string back=alread*""; +  { string back=alread->get();    if(sizeof(back))    { in->unread(back);    if(verb<0)    { back-="\n";    if(sizeof(back))    werror("Backtracking %O\n",back);    }    } -  alread=oldalread; +  alread->add(oldalread);    }    }   }      #define FETCHAR(c,buf,i) (catch((c)=(buf)[(i)++])?((c)=-1):(c))      private mapping getrecord(array fmt,int found)   { mapping ret=([]),options;    if(stringp(fmt[0]))    { options=(["name":fmt[0]]);
pike.git/lib/modules/Parser.pmod/Tabular.pike:150:    throw(severity); // early exit, already found one    }    else if(options->mandatory)    severity=2;    if(verb<0)    werror("Checking record %d for %O\n",recordcount,options->name);    eol=0;    foreach(fmt;int fi;array|mapping m)    { if(fi<2)    continue; -  string|array|mapping value; +  string value;    if(arrayp(m))    { array field=m;    fmt[fi]=m=(["name":field[0]]);    mixed nm=field[1];    if(!mappingp(nm))    { if(arrayp(nm)) -  value=getrecord(nm,found); +  ret+=getrecord(nm,found);    else    m+=([(intp(nm)?"width":(stringp(nm)?"match":"delim")):nm]);    if(sizeof(field)>2)    m+=field[2];    }    fmt[fi]=m;    }    if(eol)    throw(severity);    if(!zero_type(m->width))    value=gets(m->width);    if(m->delim)    { multiset delim=m->delim; -  if(sizeof(delim-(<',',';','\t',' '>))) -  { array word; -  int i; +  int i,pref=m->prefetch || prefetch; +  String.Buffer word=String.Buffer(pref);    string buf,skipclass; -  skipclass="%[^"+(string)indices(delim)+"\r\x1a\n]"; -  value=word=({}); +  skipclass="%[^"+(string)indices(delim)+"\"\r\x1a\n]"; +  if(sizeof(delim-(<',',';','\t',' '>)))   delimready:    for(;;)    { i=0; -  buf=in->read(m->prefetch || prefetch); +  buf=in->read(pref);    int c;    FETCHAR(c,buf,i);    while(c>=0)    { if(delim[c])    break delimready;    else switch(c)    { default:    { string s;    sscanf(buf[--i..],skipclass,s); -  value+=({word,s}); -  word=({}); +  word->add(s);    i+=sizeof(s);    break;    }    case '\n':    eol=1;    break delimready;    case '\r':case '\x1a':;    }    FETCHAR(c,buf,i);    }    if(!sizeof(buf)) -  { value+=({word}); +     throw(severity); -  +  alread->add(buf);    } -  alread+=({buf}); -  } -  value+=({word}); -  alread+=({buf[..i-1]}); -  in->unread(buf[i..]); -  value=value*""; -  } +     else -  { array word; -  int leadspace=1,inquotes=0,i; -  string buf,skipclass; -  skipclass="%[^"+(string)indices(delim)+"\"\r\x1a\n]"; -  value=word=({}); +  { int leadspace=1,inquotes=0;   csvready:    for(;;)    { i=0; -  buf=in->read(m->prefetch || prefetch); +  buf=in->read(pref);    int c;    FETCHAR(c,buf,i);    while(c>=0)    { if(delim[c])    { if(!inquotes)    break csvready; -  word+=({c}); +  word->putchar(c);    }    else switch(c)    { case '"':leadspace=0;    if(!inquotes)    inquotes=1;    else if(FETCHAR(c,buf,i)=='"') -  word+=({c}); +  word->putchar(c);    else    { inquotes=0;    continue;    }    break;    default:leadspace=0;    case ' ':case '\t':    if(!leadspace)    { string s;    sscanf(buf[--i..],skipclass,s); -  value+=({word,s}); -  word=({}); +  word->add(s);    i+=sizeof(s);    }    break;    case '\n':    if(!inquotes)    { eol=1;    break csvready;    } -  word+=({c}); +  word->putchar('\n');    case '\r':case '\x1a':;    }    FETCHAR(c,buf,i);    }    if(!sizeof(buf)) -  { value+=({word}); +     throw(severity); -  +  alread->add(buf);    } -  alread+=({buf}); +     } -  value+=({word}); -  alread+=({buf[..i-1]}); +  alread->add(buf[..i-1]);    in->unread(buf[i..]); -  value=value*""; +  value=word->get();    } -  } +     if(m->match)    { Regexp rgx;    if(stringp(m->match))    { if(!value && simple->match(m->match))    { m->width=sizeof(m->match);    value=gets(m->width);    }    m->match=Regexp("^("+m->match+")"+(value?"$":""));    }    rgx=m->match;    if(value)    { if(!rgx->match(value))    { if(verb<-3)    werror(sprintf("Mismatch %O!=%O\n",value,rgx)    -"Regexp.SimpleRegexp");    throw(severity);    }    }    else    { string buf=in->read(m->prefetch || prefetch); -  if(!buf || !(value=rgx->split(buf))) -  { alread+=({buf}); +  { array spr; +  if(!buf || !(spr=rgx->split(buf))) +  { alread->add(buf);    if(verb<-3)    werror(sprintf("Mismatch %O!=%O\n",buf[..32],rgx)    -"Regexp.SimpleRegexp");    throw(severity);    } -  in->unread(buf[sizeof(value=value[0])..]); -  alread+=({value}); +  in->unread(buf[sizeof(value=spr[0])..]); +  } +  alread->add(value);    value-="\r";    if(has_suffix(value,"\n"))    value=value[..<1];    }    }    if(!m->drop)    ret[m->name]=value;    }    if(!eol && gets(0)!="")    throw(severity);