We use cookies to ensure you have the best browsing experience on our website. Please read our cookie policy for more information about how we use cookies.
This one was definitely quite a bit more difficult than most of the others I've encounterd so far. Here's the solution I came up with. I tried to write an actual parser rather than just use regex. I'm somewhat happy with it, but I think there are probably some aspects that could use a bit of tidying up.
#include<iostream>#include<vector>enumnode_type{tag,label,value};structparse_tree_node{node_typent;std::stringname;std::vector<structparse_tree_node*>children;structparse_tree_node*parent;};voidutility_free(structparse_tree_node*ptn){for(autoconst&value:ptn->children)utility_free(value);deleteptn;}intmain(void){structparse_tree_node*root=newstructparse_tree_node;structparse_tree_node*current_level=root;current_level->name="ROOT";current_level->nt=tag;intn,q;std::cin>>n>>q;// parse lines into treefor(inti=0;i<n;i++){while(std::cin.get()!='<');if(std::cin.peek()!='/'){charnext_char;boolexpecting_space=true;boolneed_next=false;booldone=false;boolquoted_mode=false;structparse_tree_node*new_node=newstructparse_tree_node;new_node->nt=tag;current_level->children.push_back(new_node);new_node->parent=current_level;current_level=new_node;while(!done){next_char=std::cin.get();if(!quoted_mode)switch(next_char){case'"':quoted_mode=true;need_next=true;break;case'>':done=true;break;case' ':if(!expecting_space)need_next=true;break;case'=':{structparse_tree_node*parent_node=new_node;new_node=newstructparse_tree_node;new_node->nt=value;parent_node->children.push_back(new_node);expecting_space=true;need_next=false;break;}default:if(need_next){structparse_tree_node*parent_node=current_level;;new_node=newstructparse_tree_node;new_node->nt=label;parent_node->children.push_back(new_node);need_next=false;}new_node->name.append(1,next_char);expecting_space=false;break;}else{if(next_char!='"')new_node->name.append(1,next_char);elsequoted_mode=false;}}}else{current_level=current_level->parent;while(std::cin.get()!='>');}}// process queriesfor(inti=0;i<q;i++){structparse_tree_node*current_level=root;std::stringqstr_part;charpeek_char;booltilde_mode=false;while((peek_char=std::cin.peek())==' '||peek_char=='\n')std::cin.get();while(true){charnext_char=std::cin.get();if(next_char=='.'||next_char=='~'){boolfound=false;tilde_mode=next_char=='~';for(autoconst&value:current_level->children)if(value->nt==tag&&value->name==qstr_part){current_level=value;qstr_part="";found=true;break;}if(!found){chardrop_char;std::cout<<"Not Found!"<<std::endl;while((drop_char=std::cin.get())!='\n'&&drop_char!=EOF);break;}}elseif(next_char=='\n'||next_char==EOF){boolfound=false;if(tilde_mode)for(autoconst&value:current_level->children)if(value->nt==label&&value->name==qstr_part){// This next line is a little sketchy.std::cout<<value->children[0]->name<<std::endl;found=true;break;}if(!found)std::cout<<"Not Found!"<<std::endl;break;}else{qstr_part.append(1,next_char);}}}utility_free(root);return0;}
Attribute Parser
You are viewing a single comment's thread. Return to all comments →
This one was definitely quite a bit more difficult than most of the others I've encounterd so far. Here's the solution I came up with. I tried to write an actual parser rather than just use regex. I'm somewhat happy with it, but I think there are probably some aspects that could use a bit of tidying up.