I'm not quite sure; that is one of the things I hope perhaps to get some inspiration for here. The coding isn't too hard, but how should it look? Since there is not information in the parser about what type of parameters are allowed, they will just have to be something like "<parm>" for mandatory and "[<parm>]" for optional.
The number of options allowed seems to be controlled both by numAllowed in struct Option and by minimum, maximum in struct OptionGroup. I have taken to setting numAllowed to 0 and making single option groups for options that I want to restrict, using maximum and minimum. For options I think something like: OPTION for mandatory keywords (ie minimum>0) [OPTION] for optional keywords (ie minimum=0) OPTION ... and [OPTION] ... when maximum>minimum - but how about when minimum > 1; I suppose something like: OPTION <parm> (x #) ... (up to #) Would that be understood easily by the average user? /jan Sharon Lucas wrote: > Hi, > > Thanks for looking into this. It would be nice to have a way to > automatically generate the help text for STAF service requests. > > The STAFCommandParser lets you specify the following: > 1) The valid command options > 2) The number of times an option may be specified (0 is unlimited) > 3) If there is a value associated with the option (can be required, not > allowed, or optional) > 4) Groupings for options and if there is a minimum or maximum number of > options that can be specified in a grouping > 5) Dependency relationships (needee and needer options) > > So far it appears you've implemented something for 1 and 5, but nothing > yet for 2, 3, and 4. I would be interested to see how you plan to > represent all of these attributes in your output. > > Could you provide an example of the output you envision for an existing > STAF service, like the RESPOOL service? > > C:\>STAF local RESPOOL HELP > Response > -------- > *** RESPOOL Service Help *** > > CREATE POOL <PoolName> DESCRIPTION <Pool Description> > DELETE POOL <PoolName> CONFIRM [FORCE] > LIST [POOLS | SETTINGS] > ADD POOL <PoolName> ENTRY <Value> [ENTRY <Value>]... > REMOVE POOL <PoolName> ENTRY <Value> [ENTRY <Value>]... CONFIRM [FORCE] > QUERY POOL <PoolName> > REQUEST POOL <PoolName> > [FIRST | RANDOM | ENTRY <Value>] [PRIORITY <Number>] > [TIMEOUT <Number>[s|m|h|d|w]] [GARBAGECOLLECT <Yes | No>] > RELEASE POOL <PoolName> ENTRY <Value> [FORCE] > CANCEL POOL <PoolName> > [FORCE [MACHINE <Machine>] [HANDLE <Handle #> | NAME <Handle > Name>]] > [ENTRY <Value>] [PRIORITY <Priority>] [FIRST | LAST] > VERSION > HELP > > -------------------------------------------------------------- > Sharon Lucas > IBM Austin, luc...@us.ibm.com > (512) 286-7313 or Tieline 363-7313 > > > > > "jander...@talentex.co.uk" <jander...@talentex.co.uk> > 06/22/2010 06:19 AM > > To > staf <staf-users@lists.sourceforge.net> > cc > > Subject > [staf-users] A first shot at a self-documenting parser interface > > > > > > > I have been messing about with the code in STAFCommandParser, and I > thought it might be of use to others; also, it would be quite nice if > somebody felt inspired to give the code a shove or two, now that I > have begun. One may ask why I waste my time doing this, since most > parsers presumably are static and this code therefore doesn't save > large amounts of work. Personally I do it because I work on dynamic > parsers - potentially large numbers of them, so I need something like. > But I think it may be of more general interest too, since it can be > used to identify structural problems in a parser - I identified a > couple in the example I provided; one of those things that creep in > when you change a parser. And of course, you won't have to remember to > change your HELP text if you can generate it directly from the parser. > > The philosophy is simple - when you build a parser in STAF, you are > (potentially) constructing a hierarchy by defining the relations > between "needers" and "needees"; I have created two functions, one > that translates needer/needee into a hierarchical structure, and one > that prints out a representation of the same. > > I have provided an example in the included file (UNIX text file) along > with the code I added to STAFCommandParser.* > > Among the things that still need doing are: > > 1. printtree() only outputs to stdout - ideally one should get a > something in a format that can be returned to the client. > > 2. I haven't shown any information about parameter values etc > Construction of an example parser: > > pData->fRequestParser=STAFCommandParserPtr( > new STAFCommandParser, > STAFCommandParserPtr::INIT > ); > pData->fRequestParser->addOption( > "REQUEST", > 1, > STAFCommandParser::kValueNotAllowed > ); > pData->fRequestParser->addOption( > "LIST", > 1, > STAFCommandParser::kValueNotAllowed > ); > pData->fRequestParser->addOption( > "RESCLASS", > 1, > STAFCommandParser::kValueRequired > ); > pData->fRequestParser->addOption( > "RESNAME", > 1, > STAFCommandParser::kValueRequired > ); > pData->fRequestParser->addOption( > "RESTYPE", > 1, > STAFCommandParser::kValueRequired > ); > pData->fRequestParser->addOption( > "RESVERSION", > 1, > STAFCommandParser::kValueRequired > ); > pData->fRequestParser->addOption( > "TIMEOUT", > 1, > STAFCommandParser::kValueRequired > ); > pData->fRequestParser->addOption( > "LOC", > 1, > STAFCommandParser::kValueRequired > ); > pData->fRequestParser->addOption( > "LOCATION", > 1, > STAFCommandParser::kValueRequired > ); > pData->fRequestParser->addOption( > "OS", > 10, > STAFCommandParser::kValueRequired > ); > pData->fRequestParser->addOption( > "OSVERSION", > 1, > STAFCommandParser::kValueRequired > ); > pData->fRequestParser->addOption( > "OSBITS", > 1, > STAFCommandParser::kValueRequired > ); > pData->fRequestParser->addOption( > "DISK", > 1, > STAFCommandParser::kValueRequired > ); > pData->fRequestParser->addOption( > "ROLE", > 1, > STAFCommandParser::kValueRequired > ); > pData->fRequestParser->addOption( > "SCHEMA", > 1, > STAFCommandParser::kValueRequired > ); > pData->fRequestParser->addOption( > "INSTANCE", > 1, > STAFCommandParser::kValueRequired > ); > pData->fRequestParser->addOption( > "DURATION", > 1, > STAFCommandParser::kValueRequired > ); > pData->fRequestParser->addOption( > "LOCKNAME", > 1, > STAFCommandParser::kValueRequired > ); > pData->fRequestParser->addOption( > "ACCESS", > 1, > STAFCommandParser::kValueRequired > ); > pData->fRequestParser->addOption( > "FORMAT", > 1, > STAFCommandParser::kValueRequired > ); > pData->fRequestParser->addOption( > "INTERFACE", > 1, > STAFCommandParser::kValueRequired > ); > pData->fRequestParser->addOption( > "MARSHALL", > 1, > STAFCommandParser::kValueNotAllowed > ); > pData->fRequestParser->addOptionNeed( > "LIST RESCLASS RESNAME RESTYPE RESVERSION TIMEOUT > " > "LOC LOCATION OS OSVERSION OSBITS DISK ROLE SCHEMA > " > "INSTANCE DURATION LOCKNAME ACCESS FORMAT > INTERFACE " > "MARSHALL", > "REQUEST" > ); > pData->fRequestParser->addOptionNeed( > "FORMAT", > "LIST" > ); > pData->fRequestParser->addOptionNeed("RDBMS > FILE","RESCLASS"); > pData->fRequestParser->addOptionGroup("RESCLASS",1,1); > pData->fRequestParser->addOptionGroup("REQUEST",1,1); > pData->fRequestParser->addOptionGroup("LOC LOCATION",0,1); > > > > parsertree p=getParsertree(*pData->fRequestParser); > printtree(p); > > --------------------------------------------------- > > Output from printtree(): > > First on each line, the option, indented, and in brackets, the group it > belongs to, if any. If an option-name is found amongst the needers, which > hasn't been defined as an option, the text "is missing!" is appended to > it. Although it can't be seen in the printout, all the information > included in STAF's internal representation of a parser is extracted and > returned in the tree-structure. > > REQUEST (REQUEST) > LIST () > FORMAT () > RESCLASS (RESCLASS) > RDBMS is missing! () > FILE is missing! () > RESNAME () > RESTYPE () > RESVERSION () > TIMEOUT () > LOC (LOC LOCATION) > LOCATION (LOC LOCATION) > OS () > OSVERSION () > OSBITS () > DISK () > ROLE () > SCHEMA () > INSTANCE () > DURATION () > LOCKNAME () > ACCESS () > FORMAT () > INTERFACE () > MARSHALL () > > --------------------------------------------------- > >>From STAFCommandParser.cpp: > > //Parsertree functions > > opt::opt() > { > name=""; > numAllowed=0; > valueRequirement=STAFCommandParser::kValueNotAllowed; > } > > int toplevel(STAFCommandParserImpl &parser,STAFString &name) > { > for ( > STAFCommandParserImpl::NeedList::iterator > n=parser.fNeedList.begin(); > n!=parser.fNeedList.end(); > ++n > ){ > if (n->needer.find(name)!=0xffffffff){ > return 0; > } > } > return 1; > } > > STAFString getneeders(STAFCommandParserImpl &parser,STAFString &parent) > { > STAFString needers; > > if (parent==""){ > for ( > STAFCommandParserImpl::OptionList::iterator o=parser.fOptionList.begin(); > o!=parser.fOptionList.end(); > ++o > ){ > if > (toplevel(parser,o->second.name)){ > needers+=o->second.name+" "; > } > } > } > else{ > for ( > STAFCommandParserImpl::NeedList::iterator n=parser.fNeedList.begin(); > n!=parser.fNeedList.end(); > ++n > ){ > if (n->needee==parent) > needers+=n->needer+" "; > } > } > return needers; > } > > int findgrpix(parsertree &pt,STAFString curnm) > { > int i=0; > for ( > glist::iterator o=pt.groups.begin(); > o!=pt.groups.end(); > o++,i++ > ){ > if(o->second.group.find(curnm)!=0xffffffff) //i.e. if found > curnm in this group > return i; > } > } > > void addsub(STAFCommandParserImpl &parser,parsertree &pt,tree &subtree,opt > &option, int lvl=0) > { > STAFString needers=getneeders(parser,option.name); > STAFString curnm,CURNM; > opt curopt; > int w=needers.numWords(); > > for (int i=0;i<w;i++){ > CURNM=needers.subWord(i,1); > curnm=CURNM.toLowerCase(); > curopt.name=parser.fOptionList[curnm].name; > curopt.numAllowed=parser.fOptionList[curnm].numAllowed; > curopt.valueRequirement=parser.fOptionList[curnm].valueRequirement; > if (curopt.name=="") > curopt.name=CURNM+" is > missing!"; > subtree[i].option=curopt; > subtree[i].grpix=findgrpix(pt,CURNM); > addsub(parser,pt,subtree[i].sub,curopt,lvl+1); > } > } > > parsertree getParsertree(STAFCommandParser &p) > { > parsertree pt; > opt option; > STAFCommandParserImpl *parser_=p.getImpl(); > STAFCommandParserImpl &parser=*parser_; > > int i=0; > for ( > STAFCommandParserImpl::GroupList::iterator g=parser.fGroupList.begin(); > g!=parser.fGroupList.end(); > g++,i++ > ){ > pt.groups[i].group=g->group; > pt.groups[i].minimum=g->minimum; > pt.groups[i].maximum=g->maximum; > } > addsub(parser,pt,pt.ptree,option); > > return pt; > } > > void prtree(parsertree &pt,tree &t,int level=0) > { > STAFString spaces; > > for (int i=0;i<level;i++) > spaces+=" "; > for (tree::iterator o=t.begin();o!=t.end();o++){ > std::cout<<spaces > <<o->second.option.name > <<" > ("<<pt.groups[o->second.grpix].group<<")" > <<"\n"; > if (!o->second.sub.empty()) > prtree(pt,o->second.sub,level+1); > } > } > > void printtree(parsertree &t) > { > prtree(t,t.ptree); > } > > //Parsertree funetions - end > > --------------------------------------------------- > >>From STAFCommandParser.h: > > struct twig; > typedef std::map<int,twig> tree; > > struct opt{ > opt(); > > STAFString name; > unsigned int numAllowed; > STAFCommandParser::ValueRequirement valueRequirement; > }; > > struct twig{ > tree sub; > opt option; > unsigned int grpix; > }; > > struct ogrp{ > STAFString group; > unsigned int minimum,maximum; > }; > > typedef std::map<int,ogrp> glist; > > struct parsertree{ > tree ptree; > glist groups; > }; > > parsertree getParsertree(STAFCommandParser &p); > void printtree(parsertree &t); > ------------------------------------------------------------------------------ > ThinkGeek and WIRED's GeekDad team up for the Ultimate > GeekDad Father's Day Giveaway. ONE MASSIVE PRIZE to the > lucky parental unit. See the prize list and enter to win: > http://p.sf.net/sfu/thinkgeek-promo > _______________________________________________ > staf-users mailing list > staf-users@lists.sourceforge.net > https://lists.sourceforge.net/lists/listinfo/staf-users > > ------------------------------------------------------------------------------ ThinkGeek and WIRED's GeekDad team up for the Ultimate GeekDad Father's Day Giveaway. ONE MASSIVE PRIZE to the lucky parental unit. See the prize list and enter to win: http://p.sf.net/sfu/thinkgeek-promo _______________________________________________ staf-users mailing list staf-users@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/staf-users