def get_short_option_with_angle_bracket(self, current, token): lt_index = current.find('<') prepended = False arg_token = None if self.stdopt and self.attachopt: # -a<sth> -> -a <sth>; -abc<sth> -> -a -bc<sth> if not self.attachvalue: raise DocpieError( "You can't write %s while attachvalue=False" % current) flag = current[:2] # -abc<sth> if lt_index > 2: token.insert(0, '-' + current[2:]) prepended = True # -a<sth> else: arg_token = Token([current[lt_index:]]) # rest = atom[lt_index:] # -a<sth> -> -a <sth>; -abc<sth> -> -abc <sth> else: flag = current[:lt_index] arg_token = Token([current[lt_index:]]) return flag, arg_token, prepended
def get_short_option_arg(self, current, token, arg_token, rest): prepended = False opt_2_ins = {} # TODO: Better solution, maybe cache one for options in self.titled_opt_to_ins.values(): opt_2_ins.update(options) if current in opt_2_ins: ins = opt_2_ins[current][0] # In Options it requires no argument if ins.ref is None: # sth stacked with it if rest: if Atom.get_class(rest)[0] is Argument: raise DocpieError( ('%s announced difference in ' 'Options(%s) and Usage(%s)') % (current, ins, current)) if not (self.stdopt and self.attachopt): raise DocpieError( ("You can't write %s while it requires " "argument and attachopt=False") % current) token.insert(0, '-' + rest) prepended = True # In Options it requires argument else: if rest: arg_token = Token([rest]) elif arg_token: pass else: _current = token.current() if _current in '([': tk = [token.next()] tk.extend(token.till_end_bracket(tk[0])) tk.append(')' if tk[0] == '(' else ']') arg_token = Token(tk) elif _current in ('...', '|'): raise DocpieError( ('%s requires argument in Options(%s) ' 'but hit "%s" in Usage') % current, ins, _current) else: arg_token = Token([token.next()]) if token.current() == '...': arg_token.append(token.next()) elif rest: if not (self.stdopt and self.attachopt): raise DocpieError( "You can't write %s while it requires argument " "and attachopt=False" % current) # -asth -> -a -sth token.insert(0, '-' + rest) prepended = True return arg_token, prepended
def parse_other_element(self, current, token): atom_class, title = Atom.get_class(current) if atom_class is OptionsShortcut: return self.parse_options_shortcut(title, token) args = set([current]) if atom_class is Option: for options in self.titled_opt_to_ins.values(): if current in options: ins_in_opt = options[current][0] args.update(ins_in_opt.names) if ins_in_opt.ref is not None: ref_current = token.next() ref_token = Token() if ref_current in '([': ref_token.append(ref_current) ref_token.extend( token.till_end_bracket(ref_current) ) ref_token.append( ')' if ref_current == '(' else ']' ) else: ref_token.extend(('(', ref_current, ')')) ref_ins = self.parse_pattern(ref_token) logger.debug(ins_in_opt.ref) logger.debug(ref_ins[0]) if len(ref_ins) != 1: raise DocpieError( ('%s announced difference in ' 'Options(%s) and Usage(%s)') % (current, ins_in_opt, ref_ins)) if ins_in_opt.ref != ref_ins[0]: raise DocpieError( ('%s announced difference in ' 'Options(%s) and Usage(%s)') % (current, ins_in_opt, ref_ins)) ins = atom_class(*args, **{'ref': ins_in_opt.ref}) return (ins,) ins = atom_class(*args) repeat = token.check_ellipsis_and_drop() if repeat: ins = Required(ins, repeat=True) logger.debug('%s -> %s', current, ins) return (ins,)
def parse_2_instance(self, name): result = [] for each_line in self.split_line_by_indent(self.formal_content): raw_str_lis = self.parse_line_to_lis(each_line, name) chain = self.parse_pattern(Token(raw_str_lis)) result.append(chain) self.instances = result
def get_long_option_with_arg(self, current, token): flag, arg = current.split('=', 1) if Atom.get_class(flag)[0] is Option: if arg: arg_token = Token([arg]) else: next_arg = token.next() if next_arg not in '([': raise DocpieError('format error: %s' % current) tk = [next_arg] tk.extend(token.till_end_bracket(next_arg)) tk.append(')' if next_arg == '(' else ']') arg_token = Token(tk) if token.current() == '...': arg_token.append(token.next()) return flag, arg_token
def parse_other_element(self, current, token): atom_class, title = Atom.get_class(current) if atom_class is OptionsShortcut: return self.parse_options_shortcut(title, token) args = set([current]) if atom_class is Option: for options in self.titled_opt_to_ins.values(): if current in options: ins_in_opt = options[current][0] args.update(ins_in_opt.names) if ins_in_opt.ref is not None: ref_current = token.next() ref_token = Token() if ref_current in '([': ref_token.append(ref_current) ref_token.extend(token.till_end_bracket(ref_current)) ref_token.append(')' if ref_current == '(' else ']') else: ref_token.extend(('(', ref_current, ')')) ref_ins = self.parse_pattern(ref_token) logger.debug(ins_in_opt.ref) logger.debug(ref_ins[0]) if len(ref_ins) != 1: raise DocpieError( '%s announced difference in Options(%s) and Usage(%s)' % (current, ins_in_opt, ref_ins)) if ins_in_opt.ref != ref_ins[0]: raise DocpieError( '%s announced difference in Options(%s) and Usage(%s)' % (current, ins_in_opt, ref_ins)) ins = atom_class(*args, **{'ref': ins_in_opt.ref}) return (ins,) ins = atom_class(*args) repeat = token.check_ellipsis_and_drop() if repeat: ins = Required(ins, repeat=True) logger.debug('%s -> %s', current, ins) return (ins,)
def parse_bracket(self, token): start = token.next() instance_type = Required if start == '(' else Optional lis = token.till_end_bracket(start) repeat = token.check_ellipsis_and_drop() bracket_token = Token(lis) instances = self.parse_pattern(bracket_token) return instance_type(*instances, **{'repeat': repeat})
def parse_opt_str(self, opt): repeat = False # -sth=<goes> ON -> -sth, <goes>, ON opt_lis = self.opt_str_to_list(opt) logger.debug('%r -> %s' % (opt, opt_lis)) first = opt_lis.pop(0) if not first.startswith('-'): raise DocpieError('option %s does not start with "-"' % first) # if self.stdopt: # -sth -> name=-s, value=th # else: # -sth -> name=-sth, value='' name, value = self.split_short_by_cfg(first) opt_ins = Option(name) if value == '...': repeat = True # -f... <sth> if opt_lis and not opt_lis[0].startswith('-'): raise DocpieError( 'option "%s" has argument following "..."', opt) elif value: args_ins = [Required(Argument(value))] else: args_ins = [] if opt_lis and opt_lis[0] == '...': repeat = True opt_lis.pop(0) if opt_lis and not opt_lis[0].startswith('-'): raise DocpieError( 'option "%s" has argument following "..."', opt) args = [] # store the current args after option for each in opt_lis: if each.startswith('-'): # alias name, value = self.split_short_by_cfg(each) opt_ins.names.add(name) if value: args_ins.append(Required(Argument(value))) if args: # trun it into instance if args[0] == '...': if len(args) != 1: raise DocpieError( 'Error in %s: "..." followed by non option', opt) repeat = True else: this_arg = Required( *self.parse_pattern(Token(args)) ).fix() if this_arg is not None: args_ins.append(this_arg) del args[:] else: args.append(each) else: if args: # trun it into instance if args[0] == '...': if len(args) != 1: raise DocpieError( 'Error in %s: "..." followed by non option', opt) repeat = True else: this_arg = Required( *self.parse_pattern(Token(args))).fix() if this_arg is not None: args_ins.append(this_arg) # option without any args if not args_ins: return opt_ins, repeat # in Option, there should only have one arg list # e.g.: -f <file> --file=FILE -> -f/--file (<file>|FILE) # because the arg name will now be shown, it parsed as: # -f <file> --file=FILE -> -f/--file (<file>) current_ins = args_ins.pop(0) current_range = current_ins.arg_range() # avoid e.g.: -f <a> <b> --file <c> for other_ins in args_ins: this_range = other_ins.arg_range() if this_range != current_range: raise DocpieError("%s announced differently (%s, %s)" % ( opt_ins, this_range, current_range)) if len(current_range) > 1: logger.debug('too many possibilities: ' 'option %s expect %s arguments', name, '/'.join(map(str, current_range))) # TODO: check if current_ins contain Command(not allowed in fact) opt_ins.ref = current_ins return opt_ins, repeat