diff options
Diffstat (limited to 'src/LexForth.cpp')
-rwxr-xr-x | src/LexForth.cpp | 348 |
1 files changed, 348 insertions, 0 deletions
diff --git a/src/LexForth.cpp b/src/LexForth.cpp new file mode 100755 index 0000000..3f12815 --- /dev/null +++ b/src/LexForth.cpp @@ -0,0 +1,348 @@ +// Scintilla source code edit control +/** @file LexCrontab.cxx + ** Lexer to use with extended crontab files used by a powerful + ** Windows scheduler/event monitor/automation manager nnCron. + ** (http://nemtsev.eserv.ru/) + **/ +// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org> +// The License.txt file describes the conditions under which this software may be distributed. + +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <stdio.h> +#include <stdarg.h> + +#include "Platform.h" + +#include "PropSet.h" +#include "Accessor.h" +#include "KeyWords.h" +#include "Scintilla.h" +#include "SciLexer.h" + +bool is_whitespace(int ch){ + return ch == '\n' || ch == '\r' || ch == '\t' || ch == ' '; +} + +bool is_blank(int ch){ + return ch == '\t' || ch == ' '; +} +//#define FORTH_DEBUG +#ifdef FORTH_DEBUG +static FILE *f_debug; +#define log(x) fputs(f_debug,x); +#else +#define log(x) +#endif + +#define STATE_LOCALE +#define BL ' ' + +static Accessor *st; +static int cur_pos,pos1,pos2,pos0,lengthDoc; +char *buffer; + +char getChar(bool is_bl){ + char ch=st->SafeGetCharAt(cur_pos); + if(is_bl) if(is_whitespace(ch)) ch=BL; + return ch; +} + +char getCharBL(){ + char ch=st->SafeGetCharAt(cur_pos); + return ch; +} +bool is_eol(char ch){ + return ch=='\n' || ch=='\r'; +} + +int parse(char ch, bool skip_eol){ +// pos1 - start pos of word +// pos2 - pos after of word +// pos0 - start pos + char c=0; + int len; + bool is_bl=ch==BL; + pos0=pos1=pos2=cur_pos; + for(;cur_pos<lengthDoc && (c=getChar(is_bl))==ch; cur_pos++){ + if(is_eol(c) && !skip_eol){ + pos2=pos1; + return 0; + } + } + pos1=cur_pos; + pos2=pos1; + if(cur_pos==lengthDoc) return 0; + for(len=0;cur_pos<lengthDoc && (c=getChar(is_bl))!=ch; cur_pos++){ + if(is_eol(c) && !skip_eol) break; + pos2++; + buffer[len++]=c; + } + if(c==ch) pos2--; + buffer[len]='\0'; +#ifdef FORTH_DEBUG + fprintf(f_debug,"parse: %c %s\n",ch,buffer); +#endif + return len; +} + +bool _is_number(char *s,int base){ + for(;*s;s++){ + int digit=((int)*s)-(int)'0'; +#ifdef FORTH_DEBUG + fprintf(f_debug,"digit: %c %d\n",*s,digit); +#endif + if(digit>9 && base>10) digit-=7; + if(digit<0) return false; + if(digit>=base) return false; + } + return true; +} + +bool is_number(char *s){ + if(strncmp(s,"0x",2)==0) return _is_number(s+2,16); + return _is_number(s,10); +} + +static void ColouriseForthDoc(unsigned int startPos, int length, int, WordList *keywordLists[], Accessor &styler) +{ + st=&styler; + cur_pos=startPos; + lengthDoc = startPos + length; + buffer = new char[length]; + +#ifdef FORTH_DEBUG + f_debug=fopen("c:\\sci.log","at"); +#endif + + WordList &control = *keywordLists[0]; + WordList &keyword = *keywordLists[1]; + WordList &defword = *keywordLists[2]; + WordList &preword1 = *keywordLists[3]; + WordList &preword2 = *keywordLists[4]; + WordList &strings = *keywordLists[5]; + + // go through all provided text segment + // using the hand-written state machine shown below + styler.StartAt(startPos); + styler.StartSegment(startPos); + while(parse(BL,true)!=0){ + if(pos0!=pos1){ + styler.ColourTo(pos0,SCE_FORTH_DEFAULT); + styler.ColourTo(pos1-1,SCE_FORTH_DEFAULT); + } + if(strcmp("\\",buffer)==0){ + styler.ColourTo(pos1,SCE_FORTH_COMMENT); + parse(1,false); + styler.ColourTo(pos2,SCE_FORTH_COMMENT); + }else if(strcmp("(",buffer)==0){ + styler.ColourTo(pos1,SCE_FORTH_COMMENT); + parse(')',true); + if(cur_pos<lengthDoc) cur_pos++; + styler.ColourTo(cur_pos,SCE_FORTH_COMMENT); + }else if(strcmp("[",buffer)==0){ + styler.ColourTo(pos1,SCE_FORTH_STRING); + parse(']',true); + if(cur_pos<lengthDoc) cur_pos++; + styler.ColourTo(cur_pos,SCE_FORTH_STRING); + }else if(strcmp("{",buffer)==0){ + styler.ColourTo(pos1,SCE_FORTH_LOCALE); + parse('}',false); + if(cur_pos<lengthDoc) cur_pos++; + styler.ColourTo(cur_pos,SCE_FORTH_LOCALE); + }else if(strings.InList(buffer)) { + styler.ColourTo(pos1,SCE_FORTH_STRING); + parse('"',false); + if(cur_pos<lengthDoc) cur_pos++; + styler.ColourTo(cur_pos,SCE_FORTH_STRING); + }else if(control.InList(buffer)) { + styler.ColourTo(pos1,SCE_FORTH_CONTROL); + styler.ColourTo(pos2,SCE_FORTH_CONTROL); + }else if(keyword.InList(buffer)) { + styler.ColourTo(pos1,SCE_FORTH_KEYWORD); + styler.ColourTo(pos2,SCE_FORTH_KEYWORD); + }else if(defword.InList(buffer)) { + styler.ColourTo(pos1,SCE_FORTH_KEYWORD); + styler.ColourTo(pos2,SCE_FORTH_KEYWORD); + parse(BL,false); + styler.ColourTo(pos1-1,SCE_FORTH_DEFAULT); + styler.ColourTo(pos1,SCE_FORTH_DEFWORD); + styler.ColourTo(pos2,SCE_FORTH_DEFWORD); + }else if(preword1.InList(buffer)) { + styler.ColourTo(pos1,SCE_FORTH_PREWORD1); + parse(BL,false); + styler.ColourTo(pos2,SCE_FORTH_PREWORD1); + }else if(preword2.InList(buffer)) { + styler.ColourTo(pos1,SCE_FORTH_PREWORD2); + parse(BL,false); + styler.ColourTo(pos2,SCE_FORTH_PREWORD2); + parse(BL,false); + styler.ColourTo(pos1,SCE_FORTH_STRING); + styler.ColourTo(pos2,SCE_FORTH_STRING); + }else if(is_number(buffer)){ + styler.ColourTo(pos1,SCE_FORTH_NUMBER); + styler.ColourTo(pos2,SCE_FORTH_NUMBER); + } + } +#ifdef FORTH_DEBUG + fclose(f_debug); +#endif + delete []buffer; + return; +/* + if(control.InList(buffer)) { + styler.ColourTo(i,SCE_FORTH_CONTROL); + } else if(keyword.InList(buffer)) { + styler.ColourTo(i-1,SCE_FORTH_KEYWORD ); + } else if(defword.InList(buffer)) { + styler.ColourTo(i-1,SCE_FORTH_DEFWORD ); +// prev_state=SCE_FORTH_DEFWORD + } else if(preword1.InList(buffer)) { + styler.ColourTo(i-1,SCE_FORTH_PREWORD1 ); +// state=SCE_FORTH_PREWORD1; + } else if(preword2.InList(buffer)) { + styler.ColourTo(i-1,SCE_FORTH_PREWORD2 ); + } else { + styler.ColourTo(i-1,SCE_FORTH_DEFAULT); + } +*/ +/* + chPrev=' '; + for (int i = startPos; i < lengthDoc; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + if(i!=startPos) chPrev=styler.SafeGetCharAt(i - 1); + + if (styler.IsLeadByte(ch)) { + chNext = styler.SafeGetCharAt(i + 2); + i++; + continue; + } +#ifdef FORTH_DEBUG + fprintf(f_debug,"%c %d ",ch,state); +#endif + switch(state) { + case SCE_FORTH_DEFAULT: + if(is_whitespace(ch)) { + // whitespace is simply ignored here... + styler.ColourTo(i,SCE_FORTH_DEFAULT); + break; + } else if( ch == '\\' && is_blank(chNext)) { + // signals the start of an one line comment... + state = SCE_FORTH_COMMENT; + styler.ColourTo(i,SCE_FORTH_COMMENT); + } else if( is_whitespace(chPrev) && ch == '(' && is_whitespace(chNext)) { + // signals the start of a plain comment... + state = SCE_FORTH_COMMENT_ML; + styler.ColourTo(i,SCE_FORTH_COMMENT_ML); + } else if( isdigit(ch) ) { + // signals the start of a number + bufferCount = 0; + buffer[bufferCount++] = ch; + state = SCE_FORTH_NUMBER; + } else if( !is_whitespace(ch)) { + // signals the start of an identifier + bufferCount = 0; + buffer[bufferCount++] = ch; + state = SCE_FORTH_IDENTIFIER; + } else { + // style it the default style.. + styler.ColourTo(i,SCE_FORTH_DEFAULT); + } + break; + + case SCE_FORTH_COMMENT: + // if we find a newline here, + // we simply go to default state + // else continue to work on it... + if( ch == '\n' || ch == '\r' ) { + state = SCE_FORTH_DEFAULT; + } else { + styler.ColourTo(i,SCE_FORTH_COMMENT); + } + break; + + case SCE_FORTH_COMMENT_ML: + if( ch == ')') { + state = SCE_FORTH_DEFAULT; + } else { + styler.ColourTo(i+1,SCE_FORTH_COMMENT_ML); + } + break; + + case SCE_FORTH_IDENTIFIER: + // stay in CONF_IDENTIFIER state until we find a non-alphanumeric + if( !is_whitespace(ch) ) { + buffer[bufferCount++] = ch; + } else { + state = SCE_FORTH_DEFAULT; + buffer[bufferCount] = '\0'; +#ifdef FORTH_DEBUG + fprintf(f_debug,"\nid %s\n",buffer); +#endif + + // check if the buffer contains a keyword, + // and highlight it if it is a keyword... +// switch(prev_state) +// case SCE_FORTH_DEFAULT: + if(control.InList(buffer)) { + styler.ColourTo(i,SCE_FORTH_CONTROL); + } else if(keyword.InList(buffer)) { + styler.ColourTo(i-1,SCE_FORTH_KEYWORD ); + } else if(defword.InList(buffer)) { + styler.ColourTo(i-1,SCE_FORTH_DEFWORD ); +// prev_state=SCE_FORTH_DEFWORD + } else if(preword1.InList(buffer)) { + styler.ColourTo(i-1,SCE_FORTH_PREWORD1 ); +// state=SCE_FORTH_PREWORD1; + } else if(preword2.InList(buffer)) { + styler.ColourTo(i-1,SCE_FORTH_PREWORD2 ); + } else { + styler.ColourTo(i-1,SCE_FORTH_DEFAULT); + } +// break; +// case + + // push back the faulty character + chNext = styler[i--]; + } + break; + + case SCE_FORTH_NUMBER: + // stay in CONF_NUMBER state until we find a non-numeric + if( isdigit(ch) ) { + buffer[bufferCount++] = ch; + } else { + state = SCE_FORTH_DEFAULT; + buffer[bufferCount] = '\0'; + // Colourize here... (normal number) + styler.ColourTo(i-1,SCE_FORTH_NUMBER); + // push back a character + chNext = styler[i--]; + } + break; + } + } +#ifdef FORTH_DEBUG + fclose(f_debug); +#endif + delete []buffer; +*/ +} + +static void FoldForthDoc(unsigned int, int, int, WordList *[], + Accessor &) { +} + +static const char * const forthWordLists[] = { + "control keywords", + "keywords", + "definition words", + "prewords with one argument", + "prewords with two arguments", + "string definition keywords", + 0, + }; + +LexerModule lmForth(SCLEX_FORTH, ColouriseForthDoc, "forth",FoldForthDoc,forthWordLists); |