Read.borg

Read.borg


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

{ Read(Str):
    { BGN:: Make_TXT('begin');
      TAB:: Make_TXT('tab');
      MSG:: [ 'additive operator',
              'application',
              'declaration',
              'assignment',
              'definition',
              'comma',
              'end of text',
              'fraction',
              'left brace',
              'left bracket',
              'left parenthesis',
              'multiplicative operator',
              'name',
              'number',
              'period',
              'right brace',
              'right bracket',
              'relational operator',
              'right parenthesis',
              'semicolon',
              'text',
              'exponentiation operator' ];

      TKN: void;

      error_message@any:
        Error('Unexpected ' + MSG[TKN]);

      skip()::
        TKN:= Scan();

      next(Dat)::
        { skip();
          Dat };

      expression():
        void;

      operand():
        void;

      operation(Opr, Tkn)::
        { opd: Opr();
          while(TKN = Tkn,
            { opr: next(_SCAN_);
              arg: [ opd, Opr() ];
              opd:= Make_APL(Make_TXT(opr), Make_TAB(arg)) });
          opd };

      factor()::
        operation(operand, XOP_token);

      term()::
        operation(factor, MOP_token);

      comparand()::
        operation(term, AOP_token);

      invocation()::
        operation(comparand, ROP_token);

      list(Sep, Trm)::
        { loop(count):
            { exp: expression();
              tab: if(TKN = Sep,
                     { skip();
                       loop(count+1) },
                     if(TKN = Trm,
                       next(tab[count]: void),
                       error_message()));
              tab[count]:= exp;
              tab };
          Make_TAB(loop(1)) };

      number()::
        Make_NBR(next(_SCAN_));

      fraction()::
        Make_FRC(next(_SCAN_));

      text()::
        Make_TXT(next(_SCAN_));

      application(Nam)::
        { skip();
          if(TKN = RPR_token,
            Make_APL(Make_TXT(Nam), next(_EMPTY_)),
            Make_APL(Make_TXT(Nam), list(COM_token, RPR_token))) };

      apply(Nam)::
        { skip();
          inv: invocation();
          Make_APL(Make_TXT(Nam), inv) };

      tabulation(Nam)::
        { skip();
          Make_TBL(Make_TXT(Nam), list(COM_token, RBR_token)) };

      message(Nam)::
        { skip();
          Make_MES(Make_TXT(Nam), invocation()) };

      reference(Nam)::
        Make_REF(Make_TXT(Nam));

      var_case:: case(CAT_token <> apply,
                      LBR_token <> tabulation,
                      LPR_token <> application,
                      PER_token <> message,
                           void <> reference);

      name()::
        { var: next(_SCAN_);
          cas: var_case(TKN);
          cas(var) };

      prefix(Nam)::
        { arg: [ operand() ];
          Make_APL(Make_TXT(Nam), Make_TAB(arg)) };

      opr_case:: case(AOP_token <> prefix,
                      CAT_token <> apply,
                      FRC_token <> prefix,
                      LBR_token <> tabulation,
                      LPR_token <> application,
                      MOP_token <> prefix,
                      NAM_token <> prefix,
                      NBR_token <> prefix,
                      PER_token <> message,
                      ROP_token <> prefix,
                      TXT_token <> prefix,
                      XOP_token <> prefix,
                           void <> reference);

      operator()::
        { opr: next(_SCAN_);
          cas: opr_case(TKN);
          cas(opr) };

      parentheses()::
        { skip();
          exp: expression();
          if(TKN != RPR_token, error_message());
          skip();
          exp };

      braces()::
        { skip();
          Make_APL(BGN, list(SMC_token, RBC_token)) };

      brackets()::
        { skip();
          if(TKN = RBR_token,
            Make_APL(TAB, next(_EMPTY_)),
            Make_APL(TAB, list(COM_token, RBR_token))) };

      opd_case:: case(AOP_token <> operator,
                      FRC_token <> fraction,
                      LBC_token <> braces,
                      LBR_token <> brackets,
                      LPR_token <> parentheses,
                      MOP_token <> operator,
                      NAM_token <> name,
                      NBR_token <> number,
                      ROP_token <> operator,
                      TXT_token <> text,
                      XOP_token <> operator,
                           void <> error_message);

      operand():=
        { cas: opd_case(TKN);
          cas() };

      identity(Inv)::
        Inv;

      definition(Inv)::
        Make_DEF(next(Inv), expression());

      declaration(Inv)::
        Make_DCL(next(Inv), expression());

      assignment(Inv)::
        Make_SET(next(Inv), expression());

      exp_case:: case(CEQ_token <> assignment,
                      CCL_token <> declaration,
                      COL_token <> definition,
                           void <> identity);

      expression():=
        { inv: invocation();
          cas: exp_case(TKN);
          cas(inv) };

      Read(Str):=
        { Init_Scan(Str);
          TKN := Scan();
          expression() };

      Read(Str) };

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