]> git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - parser.c
Parser is now tail recursive. Implemented parse tree, self-cleaning on failure
[xonotic/darkplaces.git] / parser.c
index b6ecc083fc6e1829dcc4529753ea2c870af0219f..b83f7c5ffe2a0f2eb6753e64eb3f0550607e15bc 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -19,6 +19,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */
 
 #include "darkplaces.h"
+#include "token.h"
 #include "parser.h"
 
 jmp_buf parse_error;
@@ -49,32 +50,29 @@ DP_FUNC_NORETURN void Parse_Error(struct qparser_state_s *state, qparser_err_t e
 }
 
 // Advance forward in the stream as many times as 'count', cleanly.
-void Parse_Next(struct qparser_state_s *state, size_t count)
+void Parse_Next(struct qparser_state_s *state, int count)
 {
-       state->col += count;
-       state->pos += count;
+       const char *next = Token_Next(state->pos, count);
 
-       if(!*state->pos)
+       if(next)
+       {
+               state->pos = next;
+               state->col += count;
+       }
+       else
                Parse_Error(state, PARSE_ERR_EOF, NULL);
 }
 
 // Skips newlines, and handles different line endings.
 static qbool Parse_Newline(struct qparser_state_s *state)
 {
-       if(*state->pos == '\n')
-               goto newline;
-       if(*state->pos == '\r')
+       if(Token_Newline(&state->pos))
        {
-               if(*state->pos + 1 == '\n')
-                       state->pos++;
-               goto newline;
+               state->col = 1;
+               state->line++;
+               return true;
        }
        return false;
-newline:
-       state->col = 1;
-       state->line++;
-       state->pos++;
-       return true;
 }
 
 // Skip all whitespace, as we normally know it.
@@ -121,38 +119,25 @@ static inline qbool Parse_Skip_Comments(struct qparser_state_s *state)
 }
 
 // Skip all whitespace.
-static inline qbool Parse_SkipToToken(struct qparser_state_s *state)
+static inline void Parse_SkipToToken(struct qparser_state_s *state)
 {
-       qbool ret = false;
-
        /*
         * Repeat this until we run out of whitespace, newlines, and comments.
         * state->pos should be left on non-whitespace when this returns.
         */
-       while(Parse_Skip_Comments(state) || Parse_Skip_Whitespace(state) || Parse_Newline(state))
-               ret = true;
-
-       return ret;
+       while(Parse_Skip_Comments(state) || Parse_Skip_Whitespace(state) || Parse_Newline(state));
 }
 
 // Skip to the next token. Advance the pointer at least 1 if we're not sitting on whitespace.
-char Parse_NextToken(struct qparser_state_s *state)
+char Parse_NextToken(struct qparser_state_s *state, int skip)
 {
-       // Check if we will skip first.
-       if(!Parse_SkipToToken(state))
-       {
-               // If not, advance the pointer.
-               Parse_Next(state, 1);
-               // Ensure we didn't land on whitespace and skip that too.
-               Parse_SkipToToken(state);
-       }
-       return *state->pos;
-}
+       if(!state->pos)
+               state->pos = state->buf;
+       else
+               Parse_Next(state, 1 + skip);
 
-// Return the current token but skip comments.
-char Parse_CurrentToken(struct qparser_state_s *state)
-{
        Parse_SkipToToken(state);
+
        return *state->pos;
 }
 
@@ -168,8 +153,8 @@ qparser_state_t *Parse_New(const unsigned char *in)
 
        out = (qparser_state_t *)Z_Malloc(sizeof(qparser_state_t));
 
-       out->buf = in;
-       out->pos = in;
+       out->buf = (const char *)in;
+       out->pos = NULL;
        out->line = 1;
        out->col = 1;
        out->depth = 0;