Rev 1 | Blame | Compare with Previous | Last modification | View Log | RSS feed
#include "bod_text_parser.h"
#include "../common/strutils.h"
#include <memory.h>
//---------------------------------------------------------------------------------
// ERROR
const char* bod_text_parser::Error::m_messages[]={
"No error",
"Newline in constant"
};
// TOKEN
const 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;
else
return 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 string
else
PUSH_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 tabulator
else if(ch==' ' || ch==0x9){
*pos=0;
if(*old!=0)
PUSH_PREVIOUS_STRING();
old=pos + 1;
}
// brackets
else 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 instruction
else 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++;
}
// slash
else{
/* if ignore slash is on then do nothing
else treat it as comment unless C comments are specified, in which case there must
be // 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 them
if(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;
}
//---------------------------------------------------------------------------------