source: tagsplugin/tags/0.3rc1/tractags/parseargs.py

Last change on this file was 1774, checked in by Alec Thomas, 18 years ago
  • Fix so arg parsing works with new unicode code in trunk.
File size: 3.1 KB
Line 
1"""
2    Basic parsing of arguments into a non-keyword list and keyword dictionary.
3"""
4
5import re
6
7class UnexpectedEndOfInput(Exception): pass
8class InvalidToken(Exception): pass
9class UnexpectedToken(Exception): pass
10
11class Lexer(object):
12    """ Convenience wrapper around tokenize.generate_tokens """
13    _lexer = re.compile(r'''([][(),=]|"[^"]*"|'[^']*'|[^][(),=\s]+)''')
14
15    def __init__(self, string):
16        tokens = self._lexer.findall(string)
17        self.tokens = []
18        for token in tokens:
19            type = 1
20            if token[0] in '\'"':
21                type = 3
22            self.tokens.append((type, token))
23
24    def __iter__(self):
25        return self
26
27    def next(self):
28        if self.tokens:
29            token = self.tokens.pop(0)
30            return token
31        raise StopIteration
32
33    def push_token(self, token):
34        self.tokens.insert(0, token)
35
36def parseargs(arguments):
37    """ Parse a python-like set of arguments. """
38    def parse_dict(lexer):
39        out = {}
40        try:
41            for type, token in lexer:
42                if token == '}':
43                    return out
44                lexer.push_token((type, token))
45                key = parse_value(lexer)
46                type, token = lexer.get_token()
47                if token[1] not in '=:':
48                    raise UnexpectedToken(token)
49                value = parse_node(lexer)
50        except StopIteration:
51            pass
52        raise UnexpectedEndOfInput
53
54    def parse_array(lexer):
55        out = []
56        try:
57            for type, token in lexer:
58                if out and token == ',':
59                    type, token = lexer.next()
60                if token in '])':
61                    return out
62                lexer.push_token((type, token))
63                out.append(parse_node(lexer))
64        except StopIteration:
65            pass
66        raise UnexpectedEndOfInput
67       
68    def parse_value(lexer):
69        type, token = lexer.next()
70        if type == 2:
71            return float(token)
72        elif type == 3:
73            return token[1:-1]
74        elif type in (1, 51):
75            return token
76        else:
77            raise InvalidToken(token)
78
79    def parse_node(lexer):
80        type, token = lexer.next()
81        if token in '([':
82            return parse_array(lexer)
83        elif token == '{':
84            return parse_dict(lexer)
85        else:
86            lexer.push_token((type, token))
87            return parse_value(lexer)
88           
89    lexer = Lexer(arguments)
90    args = []
91    kwargs = {}
92
93    try:
94        while True:
95            arg = parse_value(lexer)
96            try:
97                type, token = lexer.next()
98            except StopIteration:
99                args.append(arg)
100                break
101            if token == '=':
102                kwargs[str(arg)] = parse_node(lexer)
103                type, token = lexer.next()
104                if token != ',':
105                    raise UnexpectedToken(token)
106            elif token == ',':
107                args.append(arg)
108    except StopIteration:
109        pass
110    return args, kwargs
111
112if __name__ == '__main__':
113    print parseargs('foo, bar')
Note: See TracBrowser for help on using the repository browser.