📄 parser.cpp
字号:
#include "Parser.h"Parser::Parser(): tmpl(0),current(0),end_tag(""),out(stdout),is_active(true) { }Parser::Parser(TemplateContainer *t, TemplateObject *curr, string end_tag_name, FILE *out_stream=stdout): tmpl(t),current(curr),end_tag(end_tag_name),out(out_stream),is_active(true){ }void Parser::addHandler(string tag,tag_handler handler) { tag_handlers[tag]=handler;}void Parser::setTemplate(TemplateContainer *t) { tmpl=t;}void Parser::setCurrent(TemplateObject *curr) { current=curr;}void Parser::setEndTag(string &tag) { end_tag=tag;}void Parser::setOutStream(FILE *out_stream) { out=out;}token Parser::getToken() { token t; int state=0; char c; while(1) { c=nextpos(); if(!c) return t; switch(state) { case 0: t.line=tmpl->line; t.pos=tmpl->pos; if(c=='"') { t.type=STRING; state=1; // waiting string } else if(isalpha(c) || c=='_') { t.type=ID; t.image+=c; state=2; } else if(c=='=') { t.type=EQ; t.image='='; return t; } else if(c=='<') { t.type=LT; t.image='<'; return t; } else if(c=='>') { t.type=GT; t.image='>'; return t; } else if(c=='!') { t.type=VZ; t.image='!'; return t; } else if(c=='/') { t.type=SLASH; t.image='/'; return t; } else if(c=='\\') { state=4; break; } else if(isspace(c)) { // skip spaces t.type=SPACE; t.image=c; return t; } else { t.type=OTHER; t.image=c; return t; } break; case 1: // string if(c=='\\') { // escaped symbol state=3; } else if(c=='"') { // end reached return t; } else { t.image+=c; } break; case 2: // identifier if(isalnum(c) || c=='_') { t.image+=c; } else { step_back(); return t; } break; case 3: // string escaped symbol t.image+=c; state=1; break; case 4: // some escaped simbol should be treated as OTHER t.type=OTHER; t.image=c; return t; } }}void Parser::parse() { int state=0; token t; TmplTag tag;// t=getToken(); string arg_key,arg_val; char c;DUMMY: state=0; while((c=nextpos())!='<') { if(!c) return; else if(is_active) fputc(c,out); } step_back(); while((t=getToken()).image!="") { switch(state) { case 0: // waiting for '<' (LT) tag.begin_line=0; tag.begin_pos=0; if(t.type==LT) { state=1; tag.begin_line=t.line; tag.begin_pos=t.pos; break; } else { print(t); goto DUMMY; break; } case 1: // should be ID or SLASH if(t.type==ID) { map<string,tag_handler>::const_iterator ci=tag_handlers.find(t.image); if(ci==tag_handlers.end()) { // not template tag should be printed asis token tmp; tmp.image='<'; print(tmp); print(t); goto DUMMY; } else { tag.name=t.image; state=2; } } else if(t.type==SLASH) { state=6; // It could be close tag } else { token tmp; tmp.image='<'; print(tmp); print(t); state=0; } break; case 2: // SPACE or GT if(t.type==SPACE) { // one or more spaces state=3; } else if(t.type==GT) { //got the full tag !!! tag_handlers[tag.name](tmpl,current,tag,is_active,out); goto DUMMY; } else { throw ParserError("Syntax error: expected SPACE or GT",t); } break; case 3: // SPACE or ID or GT if(t.type==SPACE) break; //swallow spaces if(t.type==ID) { arg_key=t.image; state=4; } else if(t.type==GT) { tag_handlers[tag.name](tmpl,current,tag,is_active,out); goto DUMMY; } else { throw ParserError("Syntax error: expected ID or ID or GT",t); } break; case 4: // SPACE or EQ if(t.type==SPACE) { // swallow spaces } else if(t.type==EQ) { state=5; } else { throw ParserError("Syntax error: expected SPACE or EQ",t); } break; case 5: // SPACE or STRING if(t.type==SPACE) { //swallow spaces } else if(t.type==STRING) { arg_val=t.image; tag.args[arg_key]=arg_val; state=2; } else { throw ParserError("Syntax error: expected SPACE or STRING",t); } break; case 6: //ID if(t.type==ID) { if(t.image==end_tag) state=7; else { token tmp; tmp.image="</"; print(tmp); print(t); goto DUMMY; } } else { token tmp; tmp.image="</"; print(tmp); print(t); goto DUMMY; } break; case 7: // GT if(t.type==GT) { return; } else { throw ParserError("Syntax error: expected GT",t); } break; } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -