stlinkv2.py now works with newer PyUSB
[gnuk/gnuk.git] / tool / sexp.py
1 # SEXP (S-expressions) Basic Transport Support
2 #
3 # See: http://people.csail.mit.edu/rivest/sexp.html
4 #
5 """
6 sexp.py - a library for SEXP
7
8 Copyright (C) 2013 Free Software Initiative of Japan
9 Author: NIIBE Yutaka <gniibe@fsij.org>
10
11 This file is a part of Gnuk, a GnuPG USB Token implementation.
12
13 Gnuk is free software: you can redistribute it and/or modify it
14 under the terms of the GNU General Public License as published by
15 the Free Software Foundation, either version 3 of the License, or
16 (at your option) any later version.
17
18 Gnuk is distributed in the hope that it will be useful, but WITHOUT
19 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
20 or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
21 License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program.  If not, see <http://www.gnu.org/licenses/>.
25 """
26
27 import re
28
29 WHITESPACE='[ \n\t\v\r\f]+'
30 re_ws = re.compile(WHITESPACE)
31 DIGITS='[0-9]+'
32 re_digit = re.compile(DIGITS)
33
34 def skip_whitespace(string, pos):
35     m = re_ws.match(string, pos)
36     if m:
37         return m.start()
38     else:
39         return pos
40
41 def sexp_match(string, ch, pos):
42     pos = skip_whitespace(string,pos)
43     if string[pos] == ch:
44         return pos+1
45     else:
46         raise ValueError("expect '%s'" % ch)
47
48 def sexp_parse_simple_string(string, pos):
49     pos = skip_whitespace(string,pos)
50     m = re_digit.match(string, pos)
51     if m:
52         length = int(string[m.start():m.end()],10)
53         pos = sexp_match(string, ':', m.end())
54         return (string[pos:pos+length], pos+length)
55     else:
56         raise ValueError('expect digit')
57
58 def sexp_parse_list(string,pos):
59     l = []
60     while True:
61         pos = skip_whitespace(string,pos)
62         if string[pos] == ')':
63             return (l, pos)
64         else:
65             (sexp, pos) = sexp_parse(string,pos)
66             l.append(sexp)
67
68 def sexp_parse(string, pos=0):
69     pos = skip_whitespace(string,pos)
70     if string[pos] == '(':
71         (l, pos) = sexp_parse_list(string,pos+1)
72         pos = sexp_match(string, ')', pos)
73         return (l, pos)
74     elif string[pos] == '[':
75         pos = skip_whitespace(string,pos)
76         (dsp, pos) = sexp_parse_simple_string(string,pos+1)
77         pos = sexp_match(string, ']', pos)
78         pos = skip_whitespace(string,pos)
79         (ss, pos) = sexp_parse_simple_string(string, pos)
80         return ((dsp, ss), pos)
81     else:
82         return sexp_parse_simple_string(string, pos)
83
84 def sexp(string):
85     (sexp, pos) = sexp_parse(string)
86     return sexp