Y_Less

Parser skeleton.

Aug 19th, 2013
449
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Pawn 7.33 KB | None | 0 0
  1. // Tokeniser.  Read text and convert it to tokens for simple processing.
  2.  
  3.  
  4. enum e_TOKEN_TYPE
  5. {
  6.     e_TOKEN_TYPE_NONE,
  7.     e_TOKEN_TYPE_STRING,
  8.     e_TOKEN_TYPE_FLOAT,
  9.     // These two are distinct for simplicity.
  10.     e_TOKEN_TYPE_FUNC,
  11.     e_TOKEN_TYPE_VAR,
  12.     e_TOKEN_TYPE_NUM,
  13.     e_TOKEN_TYPE_BOOL,
  14.     e_TOKEN_TYPE_OP,
  15. }
  16.  
  17. enum e_TOKEN_OP
  18. {
  19.     e_TOKEN_OP_NONE,
  20.     e_TOKEN_OP_ASSIGN, // '='
  21.     e_TOKEN_OP_EQUALS, // '=='
  22.     e_TOKEN_OP_LTE, // '<='
  23.     e_TOKEN_OP_GTE, // '>='
  24.     e_TOKEN_OP_LESS, // '<'
  25.     e_TOKEN_OP_GREATER, // '>'
  26.     e_TOKEN_OP_NOT, // '!'
  27.     e_TOKEN_OP_NEQ, // '!='
  28.     e_TOKEN_OP_INV, // '~'
  29.     e_TOKEN_OP_INV_ASS, // '~='
  30.     e_TOKEN_OP_ADD, // '+'
  31.     e_TOKEN_OP_ADD_ASS, // '+='
  32.     e_TOKEN_OP_SUB, // '-'
  33.     e_TOKEN_OP_SUB_ASS, // '-='
  34.     e_TOKEN_OP_MUL, // '*'
  35.     e_TOKEN_OP_MUL_ASS, // '*='
  36.     e_TOKEN_OP_DIV, // '/'
  37.     e_TOKEN_OP_DIV_ASS, // '/='
  38.     e_TOKEN_OP_MOD, // '%'
  39.     e_TOKEN_OP_MOD_ASS, // '%='
  40.     e_TOKEN_OP_XOR, // '^'
  41.     e_TOKEN_OP_XOR_ASS, // '^='
  42.     e_TOKEN_OP_LAND, // '&'
  43.     e_TOKEN_OP_LAND_ASS, // '&='
  44.     e_TOKEN_OP_LOR, // '|'
  45.     e_TOKEN_OP_LOR_ASS, // '|='
  46.     e_TOKEN_OP_RSHIFT, // '>>'
  47.     e_TOKEN_OP_RSHIFT_ASS, // '>>='
  48.     e_TOKEN_OP_SHIFT, // '>>>'
  49.     e_TOKEN_OP_SHIFT_ASS, // '>>>='
  50.     e_TOKEN_OP_LSHIFT, // '<<'
  51.     e_TOKEN_OP_LSHIFT_ASS, // '<<='
  52.     e_TOKEN_OP_AND, // '&&'
  53.     e_TOKEN_OP_OR, // '||'
  54.     e_TOKEN_OP_OP_BRACKET, // '('
  55.     e_TOKEN_OP_CL_BRACKET, // ')'
  56.     e_TOKEN_OP_OP_BRACE, // '{'
  57.     e_TOKEN_OP_CL_BRACE, // '}'
  58.     e_TOKEN_OP_OP_SQUARE, // '['
  59.     e_TOKEN_OP_CL_SQUARE, // ']'
  60.     e_TOKEN_OP_CL_INC, // '++'
  61.     e_TOKEN_OP_CL_DEC, // '--'
  62.     e_TOKEN_OP_CL_ELIPSIS, // '...'
  63.     e_TOKEN_OP_CL_CONCAT, // '..'
  64.     e_TOKEN_OP_CL_HASH, // '#'
  65.     e_TOKEN_OP_CL_PAAMAYIM, // '::'
  66.     e_TOKEN_OP_CL_DQUOTE, // '"'
  67.     e_TOKEN_OP_CL_QUOTE, // '''
  68. }
  69.  
  70. enum E_TOKEN
  71. {
  72.     e_TOKEN_TYPE:E_TOKEN_TYPE,
  73.     Float:E_TOKEN_FLOAT_VAL = 1,
  74.     bool:E_TOKEN_BOOL_VAL = 1,
  75.     e_TOKEN_OP:E_TOKEN_OP = 1,
  76.     E_TOKEN_FUNC_PTR = 1,
  77.     E_TOKEN_SYM_PTR = 1,
  78.     E_TOKEN_NUM_VAL = 1
  79. }
  80.  
  81. static stock
  82.     ISI_gInputLine[512],
  83.     ISI_gInputLen;
  84.     ISI_gInputPtr;
  85.  
  86. static stock Parser_GetSymType(const name[], &e_TOKEN_TYPE:t, &ptr)
  87. {
  88. }
  89.  
  90. static stock Parser_Peek()
  91. {
  92.     return ISI_gInputLine[ISI_gInputPtr];
  93. }
  94.  
  95. #define Parser_IsWhitespace((%0)) ('\0' <= (%0) <= ' ')
  96.  
  97. static stock Parser_SkipWhitespace()
  98. {
  99.     while ('\0' < ISI_gInputLine[ISI_gInputPtr] <= ' ') ++ISI_gInputPtr;
  100. }
  101.  
  102. #define PARSER_DO_OP_1(%9,%0)          else if (p0 == %0) ret[e_TOKEN_TYPE_OP] = (%9), len = 1;
  103. #define PARSER_DO_OP_2(%9,%0,%1)       else if (p0 == %0 && p1 == %1) ret[e_TOKEN_TYPE_OP] = (%9), len = 2;
  104. #define PARSER_DO_OP_3(%9,%0,%1,%2)    else if (p0 == %0 && p1 == %1 && p2 == %2) ret[e_TOKEN_TYPE_OP] = (%9), len = 3;
  105. #define PARSER_DO_OP_4(%9,%0,%1,%2,%3) else if (p0 == %0 && p1 == %1 && p2 == %2 && p3 == %3) ret[e_TOKEN_TYPE_OP] = (%9), len = 4;
  106.  
  107. static stock Parser_GetOp()
  108. {
  109.     new
  110.         ret[E_TOKEN] = {e_TOKEN_TYPE_OP, 0},
  111.         len = ISI_gInputLen - ISI_gInputPtr,
  112.         p0, p1, p2, p3;
  113.     if (len > 0) {
  114.         p0 = ISI_gInputLine[ISI_gInputPtr + 0];
  115.         if (len > 1) {
  116.             p1 = ISI_gInputLine[ISI_gInputPtr + 1];
  117.             if (len > 2) {
  118.                 p2 = ISI_gInputLine[ISI_gInputPtr + 2];
  119.                 if (len > 3) {
  120.                     p3 = ISI_gInputLine[ISI_gInputPtr + 3];
  121.                     }}}}
  122.     else
  123.     {
  124.         Parser_Error("Unexpected end of input.");
  125.         return ret;
  126.     }
  127.     // Should really use a "trie" here, but don't - too complex for now.
  128.     if ((len = 0)) return ret; // Placeholder "if" - leave it!
  129.     PARSER_DO_OP_4(e_TOKEN_OP_SHIFT_ASS, '>', '>', '>', '=')
  130.     PARSER_DO_OP_3(e_TOKEN_OP_RSHIFT_ASS, '>', '>', '=')
  131.     PARSER_DO_OP_3(e_TOKEN_OP_SHIFT, '>', '>', '>')
  132.     PARSER_DO_OP_3(e_TOKEN_OP_LSHIFT_ASS, '<', '<', '=')
  133.     PARSER_DO_OP_3(e_TOKEN_OP_CL_ELIPSIS, '.', '.', '.')
  134.     PARSER_DO_OP_2(e_TOKEN_OP_EQUALS, '=', '=')
  135.     PARSER_DO_OP_2(e_TOKEN_OP_LTE, '<', '=')
  136.     PARSER_DO_OP_2(e_TOKEN_OP_GTE, '>', '=')
  137.     PARSER_DO_OP_2(e_TOKEN_OP_NEQ, '!', '=')
  138.     PARSER_DO_OP_2(e_TOKEN_OP_INV_ASS, '~', '=')
  139.     PARSER_DO_OP_2(e_TOKEN_OP_ADD_ASS, '+', '=')
  140.     PARSER_DO_OP_2(e_TOKEN_OP_SUB_ASS, '-', '=')
  141.     PARSER_DO_OP_2(e_TOKEN_OP_MUL_ASS, '*', '=')
  142.     PARSER_DO_OP_2(e_TOKEN_OP_DIV_ASS, '/', '=')
  143.     PARSER_DO_OP_2(e_TOKEN_OP_MOD_ASS, '%', '=')
  144.     PARSER_DO_OP_2(e_TOKEN_OP_XOR_ASS, '^', '=')
  145.     PARSER_DO_OP_2(e_TOKEN_OP_LAND_ASS, '&', '=')
  146.     PARSER_DO_OP_2(e_TOKEN_OP_LOR_ASS, '|', '=')
  147.     PARSER_DO_OP_2(e_TOKEN_OP_RSHIFT, '>', '>')
  148.     PARSER_DO_OP_2(e_TOKEN_OP_LSHIFT, '<', '<')
  149.     PARSER_DO_OP_2(e_TOKEN_OP_AND, '&', '&')
  150.     PARSER_DO_OP_2(e_TOKEN_OP_OR, '|', '|')
  151.     PARSER_DO_OP_2(e_TOKEN_OP_CL_PAAMAYIM, ':', ':')
  152.     PARSER_DO_OP_2(e_TOKEN_OP_CL_INC, '+', '+')
  153.     PARSER_DO_OP_2(e_TOKEN_OP_CL_DEC, '-', '-')
  154.     PARSER_DO_OP_2(e_TOKEN_OP_CL_CONCAT, '.', '.')
  155.     PARSER_DO_OP_1(e_TOKEN_OP_ASSIGN, '=')
  156.     PARSER_DO_OP_1(e_TOKEN_OP_LESS, '<')
  157.     PARSER_DO_OP_1(e_TOKEN_OP_GREATER, '>')
  158.     PARSER_DO_OP_1(e_TOKEN_OP_NOT, '!')
  159.     PARSER_DO_OP_1(e_TOKEN_OP_INV, '~')
  160.     PARSER_DO_OP_1(e_TOKEN_OP_ADD, '+')
  161.     PARSER_DO_OP_1(e_TOKEN_OP_SUB, '-')
  162.     PARSER_DO_OP_1(e_TOKEN_OP_MUL, '*')
  163.     PARSER_DO_OP_1(e_TOKEN_OP_DIV, '/')
  164.     PARSER_DO_OP_1(e_TOKEN_OP_MOD, '%')
  165.     PARSER_DO_OP_1(e_TOKEN_OP_XOR, '^')
  166.     PARSER_DO_OP_1(e_TOKEN_OP_LAND, '&')
  167.     PARSER_DO_OP_1(e_TOKEN_OP_LOR, '|')
  168.     PARSER_DO_OP_1(e_TOKEN_OP_OP_BRACKET, '(')
  169.     PARSER_DO_OP_1(e_TOKEN_OP_CL_BRACKET, ')')
  170.     PARSER_DO_OP_1(e_TOKEN_OP_OP_BRACE, '{')
  171.     PARSER_DO_OP_1(e_TOKEN_OP_CL_BRACE, '}')
  172.     PARSER_DO_OP_1(e_TOKEN_OP_OP_SQUARE, '[')
  173.     PARSER_DO_OP_1(e_TOKEN_OP_CL_SQUARE, ']')
  174.     PARSER_DO_OP_1(e_TOKEN_OP_CL_HASH, '#')
  175.     PARSER_DO_OP_1(e_TOKEN_OP_CL_DQUOTE, '"')
  176.     PARSER_DO_OP_1(e_TOKEN_OP_CL_QUOTE, '\'')
  177.     if (len)
  178.     {
  179.         // Found an op.
  180.         ISI_gInputPtr += len;
  181.     }
  182.     else
  183.     {
  184.         Parser_Error("Unexpected input at (%d).", ISI_gInputPtr);
  185.         // Skip one character and try again.
  186.         ++ISI_gInputPtr;
  187.     }
  188.     return ret;
  189. }
  190.  
  191. #undef PARSER_DO_OP_1
  192. #undef PARSER_DO_OP_2
  193. #undef PARSER_DO_OP_3
  194. #undef PARSER_DO_OP_4
  195.  
  196. static stock Parser_GetNextToken()
  197. {
  198.     new ret[E_TOKEN] = {e_TOKEN_TYPE_NONE, 0};
  199.     Parser_SkipWhitespace();
  200.     switch (Parser_Peek())
  201.     {
  202.         case '\0': return ret;
  203.         case '0' .. '9': return Parser_GetNumber();
  204.         case 'a' .. 'z', 'A' .. 'Z', '_', '@': return Parser_GetSymbol();
  205.         case '"': return Parser_GetString();
  206.         case '\'': return Parser_GetChar();
  207.         default: return Parser_GetOp();
  208.     }
  209. }
  210.  
  211. static stock Parser_GetNumber()
  212. {
  213.     new
  214.         num = 0,
  215.         ch,
  216.         ptr = ISI_gInputPtr;
  217.     if (ISI_gInputLine[ptr] == '0')
  218.     {
  219.         // Hex, binary, or octal (or 0).
  220.         switch ((ch = ISI_gInputLine[++ptr]))
  221.         {
  222.             case 'x', 'X': return Parser_DoHex(); // Hex
  223.             case 'b', 'B': return Parser_DoBinary(); // Binary
  224.             case 'e', 'E', '.': return Parser_DoFloat(); // Float
  225.             case '0' .. '9':
  226.             {
  227.                 new
  228.                     bool:oct = ('0' <= ch <= '7');
  229.                 num = ch - '0';
  230.                 for ( ; ; )
  231.                 {
  232.                     switch ((ch = ISI_gInputLine[++ptr]))
  233.                     {
  234.                         case '0' .. '7': num = num * 10 + (ch - '0'), oct &= true;
  235.                         case 'e', 'E', '.': return Parser_DoFloat(); // Float
  236.                         case '8', '9': num = num * 10 + (ch - '0'), oct = false;
  237.                         default: break;
  238.                     }
  239.                 }
  240.                 if (oct) return Parser_DoOct();
  241.             }
  242.         }
  243.     }
  244.     else
  245.     {
  246.         // Decimal or float.
  247.         // Lookahead.
  248.         num = ISI_gInputLine[ptr] - '0';
  249.         for ( ; ; )
  250.         {
  251.             switch ((ch = ISI_gInputLine[++ptr]))
  252.             {
  253.                 case '0' .. '9': num = num * 10 + (ch - '0');
  254.                 case 'e', 'E', '.': return Parser_DoFloat();
  255.                 default: break;
  256.             }
  257.         }
  258.     }
  259.     new
  260.         ret[E_TOKEN] = {e_TOKEN_TYPE_NUM, num};
  261.     // Decimal (default).
  262.     ISI_gInputPtr = ptr;
  263.     return ret;
  264. }
Advertisement
Add Comment
Please, Sign In to add comment