Scan.borg

Scan.borg


`*-----------------------------------*`
`*          >>>Pico v.1.1<<<         *`
`*            Theo D'Hondt           *`
`*  VUB Programming Technology Lab   *`
`*              (c)1999              *`
`*-----------------------------------*`
`*              scanner              *`
`*       (REFLECTIVE VERSION)        *`
`*-----------------------------------*`

{ AOP_token::  1;
  CAT_token::  2;
  CCL_token::  3;
  CEQ_token::  4;
  COL_token::  5;
  COM_token::  6;
  END_token::  7;
  FRC_token::  8;
  LBC_token::  9;
  LBR_token:: 10;
  LPR_token:: 11;
  MOP_token:: 12;
  NAM_token:: 13;
  NBR_token:: 14;
  PER_token:: 15;
  RBC_token:: 16;
  RBR_token:: 17;
  ROP_token:: 18;
  RPR_token:: 19;
  SMC_token:: 20;
  TXT_token:: 21;
  XOP_token:: 22;

  _SCAN_: void;

  Scan():
    Error('scanner not initialized');

  Init_Scan(Str):
    { aop::  1;
      apo::  2;
      bkq::  3;
      cat::  4;
      col::  5;
      com::  6;
      dgt::  7;
      eol::  8;
      eql::  9;
      exp:: 10;
      ill:: 11;
      lbc:: 12;
      lbr:: 13;
      lpr:: 14;
      ltr:: 15;
      mns:: 16;
      mop:: 17;
      nul:: 18;
      per:: 19;
      pls:: 20;
      quo:: 21;
      rbc:: 22;
      rbr:: 23;
      rop:: 24;
      rpr:: 25;
      smc:: 26;
      wsp:: 27;
      xop:: 28;

      SIZ:: 28;
      NUL::  0;

      ch_tab:: [`nul` ill, ill, ill, ill, ill, ill, ill,
                 ill, wsp, eol, ill, ill, eol, ill, ill,
                 ill, ill, ill, ill, ill, ill, ill, ill,
                 ill, ill, ill, ill, ill, ill, ill, ill,
                 wsp, rop, quo, xop, aop, aop, mop, apo,
                 lpr, rpr, mop, pls, com, mns, per, mop,
                 dgt, dgt, dgt, dgt, dgt, dgt, dgt, dgt,
                 dgt, dgt, col, smc, rop, eql, rop, rop,
                 cat, ltr, ltr, ltr, ltr, exp, ltr, ltr,
                 ltr, ltr, ltr, ltr, ltr, ltr, ltr, ltr,
                 ltr, ltr, ltr, ltr, ltr, ltr, ltr, ltr,
                 ltr, ltr, ltr, lbr, mop, rbr, xop, ltr,
                 bkq, ltr, ltr, ltr, ltr, exp, ltr, ltr,
                 ltr, ltr, ltr, ltr, ltr, ltr, ltr, ltr,
                 ltr, ltr, ltr, ltr, ltr, ltr, ltr, ltr,
                 ltr, ltr, ltr, lbc, aop, rbc, rop, ill,
                 ill, ill, ill, ill, ill, ill, ill, ill,
                 ill, ill, ill, ill, ill, ill, ill, ill,
                 ill, ill, ill, ill, ill, ill, ill, ill,
                 ill, ill, ill, ill, ill, ill, ill, ill,
                 ill, ill, ill, ill, ill, ill, ill, ill,
                 ill, ill, ill, ill, ill, ill, ill, ill,
                 ill, ill, ill, ill, ill, ill, ill, ill,
                 ill, ill, ill, ill, ill, ill, ill, ill,
                 ill, ill, ill, ill, ill, ill, ill, ill,
                 ill, ill, ill, ill, ill, ill, ill, ill,
                 ill, ill, ill, ill, ill, ill, ill, ill,
                 ill, ill, ill, ill, ill, ill, ill, ill,
                 ill, ill, ill, ill, ill, ill, ill, ill,
                 ill, ill, ill, ill, ill, ill, ill, ill,
                 ill, ill, ill, ill, ill, ill, ill, ill,
                 ill, ill, ill, ill, ill, ill, ill, ill ];

      INP: void;
      POS: void;
      HLD: void;
      CHR: void;

      skip_ch()::
        CHR:= if((POS:= POS+1) > size(INP),
                NUL,
                ord(INP[POS]));

      get_cat()::
        if(CHR = NUL, nul, ch_tab[CHR]);

      next_ch(Tkn)::
        { skip_ch();
          Tkn };

      freeze()::
        HLD:= POS-1;

      capture_name(Tkn)::
        { t[POS-HLD-1]: INP[HLD:= HLD+1];
          _SCAN_:= implode(t);
          Tkn };

      capture_text(Tkn)::
        { t[POS-HLD-2]: INP[HLD:= HLD+1];
          _SCAN_:= implode(t);
          Tkn };

      capture_number(Tkn)::
        { t[POS-HLD-1]: INP[HLD:= HLD+1];
          _SCAN_:= number(implode(t));
          Tkn };

      check(allowed)::
        allowed[get_cat()];

      mask@list::
        { msk[SIZ]: false;
          for(k: 1, k <= size(list), k:= k+1,
            msk[list[k]]:= true);
          msk };

      apo_allowed:: mask(apo);
      apx_allowed:: mask(apo,eol,nul);
      bkq_allowed:: mask(bkq,eol,nul);
      col_allowed:: mask(col);
      dgt_allowed:: mask(dgt);
      eql_allowed:: mask(eql);
      exp_allowed:: mask(exp);
      nam_allowed:: mask(dgt,exp,ltr);
      opr_allowed:: mask(aop,eql,mns,mop,pls,rop,xop);
      per_allowed:: mask(per);
      quo_allowed:: mask(quo);
      qux_allowed:: mask(eol,nul,quo);
      sgn_allowed:: mask(mns,pls);
      wsp_allowed:: mask(eol,nul,wsp);

      operator(Tkn)::
        { freeze();
          until(!check(opr_allowed), skip_ch());
          capture_name(Tkn) };

      exponent()::
        { skip_ch();
          if(check(sgn_allowed), skip_ch());
          if(!check(dgt_allowed), Error('digit required'));
          until(check(!dgt_allowed), skip_ch());
          capture_number(FRC_token) };

      fraction()::
        { skip_ch();
          if(!check(dgt_allowed), Error('digit required'));
          until(!check(dgt_allowed), skip_ch());
          if(check(exp_allowed),
            exponent(),
            capture_number(FRC_token)) };

      aop_fun()::
        operator(AOP_token);

      apo_fun()::
        { skip_ch();
          freeze();
          while(!check(apx_allowed), skip_ch());
          if(!check(apo_allowed), Error("' required"));
          capture_text(next_ch(TXT_token)) };

      bkq_fun()::
        { skip_ch();
          while(!check(bkq_allowed), skip_ch());
          skip_ch();
          Scan() };

      cat_fun()::
        next_ch(CAT_token);

      col_fun()::
        { skip_ch();
          if(check(eql_allowed),
            next_ch(CEQ_token),
            if(check(col_allowed),
              next_ch(CCL_token),
              COL_token)) };

      com_fun()::
        next_ch(COM_token);

      dgt_fun()::
        { freeze();
          until(!check(dgt_allowed), skip_ch());
          if(check(per_allowed),
            fraction(),
            if(check(exp_allowed),
              exponent(),
              capture_number(NBR_token))) };

      ill_fun()::
        { Error('illegal character');
          END_token };

      lbc_fun()::
        next_ch(LBC_token);

      lbr_fun()::
        next_ch(LBR_token);

      lpr_fun()::
        next_ch(LPR_token);

      ltr_fun()::
        { freeze();
          until(!check(nam_allowed), skip_ch());
          capture_name(NAM_token) };

      mop_fun()::
        operator(MOP_token);

      nul_fun()::
        next_ch(END_token);

      per_fun()::
        next_ch(PER_token);

      quo_fun()::
        { skip_ch();
          freeze();
          while(!check(qux_allowed), skip_ch());
          if(!check(quo_allowed), Error('" required'));
          capture_text(next_ch(TXT_token)) };

      rbc_fun()::
        next_ch(RBC_token);

      rbr_fun()::
        next_ch(RBR_token);

      rop_fun()::
        operator(ROP_token);

      rpr_fun()::
        next_ch(RPR_token);

      smc_fun()::
        next_ch(SMC_token);

      wsp_fun()::
        { skip_ch();
          Scan() };

      xop_fun()::
        operator(XOP_token);

      fun_tab:: [ aop_fun,
                  apo_fun,
                  bkq_fun,
                  cat_fun,
                  col_fun,
                  com_fun,
                  dgt_fun,
                  wsp_fun,
                  rop_fun,
                  ltr_fun,
                  ill_fun,
                  lbc_fun,
                  lbr_fun,
                  lpr_fun,
                  ltr_fun,
                  aop_fun,
                  mop_fun,
                  nul_fun,
                  per_fun,
                  aop_fun,
                  quo_fun,
                  rbc_fun,
                  rbr_fun,
                  rop_fun,
                  rpr_fun,
                  smc_fun,
                  wsp_fun,
                  xop_fun ];

      Init_Scan(Str):=
        { INP:= explode(Str);
          POS:= 0;
          skip_ch();
          void };

      Scan():=
        { fun: fun_tab[get_cat()];
          fun() };

      Init_Scan(Str) };

  display('scanner ...... installed', eoln) }