From 6b6913c676e1b94521cdcff8ff2d114730bf483e Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Mon, 21 Jan 2013 10:31:18 +0900 Subject: [PATCH] add tool/sexp.py --- ChangeLog | 4 ++++ tool/sexp.py | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+) create mode 100644 tool/sexp.py diff --git a/ChangeLog b/ChangeLog index 7f91840..ecb14f5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2013-01-21 Niibe Yutaka + + * tool/sexp.py: New. + 2013-01-20 Niibe Yutaka * tool/gpg_agent.py: New. diff --git a/tool/sexp.py b/tool/sexp.py new file mode 100644 index 0000000..a705054 --- /dev/null +++ b/tool/sexp.py @@ -0,0 +1,65 @@ +# SEXP (S-expressions) Basic Transport Support +# +# See: http://people.csail.mit.edu/rivest/sexp.html +# + +import re + +WHITESPACE='[ \n\t\v\r\f]+' +re_ws = re.compile(WHITESPACE) +DIGITS='[0-9]+' +re_digit = re.compile(DIGITS) + +def skip_whitespace(string, pos): + m = re_ws.match(string, pos) + if m: + return m.start() + else: + return pos + +def sexp_match(string, ch, pos): + pos = skip_whitespace(string,pos) + if string[pos] == ch: + return pos+1 + else: + raise ValueError("expect '%s'" % ch) + +def sexp_parse_simple_string(string, pos): + pos = skip_whitespace(string,pos) + m = re_digit.match(string, pos) + if m: + length = int(string[m.start():m.end()],10) + pos = sexp_match(string, ':', m.end()) + return (string[pos:pos+length], pos+length) + else: + raise ValueError('expect digit') + +def sexp_parse_list(string,pos): + l = [] + while True: + pos = skip_whitespace(string,pos) + if string[pos] == ')': + return (l, pos) + else: + (sexp, pos) = sexp_parse(string,pos) + l.append(sexp) + +def sexp_parse(string, pos=0): + pos = skip_whitespace(string,pos) + if string[pos] == '(': + (l, pos) = sexp_parse_list(string,pos+1) + pos = sexp_match(string, ')', pos) + return (l, pos) + elif string[pos] == '[': + pos = skip_whitespace(string,pos) + (dsp, pos) = sexp_parse_simple_string(string,pos+1) + pos = sexp_match(string, ']', pos) + pos = skip_whitespace(string,pos) + (ss, pos) = sexp_parse_simple_string(string, pos) + return ((dsp, ss), pos) + else: + return sexp_parse_simple_string(string, pos) + +def sexp(string): + (sexp, pos) = sexp_parse(string) + return sexp