diff --git a/engine/slc.h b/engine/slc.h index 94ecc25..3d0ac54 100644 --- a/engine/slc.h +++ b/engine/slc.h @@ -4,6 +4,7 @@ #include // uint8_t, uint32_t.. #include // memcpy, strlen.. #include // NULL +#include // isspace /* Define this if you want to debug the engine doing its thing */ /* #define SLC_DEBUG */ @@ -13,7 +14,7 @@ #define SLOFFS_T uint64_t #endif -/* Maximum length of words - defaults but you can override */ +/* Maximum length of words - defaults but you can override; Adds +1 to this for null terminator */ #ifndef SL_MAX_WORD_NAME #define SL_MAX_WORD_NAME 255 #endif @@ -270,6 +271,8 @@ enum slc_state : uint8_t { SLC_WORD_NAME = 'w', /** Variable call (MYWORD@MYVAR) - we get to be here from SLC_WORD_NAME or from START */ SLC_WORD_VAR = 'W', + /** Syntax error state - recovers by newlines */ + SLC_SYN_ERROR = 'e', }; typedef enum slc_state slc_state; @@ -326,15 +329,45 @@ static inline slc_state slc_multiline_comment_statechange_out( return current_state; } +/** Handles state change into word definitions */ static inline slc_state slc_def_name_statechange( slc_state current_state, + char prevc, char c, const char *prefix, int *prefix_i) { - // FIXME: Implement - return current_state; + + /* If not a whitespace currently, check the prefix, otherwise check ending ':' */ + if(!isspace(c)) { + /* Early exit for not-a-definition sub-state */ + if(*prefix_i < 0) { + return current_state; + } + + /* Read prefix */ + if(prefix[*prefix_i] != 0) { + if(prefix[*prefix_i] == c) { + ++(*prefix_i); + } else { + *prefix_i = -1; + } + } + + return current_state; + } else { + /* Check if ended by ':' after full prefix or not */ + if(prevc == ':' && (*prefix_i > 0) && prefix[*prefix_i] == 0) { + /* Found: a word definition! */ + return SLC_WORD_NAME; + } else { + /* Not Found: Probably a word occurence */ + *prefix_i = 0; /* XXX: restarts scan */ + return current_state; + } + } } +/** Handles state change into word occurences - shared wordname with def_name_statechange! */ static inline slc_state slc_word_statechange( slc_state current_state, char c, @@ -412,13 +445,15 @@ static inline void slc( int multiline_i = 0; int prefix_i = 0; int wordname_i = 0; - char wordname[SL_MAX_WORD_NAME]; + char wordname[SL_MAX_WORD_NAME + 1]; + char prevc = 0; char c = 0; while(((c = code_src()) != 0)) { /* Handle lines and columns, parts of indenting */ if(endsline(c)) { - if(!last_is_endl) { + /* Handles \n, \r, \r\n and \n\r this way and counts empty lines properly */ + if((prevc != c) || !last_is_endl) { ++line; col = 0; /* Indent part */ @@ -454,6 +489,7 @@ static inline void slc( if(state == SLC_START) { state = slc_def_name_statechange( state, + prevc, c, prefix, &prefix_i); @@ -489,7 +525,13 @@ static inline void slc( break; case SLC_WORD_VAR: break; + case SLC_SYN_ERROR: + /* Recover from slc syntax errors at endlines for now */ + if(endsline(c)) state = SLC_START; + break; } + + prevc = c; } } diff --git a/main.c b/main.c index 46dd68b..db4edd3 100644 --- a/main.c +++ b/main.c @@ -29,12 +29,20 @@ iores nopioconn(SLC_IO_OP op, const char *param) { char testcoderead() { static int i = 0; static const char *code = - "// This is a small test program push(42)\n" + "// This is a small test program to push(42); print\n" "/*#push(21)\n" "#push(21)\n" "#add*/\n" " #push(42)\n" - " #print\n"; + " #print\n" + "\n" + "#: word_test\n" + " #push(21)\n" + " #push(21)\n" + " #add\n" + " #print\n" + "\n" + "word_test\n"; return code[i++]; }