forked from Qortal/Brooklyn
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
86 lines
2.5 KiB
86 lines
2.5 KiB
# SEXP (S-expressions) Basic Transport Support |
|
# |
|
# See: http://people.csail.mit.edu/rivest/sexp.html |
|
# |
|
""" |
|
sexp.py - a library for SEXP |
|
|
|
Copyright (C) 2013 Free Software Initiative of Japan |
|
Author: NIIBE Yutaka <[email protected]> |
|
|
|
This file is a part of Gnuk, a GnuPG USB Token implementation. |
|
|
|
Gnuk is free software: you can redistribute it and/or modify it |
|
under the terms of the GNU General Public License as published by |
|
the Free Software Foundation, either version 3 of the License, or |
|
(at your option) any later version. |
|
|
|
Gnuk is distributed in the hope that it will be useful, but WITHOUT |
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY |
|
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public |
|
License for more details. |
|
|
|
You should have received a copy of the GNU General Public License |
|
along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
""" |
|
|
|
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
|
|
|