📄 cppcms_tmpl_cc
字号:
#!/usr/bin/env pythonimport osimport reimport sysvariable_match=r'\*?([a-zA-Z]\w*)(((\.|->)([a-zA-Z]\w*))*)'str_match=r'"([^"\\]|\\[^"]|\\")*"'def interleave(*args): for idx in range(0, max(len(arg) for arg in args)): for arg in args: try: yield arg[idx] except IndexError: continuedef output(s): global stack global file_name global line_number global output_fd output_fd.write('\t' * len(stack) + '#line %d "%s"' % (line_number,file_name)+'\n' + \ '\t'*len(stack) + s + '\n')class tmpl_descr: def __init__(self,start,size): self.start_id=start self.param_num=sizeclass namespace_block: pattern=r'^<%\s*namespace\s+(\w+)\s*(at\s*(\w+)\s*)?%>$' type='namespace' def use(self,m): self.internal_namespace=0 global namespace_name if m.group(1)=='vary': if namespace_name!='': self.internal_namespace=0 else: error_exit("Can't use `vary' namespace without external one") else: # m.group(1)!='vary' if namespace_name=='': namespace_name=m.group(1) self.internal_namespace=1 else: error_exit("Can't define both external and non-vary namespace") output( "namespace %s {" % namespace_name) self.reset_gettext=0 if m.group(2): global spec_gettext if not spec_gettext: spec_gettext=m.group(3) self.reset_gettext=1 global stack stack.append(self) def on_end(self): global namespace_name output( "} // end of namespace %s" % namespace_name) if self.internal_namespace: namespace_name='' if self.reset_gettext: global spec_gettext spec_gettext=''def write_class_loader(): global class_list output( "namespace {") output( " struct loader {") output( " loader(){") output( " using namespace cppcms::details;") output( " views_storage &_VS_ref=views_storage::instance();") list_of_views={} for class_def in class_list: list_of_views[class_def.namespace]="" if class_def.content_name!='': output( ' _VS_ref.add_view("%s","%s",view_builder<%s::%s,%s>());' \ % (class_def.namespace,class_def.name,class_def.namespace,class_def.name,class_def.content_name)) else: output( ' _VS_ref.add_view("%s","%s",simple_view_builder<%s::%s>());' \ % (class_def.namespace,class_def.name,class_def.namespace,class_def.name)) output( " };") output( ' ~loader() { ') output( " using namespace cppcms::details;") output( " views_storage &_VS_ref=views_storage::instance();") for ns in list_of_views: output( ' _VS_ref.remove_views("%s");' % ns) output( ' }') output( " } loader_entry;") output( "} // empty namespace ") output( 'extern "C" { // Dummy extern symbols to insure full link' ) for ns in list_of_views: output( '\tvoid load_view_%s(){}' % ns ) output( '} // extern C' )def gettext_domain(): global spec_gettext if spec_gettext: return spec_gettext global namespace_name return namespace_nameclass html_type: pattern=r'^<%\s*(x)?html\s*%>$' def use(self,m): global html_type_code if m.group(1): html_type_code='cppcms::base_form::as_xhtml' else: html_type_code='cppcms::base_form::as_html' class class_block: pattern=r'^<%\s*class\s+(\w+)\s+(uses\s+(\w+(::\w+)?))?\s+(extends\s+(\w+(::\w+)?))?\s*%>$' type='class' def declare(self): if self.extends=='' : constructor='cppcms::base_view(_s)' self.extends='cppcms::base_view' else: constructor='%s(_s,_content)' % self.extends; output( "struct %s :public %s" % (self.class_name , self.extends )) output( "{") if self.uses!='' : output( "\t%s &content;" % self.uses) output( "\tcppcms::transtext::trans const *tr;" ) output( "\t%s(cppcms::base_view::settings _s,%s &_content): %s,content(_content)" % ( self.class_name,self.uses,constructor )) else: output( "\t%s(cppcms::base_view::settings _s): %s" % ( self.class_name,constructor )) output("\t{") output('\t\ttr=_s.worker->domain_gettext("%s");' % gettext_domain() ) output("\t};") def use(self,m): self.class_name=m.group(1) if m.group(2): self.uses=m.group(3) else: self.uses='' if m.group(5): self.extends=m.group(6) else: self.extends='' self.declare(); global stack if len(stack)!=1 or stack[-1].type!='namespace': error_exit("You must define class inside namespace block only") stack.append(self) global class_list global namespace_name class information: content_name=self.uses name=self.class_name namespace=namespace_name class_list.append(information()) def on_end(self): output( "}; // end of class %s" % self.class_name)class template_block: pattern=r'^<%\s*template\s+([a-zA-Z]\w*)\s*\(([\w\s,:\&]*)\)\s*%>$' type='template' plist=[] def create_parameters(self,lst): pattern=r'^\s*((\w+(::\w+)*)\s*(const)?\s*(\&)?\s*(\w+))\s*(,(.*))?$' m=re.match(pattern,lst) res=[] while m: global tmpl_seq id=m.group(6) if tmpl_seq.has_key(id): error_exit("Duplicate definition of patameter %s" % id) for v in self.plist: del tmpl_seq[v] return "" tmpl_seq[id]='' res.append(m.group(1)) self.plist.append(id) if m.group(8): lst=m.group(8) m=re.match(pattern,lst) else: return ','.join(res) for v in self.plist: del tmpl_seq[v] error_exit("Wrong expression %s" % lst) def use(self,m): self.name=m.group(1) params="" if m.group(2) and not re.match('^\s*$',m.group(2)): params=self.create_parameters(m.group(2)) output( "virtual void %s(%s) {" % (self.name,params) ) global stack if len(stack)==0 or stack[-1].type!='class': error_exit("You must define template inside class block only") stack.append(self) global current_template current_template=self.name global ignore_inline ignore_inline=0 def on_end(self): output( "} // end of template %s" % self.name) global ignore_inline ignore_inline=1 global tmpl_seq tmpl_seq={} def inline_content(s): global ignore_inline if not ignore_inline: output( 'cout<<"%s";' % to_string(s))def error_exit(x): global exit_flag global file_name global line_number sys.stderr.write("Error: %s in file %s, line %d\n" % (x,file_name,line_number)) exit_flag=1def to_string(s): res='' for c in s: global stack if c=='\n': res+="\\n\""+"\n"+"\t"*len(stack)+"\t\"" elif c=="\t": res+="\\t" elif c=="\v": res+="\\v" elif c=="\b": res+="\\b" elif c=="\r": res+="\\r" elif c=="\f": res+="\\f" elif c=="\a": res+="\\a" elif c=="\\": res+="\\\\" elif c=="\"": res+="\\\"" elif ord(c)>0 and ord(c)<32: res+="%03o" % ord(c) else: res+=c return resdef make_ident(val): m=re.match('^'+variable_match+'$',val) global tmpl_seq if tmpl_seq.has_key(m.group(1)): return val m2=re.match('^\*(.*)$',val) if m2: return "*content." + m2.group(1) else: return "content." + valclass foreach_block: pattern=r'^<%\s*foreach(\s+widget)?\s+([a-zA-Z]\w*)\s+in\s+(' + variable_match +')\s*%>$' type='foreach' has_item=0 has_separator=0 separator_label='' on_first_label='' widget=0 def use(self,m): self.ident=m.group(2) self.seq_name=make_ident(m.group(3)) global tmpl_seq if tmpl_seq.has_key(self.ident): error_exit("Nested sequences with same name") tmpl_seq[self.ident]=''; if m.group(1): self.widget=1 output("if(%s.widgets.begin()!=%s.widgets.end()){" % (self.seq_name,self.seq_name) ) else: output( "if(%s.begin()!=%s.end()) {" % (self.seq_name,self.seq_name) ) global stack stack.append(self) def on_end(self): if not self.has_item: error_exit("foreach without item") global tmpl_seq del tmpl_seq[self.ident] output( "}" )def prepare_foreach(widget,seq,ident,has_separator): if widget: output("for(cppcms::widgetset::widgets_t::iterator %(i)s_ptr=%(s)s.widgets.begin(),%(i)s_ptr_end=%(s)s.widgets.end();%(i)s_ptr!=%(i)s_ptr_end;++%(i)s_ptr) {" \ % { 's' :seq, 'i' : ident }) output( "cppcms::widgets::base_widget &%s=**%s_ptr;" % (ident,ident)) else: output( "for(CPPCMS_TYPEOF(%(s)s.begin()) %(i)s_ptr=%(s)s.begin(),%(i)s_ptr_end=%(s)s.end();%(i)s_ptr!=%(i)s_ptr_end;++%(i)s_ptr) {" \ % { 's' :seq, 'i' : ident }) output( "CPPCMS_TYPEOF(*%s_ptr) &%s=*%s_ptr;" % (ident,ident,ident)) if has_separator: if widget: output( "if(%s_ptr!=%s.widgets.begin()) {" % (ident,seq)) else: output( "if(%s_ptr!=%s.begin()) {" % (ident,seq)) class separator_block: pattern=r'^<%\s*separator\s*%>' type='separator' def use(self,m): global stack if len(stack)==0 or stack[len(stack)-1].type!='foreach': error_exit("separator without foreach") return foreachb=stack[len(stack)-1] if foreachb.has_separator: error_exit("two separators for one foreach") foreachb.has_separator=1 prepare_foreach(foreachb.widget,foreachb.seq_name,foreachb.ident,1) class item_block: pattern=r'^<%\s*item\s*%>' type='item' def use(self,m): global stack if not stack or stack[-1].type!='foreach': error_exit("item without foreach") return foreachb=stack[-1] if foreachb.has_item: error_exit("Two items for one foreach"); if foreachb.has_separator: output( "} // end of separator") else: prepare_foreach(foreachb.widget,foreachb.seq_name,foreachb.ident,0) foreachb.has_item=1 stack.append(self) def on_end(self): output( "} // end of item" )class empty_block: pattern=r'^<%\s*empty\s*%>' type='empty' def use(self,m): global stack if not stack or stack[-1].type!='foreach': error_exit("empty without foreach") return forb=stack.pop() if not forb.has_item: error_exit("Unexpected empty - item missed?") output( " } else {") self.ident=forb.ident stack.append(self)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -