def parse_atom(tokens, options):
    """atom ::= '(' expr ')' | '[' expr ']' | 'options'
             | long | shorts | argument | command ;
    """
    token = tokens.current()
    result = []
    if token == '(':
        tokens.move()
        result = [Required(*parse_expr(tokens, options))]
        if tokens.move() != ')':
            raise tokens.error("Unmatched '('")
        return result
    elif token == '[':
        tokens.move()
        result = [Optional(*parse_expr(tokens, options))]
        if tokens.move() != ']':
            raise tokens.error("Unmatched '['")
        return result
    elif token == 'options':
        tokens.move()
        return [AnyOptions()]
    elif token.startswith('--') and token != '--':
        return parse_long(tokens, options)
    elif token.startswith('-') and token not in ('-', '--'):
        return parse_shorts(tokens, options)
    elif token.startswith('<') and token.endswith('>') or token.isupper():
        return [Argument(tokens.move())]
    else:
        return [Command(tokens.move())]
dataset/ETHPy150Open kmike/port-for/port_for/docopt.py/parse_atom/original