Atlas  0.7.0
Networking protocol for the Worldforge system.
bach.py
1 #Bach parser and generator
2 
3 #Copyright 2001 by Aloril
4 #Copyright 2002 by AIR-IX SUUNNITTELU/Ahiplan Oy
5 
6 #This library is free software; you can redistribute it and/or
7 #modify it under the terms of the GNU Lesser General Public
8 #License as published by the Free Software Foundation; either
9 #version 2.1 of the License, or (at your option) any later version.
10 
11 #This library is distributed in the hope that it will be useful,
12 #but WITHOUT ANY WARRANTY; without even the implied warranty of
13 #MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 #Lesser General Public License for more details.
15 
16 #You should have received a copy of the GNU Lesser General Public
17 #License along with this library; if not, write to the Free Software
18 #Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 
20 
21 import string
22 import atlas
23 from atlas.typemap import *
24 
25 from atlas.gen_bach import *
26 import encoder, decoder
27 
28 class BachException(Exception): pass
29 
31  begin_string = "[\n"
32  middle_string = ",\n"
33  end_string = "\n]\n"
34  empty_end_string = "[]\n"
35 
36  def encode1stream(self, object):
37  return "\t" + encode(object, "\t")
38 
39  def encode1(self, object):
40  return gen_bach(object)
41 
42 
43 
44 def get_encoder(stream_flag=None):
45  return Encoder(stream_flag)
46 
47 
48 
49 
50 class Context:
51  def __init__(self, value, excepted_value=""):
52  self.valuevalue = value
53  self.excepted_valueexcepted_value = excepted_value # "map_name", "map_value", "list_value"
54  self.namename = None
55  def __repr__(self):
56  return "Context(%s, %s, %s)" % (repr(self.valuevalue), self.excepted_valueexcepted_value, self.namename)
57 
59  def __init__(self, stream_flag=None):
60  """uses tree that start from root_obj, current route to leave
61  is kept in obj_stack"""
62  #Root object is never removed or visible for parser users,
63  #incoming objects are added to its value
64  #resulting complete atlas 'messages' are added here
65  self.stackstack = []
66  self.modemode = self.skip_white_spaceskip_white_space
67  self.linenolineno = 1
68  self.setupsetup(stream_flag=None)
69 
70  def eos(self):
71  """end of stream"""
72  return not self.datadata and not self.stackstack
73 
74  def feed(self, msg):
75  #import pdb; pdb.set_trace()
76  for ch in msg:
77  #print ch
78  if ch=="\n":
79  self.linenolineno = self.linenolineno + 1
80  self.modemode(ch)
81 
82  def context(self):
83  return self.stackstack[-1]
84 
85  def add_value(self):
86  value = self.stackstack.pop().value
87  c = self.contextcontext()
88  obj = c.value
89  if c.excepted_value == "map_name":
90  if not isinstance(obj, atlas.Object):
91  raise BachException("attribute name outside mapping (%s)!" % \
92  (value))
93  c.name = value
94  c.excepted_value = "map_value"
95  elif c.excepted_value == "map_value":
96  if not isinstance(obj, atlas.Object):
97  raise BachException("attribute value outside mapping (%s:%s)!" % \
98  (c.name, value))
99  if not isinstance(c.name, str):
100  c.name = str(c.name)
101  setattr(obj, c.name, value)
102  c.excepted_value = "map_name"
103  elif c.excepted_value == "list_value":
104  if not isinstance(obj, list):
105  raise BachException("object not inside list (%s)!" % value)
106  obj.append(value)
107  else:
108  raise BachException("unknown container (%s)!" % value)
109  self.modemode = self.skip_white_spaceskip_white_space
110 
111  def push(self, value, mode = None, ch=None, excepted_value=""):
112  self.stackstack.append(Context(value, excepted_value))
113  if mode: self.modemode = mode
114  else: self.modemode = self.skip_white_spaceskip_white_space
115  if ch: self.modemode(ch)
116 
117  def pop(self):
118  if self.stream_flagstream_flag:
119  if len(self.stackstack)>1:
120  self.add_valueadd_value()
121  if len(self.stackstack)==1:
122  obj=self.stackstack[0].value.pop(0)
123  self.msgListmsgList.append(obj)
124  else:
125  self.stackstack.pop() #stream is closed now really...
126  else:
127  if len(self.stackstack)==1:
128  obj=self.stackstack.pop().value
129  self.msgListmsgList.append(obj)
130  else:
131  self.add_valueadd_value()
132 
133  def get_next_mode(self, ch):
134  if ch=="{":
135  self.pushpush(atlas.Object(), excepted_value="map_name")
136  elif ch=="[":
137  self.pushpush([], excepted_value="list_value")
138  elif ch in "}]":
139  self.poppop()
140  elif ch in int_characters:
141  self.pushpush("", self.intint, ch)
142  elif ch=='"':
143  self.pushpush("", self.stringstring)
144  elif ch in plain_name_characters:
145  self.pushpush("", self.namename, ch)
146  elif ch in ",:" + string.whitespace:
147  self.modemode = self.skip_white_spaceskip_white_space
148  elif ch=="#":
149  self.modemode = self.add_commentadd_comment
150  else:
151  raise BachException("illegal character (%s (%s) at line %i)!" % (ch, ord(ch), self.linenolineno))
152 
153  def add_comment(self, ch):
154  #CHEAT: should add comment field
155  if ch=="\n":
156  self.modemode = self.skip_white_spaceskip_white_space
157  return
158 
159  def skip_white_space(self, ch):
160  if ch in string.whitespace:
161  return
162  self.get_next_modeget_next_mode(ch)
163 
164  def int(self, ch):
165  c = self.contextcontext()
166  if ch in int_characters:
167  c.value = c.value + ch
168  elif ch in float_characters:
169  self.modemode = self.floatfloat
170  self.modemode(ch)
171  else:
172  try:
173  c.value = int(c.value)
174  except ValueError:
175  c.value = int(c.value)
176  self.add_valueadd_value()
177  self.get_next_modeget_next_mode(ch)
178 
179  def float(self, ch):
180  c = self.contextcontext()
181  if ch in float_characters:
182  c.value = c.value + ch
183  else:
184  c.value = float(c.value)
185  self.add_valueadd_value()
186  self.get_next_modeget_next_mode(ch)
187 
188  def quote(self, ch):
189  c = self.contextcontext()
190  c.value = c.value + ch
191  self.modemode = self.stringstring
192 
193  def string(self, ch):
194  c = self.contextcontext()
195  if ch=="\\":
196  self.modemode = self.quotequote
197  elif ch!='"':
198  c.value = c.value + ch
199  else:
200  self.add_valueadd_value()
201 
202  def name(self, ch):
203  c = self.contextcontext()
204  if ch in plain_name_characters:
205  c.value = c.value + ch
206  elif ch in ":" + string.whitespace:
207  self.add_valueadd_value()
208  else:
209  raise BachException("illegal character (%s)!" % ch)
210 
211 def get_decoder(stream_flag=None):
212  bach_msg_parser=BachParser(stream_flag)
213  return bach_msg_parser
def float(self, ch)
Definition: bach.py:179
def __init__(self, stream_flag=None)
Definition: bach.py:59
def quote(self, ch)
Definition: bach.py:188
def push(self, value, mode=None, ch=None, excepted_value="")
Definition: bach.py:111
def name(self, ch)
Definition: bach.py:202
def int(self, ch)
Definition: bach.py:164
def skip_white_space(self, ch)
Definition: bach.py:159
def get_next_mode(self, ch)
Definition: bach.py:133
def add_comment(self, ch)
Definition: bach.py:153
def string(self, ch)
Definition: bach.py:193
def setup(self, stream_flag=None)
Definition: decoder.py:23