Rob's S-BASIC: Approach From Ignorance (AFI)

Feel free to talk about any other retro stuff here including Commodore, Sinclair, Atari, Amstrad, Apple... the list goes on!
rje
Posts: 1263
Joined: Mon Apr 27, 2020 10:00 pm
Location: Dallas Area

Rob's S-BASIC: Approach From Ignorance (AFI)

Post by rje »



56 minutes ago, SlithyMatt said:




Yep, but the math expression parsing will require a bit more introspection to break it down. Would be a lot easier if it was something like Forth, as that is closer to how computers actually work.



 

#define         PREC_NONE         0
#define         PREC_ASSIGNMENT   1
#define         PREC_OR           2
#define         PREC_AND          3
#define         PREC_EQUALITY     4
#define         PREC_COMPARISON   5
#define         PREC_TERM         6
#define         PREC_FACTOR       7
#define         PREC_UNARY        8
#define         PREC_CALL         9
#define         PREC_PRIMARY      10

[...later...]
//
//  Pratt Parser data.
//
// typedef    uint8_t ParseRuleNum;
// ParseFn    prefix[MAX_TOKEN_VALUE];
// ParseFn    infix[MAX_TOKEN_VALUE];
// Precedence precedence[MAX_TOKEN_VALUE];
//
// prefixRule[ num ] = NULL | grouping | unary | number
// infixRule[  num ] = NULL | binary
// precedence[ num ] = PREC_NONE | PREC_FACTOR
//
#define ParseRule(n,pf,if,prec) prefixRule[n]=pf;infixRule[n]=if;precedenceRule[n]=prec
void initPrattTable()
{
   ParseRule(TOKEN_RIGHT_PAREN  ,NULL,    NULL,  PREC_NONE);
   ParseRule(TOKEN_LEFT_BRACE   ,NULL,    NULL,  PREC_NONE);
   ParseRule(TOKEN_RIGHT_BRACE  ,NULL,    NULL,  PREC_NONE);
   ParseRule(TOKEN_COMMA        ,NULL,    NULL,  PREC_NONE);
   ParseRule(TOKEN_DOT          ,NULL,    binary,PREC_TERM);
   ParseRule(TOKEN_MINUS        ,unary,   binary,PREC_TERM);
   ParseRule(TOKEN_PLUS         ,NULL,    binary,PREC_TERM);
   ParseRule(TOKEN_SEMICOLON    ,NULL,    NULL,  PREC_NONE);
   ParseRule(TOKEN_SLASH        ,NULL,    binary,PREC_FACTOR);
   ParseRule(TOKEN_MOD          ,NULL,    binary,PREC_FACTOR);
   ParseRule(TOKEN_STAR         ,NULL,    binary,PREC_FACTOR);
   ParseRule(TOKEN_UP           ,NULL,    binary,PREC_FACTOR);
   ParseRule(TOKEN_BANG         ,unary,   NULL,  PREC_NONE);
   ParseRule(TOKEN_BANG_EQUAL   ,NULL,    binary,  PREC_EQUALITY);
   ParseRule(TOKEN_EQUAL        ,NULL,    NULL,  PREC_NONE);
   ParseRule(TOKEN_EQUAL_EQUAL  ,NULL,    binary,  PREC_EQUALITY);
   ParseRule(TOKEN_GREATER      ,NULL,    binary,  PREC_EQUALITY);
   ParseRule(TOKEN_GREATER_EQUAL,NULL,    binary,  PREC_EQUALITY);
   ParseRule(TOKEN_LESS         ,NULL,    binary,  PREC_EQUALITY);
   ParseRule(TOKEN_LESS_EQUAL   ,NULL,    binary,  PREC_EQUALITY);
   ParseRule(TOKEN_IDENTIFIER   ,variable,NULL,  PREC_NONE);
   ParseRule(TOKEN_STRING       ,string,  NULL,  PREC_NONE);
   ParseRule(TOKEN_NUMBER       ,number,  NULL,  PREC_NONE);
   ParseRule(TOKEN_AND          ,NULL,    NULL,  PREC_NONE);
   ParseRule(TOKEN_ELSE         ,NULL,    NULL,  PREC_NONE);
   ParseRule(TOKEN_FALSE        ,literal, NULL,  PREC_NONE);
   ParseRule(TOKEN_FOR          ,NULL,    NULL,  PREC_NONE);
   ParseRule(TOKEN_FUN          ,NULL,    NULL,  PREC_NONE);
   ParseRule(TOKEN_GETTIME      ,literal, NULL,  PREC_NONE);
   ParseRule(TOKEN_TRUE         ,literal, NULL,  PREC_NONE);
   ParseRule(TOKEN_IF           ,NULL,    NULL,  PREC_NONE);
   ParseRule(TOKEN_NIL          ,literal, NULL,  PREC_NONE);
   ParseRule(TOKEN_OR           ,NULL,    NULL,  PREC_NONE);
   ParseRule(TOKEN_PRINT        ,NULL,    NULL,  PREC_NONE);
   ParseRule(TOKEN_RETURN       ,NULL,    NULL,  PREC_NONE);
   ParseRule(TOKEN_WHILE        ,NULL,    NULL,  PREC_NONE);
   ParseRule(TOKEN_EOF          ,NULL,    NULL,  PREC_NONE);
}

rje
Posts: 1263
Joined: Mon Apr 27, 2020 10:00 pm
Location: Dallas Area

Rob's S-BASIC: Approach From Ignorance (AFI)

Post by rje »


And:

static void parsePrecedence(uint8_t precedence)
{
   advance();
   //
   //  The prefix rule MUST exist.  Why?
   //
   if ( parser_previous->type >= TOKEN_START_OF_ERRORS )  // take care of all the error tokens
   {                                                  // (which DO NOT have Pratt entries!)
      return;                                         //
   }                                                  //
   if ( prefixRule[parser_previous->type] == NULL )
   {
      error(TOKEN_ERROR_EXPRESSION_EXPECTED); // "expression expected.");
      return;
   }
   (prefixRule[parser_previous->type])();
   //
   //  If we're at a lower precedence, then advance and call
   //  the infix rule on the previous token, if present.
   //
   while(precedence <= precedenceRule[parser_current->type])
   {
      advance();
      if ( infixRule[parser_previous->type] )
      {
         (infixRule[parser_previous->type])();
      }
   }
}

Post Reply