Rev 1 | Blame | Compare with Previous | Last modification | View Log | RSS feed
#include "bod_text_parser.h"#include "../common/strutils.h"#include <memory.h>//---------------------------------------------------------------------------------// ERRORconst char* bod_text_parser::Error::m_messages[]={"No error","Newline in constant"};// TOKENconst char* bod_text_parser::token::specialChars[]={ "{", "}", ";", ":", "=", "/!", "!/", "/#", "(", ")", "/", ".", "+" };char bod_text_parser::token::tabWidth;const char* bod_text_parser::token::getText() const{if(type >= t_text)return text;elsereturn specialChars[(int)type];}//---------------------------------------------------------------------------------void bod_text_parser::preParseBuffer(char *pszBuffer, size_t size){m_pszBuffer=pszBuffer;m_buffLen=size;}//---------------------------------------------------------------------------------size_t bod_text_parser::parseBuffer(size_t limit){char *ln;size_t old=tokens.size();while(ln=nextLine()){if(parseLine(ln, ++m_lineIdx)==false)break;if(limit!=-1 && ((tokens.size() - old) >= limit)){break;}}return tokens.size() - old;}//---------------------------------------------------------------------------------#define PUSH_PREVIOUS_STRING() { t=new token(); \t->type=token::t_text; \t->line=idx; \t->text=old; \t->col=(int)(old - line + 1); \tokens.push_back(t); }#define PUSH_TOKEN(_type, _col, _text) { t=new token(); \t->type=_type; \t->line=idx; \t->col=(int)(_col); \t->text=_text; \tokens.push_back(t); }bool bod_text_parser::parseLine(char *line, int idx){char *old=line, *pos=line, ch;token *t;bool bInQuotedString=false;while(*pos!=0){ch=*pos;if(bInQuotedString || (ch=='"' && testFlag(parseQuotedStrings))){if(ch=='"'){bInQuotedString=!bInQuotedString;*pos=0;if(bInQuotedString){if(*old!=0)PUSH_PREVIOUS_STRING();}// got stringelsePUSH_TOKEN(token::t_quotedString, old - line, old);old=pos + 1;}else{++pos;continue;}}else if(ch==';' || ch==':' || (ch=='=' && testFlag(parseEqual)) ||(testFlag(parseOperators) && (ch=='.' || ch=='+'))) {*pos=0;if(*old!=0)PUSH_PREVIOUS_STRING();token::Type ty;switch(ch){case ';':ty=token::t_semicolon;break;case ':':ty=token::t_colon;break;case '=':ty=token::t_equal;break;case '.':ty=token::t_dot;break;case '+':ty=token::t_plus;break;}PUSH_TOKEN(ty, pos - line + 1, 0);old=pos + 1;}// space or tabulatorelse if(ch==' ' || ch==0x9){*pos=0;if(*old!=0)PUSH_PREVIOUS_STRING();old=pos + 1;}// bracketselse if(ch=='{' || ch=='}' || (testFlag(parseStdBrackets) && (ch=='(' || ch==')'))) {*pos=0;if(*old!=0)PUSH_PREVIOUS_STRING();token::Type ty;switch(ch){case '{':ty=token::t_openCrBracket;break;case '}':ty=token::t_closeCrBracket;break;case '(':ty=token::t_openStdBracket;break;case ')':ty=token::t_closeStdBracket;break;}PUSH_TOKEN(ty, pos - line + 1, 0);old=pos + 1;}// either comment, header info or processing instructionelse if(ch=='/') {if(pos[1]=='#'){t=new token();t->text=pos + 2;while(*t->text!=0 && *t->text==' ')t->text++;if(*t->text==0)delete t;else{t->line=idx;t->col=(int)(pos - line) + 1;t->type=token::t_hdrinfo;tokens.push_back(t);}}// open proc instruction /!if(pos[1]=='!') {PUSH_TOKEN(token::t_openInstrBlock, pos - line + 1, 0);old=pos + 2;pos++;}// slashelse{/* if ignore slash is on then do nothingelse treat it as comment unless C comments are specified, in which case there mustbe // to make comment, otherwise / is treated as token*/if(testFlag(parseIgnoreSlash)==false){if(testFlag(parseBODComments)) {*pos=0;pos--;}else if(testFlag(parseCComments) && pos[1]=='/') {*pos=0;pos--;}else {*pos=0;if(*old!=0)PUSH_PREVIOUS_STRING();PUSH_TOKEN(token::t_slash, pos - line + 1, 0);old=pos + 1;}}}}// close proc instruction !/else if(ch=='!' && pos[1]=='/'){*pos=0;if(*old!=0)PUSH_PREVIOUS_STRING();PUSH_TOKEN(token::t_closeInstrBlock, pos - line + 1, 0);old=pos + 2;pos++;}pos++;}if(bInQuotedString){error(idx, (int)strlen(line), Error::errNewLineInConstant);return false;}// if there are some chars left after last delimeter (usually ;) this will process themif(old!=pos){PUSH_TOKEN(token::t_text, old - line + 1, old);}return true;}//---------------------------------------------------------------------------------char * bod_text_parser::nextLine(){size_t i, size=m_buffLen;char *line=0, *buffer=(char*)m_pszBuffer;for(i=m_lastPos; i < size; i++){if(buffer[i]==0xD){buffer[i]=0;m_newPos=i;if(((i + 1) < size) && buffer[i+1]==0xA) {m_newPos++;}m_newPos++;line=buffer + m_lastPos;break;}else if(buffer[i]==0xA){buffer[i]=0;m_newPos=i + 1;line=buffer + m_lastPos;break;}}if(m_lastPos > size) return NULL;if(line==0) {line=buffer + m_lastPos;m_newPos=size + 1;}m_lastPos=m_newPos;return line;}//---------------------------------------------------------------------------------