source: proto/charsetcompiler/charset_compiler2.py @ 2997

Last change on this file since 2997 was 2997, checked in by cameron, 6 years ago

Alternative character set compiler better in some cases

File size: 23.0 KB
Line 
1#
2#  Character Class Compiler
3#
4#  Version 0.8 - Feb. 17, 2012
5#     Add command-line option for specifying basis_pattern
6#  Copyright (c) 2007-12, Robert D. Cameron
7#  All rights reserved.
8#
9#  TO DO Notes
10#
11#  1.  Perhaps the character set definition should be extended to
12#      allow other set operations.   For example, the 'Restricted' set
13#      of XML might be defined as ['\x00-\x1f'] - ['\x09', '\x0a', '\x0d']
14#      This would require fewer operations to compute.
15#
16#  2.  The range logic generator should be modified to group
17#      bit variables the same way as the individual character logic
18#      generator (i.e., combining bits 0 and 1, 2 and 3, 4 and 5 and
19#      6 and 7 first.
20#
21#  3.  Extend for 16-bit and full Unicode character values.
22#
23#
24#--------------------------------------------------------------------------
25#
26#  Data types
27#  1. Character Set Definitions
28#  2. Boolean Expressions
29#  3. Code Generator Objects
30#
31import sys, optparse
32import re, binascii, string
33import EBCDIC
34
35import charset_def
36CharDef = charset_def.CharDef
37CharSetDef = charset_def.CharSetDef
38
39import charsets
40DefinitionSet = charsets.DefinitionSet
41
42import charset_input_parser
43
44#
45# Symbolic Representations of Boolean Expressions
46#
47
48class BoolExpr:
49   """The BoolExpr class and its subclasses provide a symbolic
50      representation of Boolean expressions.
51   """
52   pass
53
54class Var(BoolExpr):
55    def __init__(self, varname):
56        self.varname = varname
57    def show(self): return 'Var("' + self.varname + '")'
58
59class TrueLiteral(BoolExpr):
60    def __init__(self):
61        self.value = True
62    def show(self): return 'T'
63
64class FalseLiteral(BoolExpr):
65    def __init__(self):
66        self.value = False
67    def show(self): return 'F'
68
69class Not(BoolExpr):
70    def __init__(self, expr):
71        self.operand = expr
72    def show(self): return 'Not(%s)' % (self.operand.show())
73
74class And(BoolExpr):
75    def __init__(self, expr1, expr2):
76        self.operand1 = expr1
77        self.operand2 = expr2
78    def show(self): return 'And(%s, %s)' % (self.operand1.show(), self.operand2.show())
79
80class Or(BoolExpr):
81    def __init__(self, expr1, expr2):
82        self.operand1 = expr1
83        self.operand2 = expr2
84    def show(self): return 'Or(%s, %s)' % (self.operand1.show(), self.operand2.show())
85
86class Xor(BoolExpr):
87    def __init__(self, expr1, expr2):
88        self.operand1 = expr1
89        self.operand2 = expr2
90    def show(self): return 'Xor(%s, %s)' % (self.operand1.show(), self.operand2.show())
91
92class Sel(BoolExpr):
93    def __init__(self, expr1, expr2, expr3):
94        self.sel = expr1
95        self.true_branch = expr2
96        self.false_branch = expr3
97    def show(self): return 'Sel(%s, %s, %s)' % (self.sel.show(), self.true_branch.show(), self.false_branch.show())
98
99
100#
101# Optimizing Constructors for Boolean Expressions
102# - Maintaining Assembler Instruction Form:
103#   - All boolean algebraic rules involving true/false applied.
104#   - Negations restricted:
105#       - no negations within or (DeMorgan's to nand)
106#       - at most one negation within and
107#
108
109def make_not(expr):
110    if isinstance(expr, TrueLiteral):
111        return FalseLiteral()
112    elif isinstance(expr, FalseLiteral):
113        return TrueLiteral()
114    elif isinstance(expr, Not):
115        return expr.operand
116    else: return Not(expr)
117
118def make_and(expr1, expr2):
119    if isinstance(expr1, TrueLiteral):
120        return expr2
121    elif isinstance(expr2, TrueLiteral):
122        return expr1
123    elif isinstance(expr1, FalseLiteral):
124        return FalseLiteral()
125    elif isinstance(expr2, FalseLiteral):
126        return FalseLiteral()
127    elif equal_exprs(expr1, expr2): return expr1
128    elif isinstance(expr1, Not):
129        if isinstance(expr2, Not):
130            return make_not(make_or(expr1.operand, expr2.operand))
131        elif equal_exprs(expr1.operand, expr2): return FalseLiteral()
132        else: return And(expr1, expr2)
133    elif isinstance(expr2, Not):
134        if equal_exprs(expr1, expr2.operand): return FalseLiteral()
135        else: return And(expr1, expr2)
136    else: return And(expr1, expr2)
137
138def make_or(expr1, expr2):
139    if isinstance(expr1, FalseLiteral):
140        return expr2
141    elif isinstance(expr2, FalseLiteral):
142        return expr1
143    elif isinstance(expr1, TrueLiteral):
144        return TrueLiteral()
145    elif isinstance(expr2, TrueLiteral):
146        return TrueLiteral()
147    elif isinstance(expr1, Not):
148        return make_not(make_and(expr1.operand, make_not(expr2)))
149    elif isinstance(expr2, Not):
150        return make_not(make_and(make_not(expr1), expr2.operand))
151    elif equal_exprs(expr1, expr2): return expr1
152    elif isinstance(expr1, And) and isinstance(expr2, And):
153        # These optimizations factor out common components that
154        # can occur when sets are formed by union (e.g., union of
155        # [a-z] and [A-Z].
156        if equal_exprs(expr1.operand1, expr2.operand1):
157            return make_and(expr1.operand1, make_or(expr1.operand2, expr2.operand2))
158        elif equal_exprs(expr1.operand2, expr2.operand2):
159            return make_and(expr1.operand2, make_or(expr1.operand1, expr2.operand1))
160        elif equal_exprs(expr1.operand1, expr2.operand2):
161            return make_and(expr1.operand1, make_or(expr1.operand2, expr2.operand1))
162        elif equal_exprs(expr1.operand2, expr2.operand1):
163            return make_and(expr1.operand2, make_or(expr1.operand1, expr2.operand2))
164        else: return Or(expr1, expr2)
165    else: return Or(expr1, expr2)
166
167def make_sel(if_expr, T_expr, F_expr):
168    if isinstance(if_expr, TrueLiteral):
169        return T_expr
170    elif isinstance(if_expr, FalseLiteral):
171        return F_expr
172    elif isinstance(T_expr, TrueLiteral):
173        # if x then T else y = x or y
174        return make_or(if_expr, F_expr) 
175    elif isinstance(T_expr, FalseLiteral):
176        # if x then F else y = not(x) and y
177        return make_and(make_not(if_expr), F_expr) 
178    elif isinstance(F_expr, FalseLiteral):
179        # if x then y else F = x and y
180        return make_and(if_expr, T_expr) 
181    elif isinstance(F_expr, TrueLiteral):
182        # if x then y else T = not(x) or y
183        return make_or(make_not(if_expr), T_expr)
184    elif equal_exprs(T_expr, F_expr):
185        return T_expr
186    else: return Sel(if_expr, T_expr, F_expr)
187
188
189def make_xor(expr1, expr2):
190    if isinstance(expr1, FalseLiteral):
191        return expr2
192    elif isinstance(expr2, FalseLiteral):
193        return expr1
194    elif isinstance(expr1, TrueLiteral):
195        return make_not(expr2)
196    elif isinstance(expr2, TrueLiteral):
197        return make_not(expr1)
198    elif isinstance(expr1, Not) and isinstance(expr2, Not):
199        return make_xor(expr1.operand, expr2.operand)
200    else: return Xor(expr1, expr2)
201
202# Return True if e1 and e2 can be proven equivalent according
203# to some rules, False otherwise.   Note that False may
204# be returned in some cases when the exprs are equivalent.
205def equal_exprs(e1, e2):
206    if isinstance(e1, FalseLiteral): return isinstance(e2, FalseLiteral)
207    elif isinstance(e1, TrueLiteral): return isinstance(e2, TrueLiteral)
208    elif isinstance(e1, Var) and isinstance(e2, Var):
209        return e1.varname == e2.varname
210    elif isinstance(e1, Not) and isinstance(e2, Not):
211        return equal_exprs(e1.operand, e2.operand)
212    elif isinstance(e1, And) and isinstance(e2, And):
213        if equal_exprs(e1.operand1, e2.operand1):
214            return equal_exprs(e1.operand2, e2.operand2)
215        elif equal_exprs(e1.operand1, e2.operand2):
216            return equal_exprs(e1.operand2, e2.operand1)
217        else: return False
218    elif isinstance(e1, Or) and isinstance(e2, Or):
219        if equal_exprs(e1.operand1, e2.operand1):
220            return equal_exprs(e1.operand2, e2.operand2)
221        elif equal_exprs(e1.operand1, e2.operand2):
222            return equal_exprs(e1.operand2, e2.operand1)
223        else: return False
224    elif isinstance(e1, Xor) and isinstance(e2, Xor):
225        if equal_exprs(e1.operand1, e2.operand1):
226            return equal_exprs(e1.operand2, e2.operand2)
227        elif equal_exprs(e1.operand1, e2.operand2):
228            return equal_exprs(e1.operand2, e2.operand1)
229        else: return False
230    elif isinstance(e1, Sel) and isinstance(e2, Sel):
231        if equal_exprs(e1.sel, e2.sel):
232             if equal_exprs(e1.true_branch, e2.true_branch):
233                 return equal_exprs(e1.false_branch, e2.false_branch)
234             else: return False
235        else: return False
236
237
238#
239#
240#  Boolean Expressions for Character Class Definitions
241#
242
243def bit_var(n):
244    global options
245#    return 'bit[%i]' % n
246    return options.basis_pattern % n
247
248def make_bitv(n):
249    return Var(bit_var(7-n))
250
251
252def bit_pattern_expr(pattern, selected_bits):
253    if selected_bits == 0: return TrueLiteral()
254    bit_terms = []
255    bit_no = 0
256    while selected_bits:
257      test_bit = 1 << bit_no
258      if selected_bits & test_bit:
259        if (pattern & test_bit) == 0:
260            bit_terms = [make_not(make_bitv(bit_no))] + bit_terms
261        else: bit_terms = [make_bitv(bit_no)] + bit_terms
262      else: bit_terms = [TrueLiteral()] + bit_terms
263      # Appending TrueLiteral() for nonselected bits is intended
264      # to keep consistent grouping of variables in the next loop.
265      selected_bits &= ~test_bit
266      bit_no += 1
267    while len(bit_terms) > 1:
268        new_terms = []
269        for i in range(0, len(bit_terms)/ 2):
270            new_terms.append(make_and(bit_terms[2*i], bit_terms[2*i+1]))
271        if len(bit_terms) % 2 == 1:
272            new_terms.append(bit_terms[-1])
273        bit_terms = new_terms
274    return bit_terms[0]
275   
276
277def char_test_expr(ch):
278    #return make_bit_test(ord(ch), 8)
279    return bit_pattern_expr(ord(ch), 0xFF)
280
281
282BadRange = Exception()
283
284BadCharSetItem = Exception()
285
286def char_or_range_expr(charset_item):
287    if len(charset_item) == 1:
288        return char_test_expr(charset_item[0])
289    elif len(charset_item) == 3:
290        if charset_item[1] == '-' and ord(charset_item[0]) <= ord(charset_item[2]):
291             return Make_Range(ord(charset_item[0]), ord(charset_item[2]))
292    print charset_item
293    raise BadCharSetItem
294
295def charset_expr(chardef):
296    if chardef.items == []: return FalseLiteral()
297    e1 = char_or_range_expr(chardef.items[0])
298    for i in range(1, len(chardef.items)):
299        e1 = make_or(e1, char_or_range_expr(chardef.items[i]))
300    if chardef.complemented: return make_not(e1)
301    else: return e1
302
303
304def count_leading_zeroes(strm):
305        zeroes = 0
306        while (strm & 0xFFFFFFFF) == 0: 
307                zeroes += 32
308                strm >>= 32
309        while (strm & 1) == 0:
310                zeroes += 1
311                strm >>= 1
312        return zeroes
313
314def popcount(strm): 
315        pop = 0
316        while strm > 0: 
317                p1 = (strm & 0x5555555555555555) + ((strm >> 1) & 0x5555555555555555)
318                p1 = (p1 & 0x3333333333333333) + ((p1 >> 2) & 0x3333333333333333)
319                p1 = (p1 & 0x0F0F0F0F0F0F0F0F) + ((p1 >> 4) & 0x0F0F0F0F0F0F0F0F)
320                p1 = (p1 & 0x00FF00FF00FF00FF) + ((p1 >> 8) & 0x00FF00FF00FF00FF)
321                p1 = (p1 & 0x0000FFFF0000FFFF) + ((p1 >> 16) & 0x0000FFFF0000FFFF)
322                pop += (p1 & 0x00000000FFFFFFFF) + ((p1 >> 32) & 0x00000000FFFFFFFF)
323                strm >>= 64
324        return pop
325
326#
327# New charset processing using a bitset representation
328#
329def cset_universe(N):
330  return (1<<(1<<N)) - 1
331
332def cset_intersect(s1, s2): 
333  return s1 & s2
334
335def cset_union(s1, s2):
336  return s1 | s2
337
338def cset_isempty(s):
339  return s == 0
340
341# precondition not cset_isempty(s)
342def cset_min(s):
343  return count_leading_zeroes(s)
344
345# precondition not cset_isempty(s)
346def cset_max(s):
347  s1 = s & (s - 1)
348  while not cset_isempty(s1):
349    s = s1
350    s1 = s & (s - 1)
351  return count_leading_zeroes(s)
352
353# compute [c in s if c < n]
354def cset_select_if_less(s, n):
355  return s & ((1 << n) - 1)
356
357# compute [c in s if c >= n]
358def cset_select_if_greater_or_equal(s, n):
359  return s - cset_select_if_less(s, n)
360
361def subtract_all(cset, n):
362  return cset >> n
363
364def cset_from_charset_expr(chardef):
365    cset = 0
366    for item in chardef.items:
367      if len(item) == 1:
368        cset |= 1 << ord(item[0])
369      else:
370        lo = ord(item[0])
371        hi = ord(item[2])
372        # compute a run of 1 bits of length hi - lo + 1
373        range_run = (1 << (hi - lo + 1)) - 1
374        cset |= (range_run << lo)
375    return cset
376
377#
378# Given a set of characters cset, build an expression to
379# produce a character class bit stream from the N low order
380# basis bit streams of # the transposed character representations.   
381#
382def CharSetExpr(N, cset):
383  characterMask = (1 << N) - 1
384  U = cset_universe(N)
385  #print "N = %i, cset = %x" % (N, cset)
386  if cset &~ U: # characters that cannot be represented in N bits
387    raise BadCharSetItem
388  if cset_isempty(cset): return FalseLiteral()
389  pop = popcount(cset)
390  if (pop > 2**(N-1)): return make_not(CharSetExpr(N, cset^U))
391  #if cset == U: return TrueLiteral()
392  if N == 1: 
393    if cset == 1: return make_not(make_bitv(0))
394    elif cset == 2: return make_bitv(0)
395    elif cset == 3: return TrueLiteral()
396  else:
397    h = cset_max(cset)
398    l = cset_min(cset)
399    if h == l: return bit_pattern_expr(l, characterMask)
400    diff_bits = h ^ l
401    Nd = 0
402    while diff_bits > 0:
403        Nd += 1
404        diff_bits >>= 1
405    mask = (1 << Nd) - 1
406    characterMask ^= mask
407    #print "h = %x, l = %x, Nd= %i" %(h, l, Nd)
408    hbase = h &~ (mask >> 1)
409    lbase = l &~ mask
410    # if only one bit differs, then it is a don't care.
411    if Nd == 1: return bit_pattern_expr(lbase, characterMask)
412    # hi = [c - hbase in cset if c >= hbase]
413    hi = subtract_all(cset_select_if_greater_or_equal(cset, hbase), hbase)
414    lo = subtract_all(cset_select_if_less(cset, hbase), lbase) # [c - lbase in cset if c < hbase]
415    if Nd == N: return make_sel(make_bitv(Nd-1), CharSetExpr(Nd-1, hi), CharSetExpr(Nd-1, lo))
416    c_expr = bit_pattern_expr(lbase, characterMask)
417    #print "hi = %x, lo = %x, hbase= %x, lbase= %x" %(hi, lo, hbase, lbase)
418    # heuristics
419    if hi == lo: # set equality 
420       return make_and(c_expr, CharSetExpr(Nd-1, lo))
421    #elif cset_isempty(cset_intersect(hi, lo)) and cset_union(hi,lo) == cset_universe(Nd):
422    #   return make_and(c_expr, make_xor(make_bitv(Nd-1), CharSetExpr(Nd-1, lo)))
423    #else: return make_and(c_expr, make_or(CharSetExpr(Nd, lo), CharSetExpr(Nd, hi)))
424    else: 
425      #print "hi = %x, lo = %x, Nd = %i" %(hi, lo, Nd)
426      return make_and(c_expr, make_sel(make_bitv(Nd-1), CharSetExpr(Nd-1, hi), CharSetExpr(Nd-1, lo)))
427
428
429
430
431
432def charset_expr_from_cset(chardef):
433    cset = cset_from_charset_expr(chardef)
434    return CharSetExpr(8, cset)
435   
436#
437#
438#  Code Generation
439#
440class CodeGenObject:
441    def __init__(self, predeclared, typedecl='BitBlock '):
442        self.gensym_template = options.gensym_pattern
443        self.gensym_counter = 0
444        self.generated_code = []
445        self.common_expression_map = {}
446        for sym in predeclared: self.common_expression_map[sym] = sym
447        self.typedecl = typedecl
448    def add_assignment(self, varname, expr):
449        self.common_expression_map[expr] = varname
450        #self.generated_code.append('%s%s = %s;\n' % (self.typedecl, varname, expr))
451        self.generated_code.append('\t%s%s = %s\n' % (self.typedecl, varname, expr))
452    def expr_string_to_variable(self, expr_string):
453        if self.common_expression_map.has_key(expr_string): 
454            return self.common_expression_map[expr_string]
455        else:
456            self.gensym_counter += 1
457            sym = self.gensym_template % self.gensym_counter
458            self.add_assignment(sym, expr_string)
459            return sym
460    def showcode(self):
461        s = ''
462        for stmt in self.generated_code: s += stmt
463        return s
464
465def expr2simd(genobj, expr):
466    """Translate a Boolean expression into three-address Altivec code
467       using code generator object genobj.
468    """
469    if isinstance(expr, TrueLiteral): return 'simd_const_1(1)'
470    elif isinstance(expr, FalseLiteral): return 'simd_const_1(0)'
471    elif isinstance(expr, Var): return expr.varname
472    elif isinstance(expr, Not):
473       e = genobj.expr_string_to_variable(expr2simd(genobj, expr.operand))
474       return 'simd_andc(simd_const_1(1), %s)' % (e)
475    elif isinstance(expr, Or):
476       e1 = genobj.expr_string_to_variable(expr2simd(genobj, expr.operand1))
477       e2 = genobj.expr_string_to_variable(expr2simd(genobj, expr.operand2))
478       return 'simd_or(%s, %s)' % (e1, e2)
479    elif isinstance(expr, Xor):
480       e1 = genobj.expr_string_to_variable(expr2simd(genobj, expr.operand1))
481       e2 = genobj.expr_string_to_variable(expr2simd(genobj, expr.operand2))
482       return 'simd_xor(%s, %s)' % (e1, e2)
483    elif isinstance(expr, And):
484       if isinstance(expr.operand1, Not):
485           e1 = genobj.expr_string_to_variable(expr2simd(genobj, expr.operand1.operand))
486           e2 = genobj.expr_string_to_variable(expr2simd(genobj, expr.operand2))
487           return 'simd_andc(%s, %s)' % (e2, e1)
488       elif isinstance(expr.operand2, Not):
489           e1 = genobj.expr_string_to_variable(expr2simd(genobj, expr.operand1))
490           e2 = genobj.expr_string_to_variable(expr2simd(genobj, expr.operand2.operand))
491           return 'simd_andc(%s, %s)' % (e1, e2)
492       else:
493           e1 = genobj.expr_string_to_variable(expr2simd(genobj, expr.operand1))
494           e2 = genobj.expr_string_to_variable(expr2simd(genobj, expr.operand2))
495           return 'simd_and(%s, %s)' % (e1, e2)
496    elif isinstance(expr, Sel):
497       sel = genobj.expr_string_to_variable(expr2simd(genobj, expr.sel))
498       e1 = genobj.expr_string_to_variable(expr2simd(genobj, expr.true_branch))
499       e2 = genobj.expr_string_to_variable(expr2simd(genobj, expr.false_branch))
500       return 'simd_if(%s, %s, %s)' %(sel, e1, e2)
501
502def chardef2simd(genobj, chardef):
503    genobj.add_assignment(chardef.name, expr2simd(genobj, charset_expr(chardef)))
504
505def chardeflist2simd(chardeflist):
506    cgo = CodeGenObject([bit_var(i) for i in range(0,8)])
507    for d in chardeflist:
508        chardef2simd(cgo, d)
509    return cgo.showcode()
510
511def expr2py(genobj, expr):
512    """Translate a Boolean expression into three-address python code
513       using code generator object genobj.
514    """
515    if isinstance(expr, TrueLiteral): return '-1'
516    elif isinstance(expr, FalseLiteral): return '0'
517    elif isinstance(expr, Var): return expr.varname
518    elif isinstance(expr, Not):
519       e = genobj.expr_string_to_variable(expr2py(genobj, expr.operand))
520       return '(~%s)' % (e)
521    elif isinstance(expr, Or):
522       e1 = genobj.expr_string_to_variable(expr2py(genobj, expr.operand1))
523       e2 = genobj.expr_string_to_variable(expr2py(genobj, expr.operand2))
524       return '(%s | %s)' % (e1, e2)
525    elif isinstance(expr, Xor):
526       e1 = genobj.expr_string_to_variable(expr2py(genobj, expr.operand1))
527       e2 = genobj.expr_string_to_variable(expr2py(genobj, expr.operand2))
528       return '(%s ^ %s)' % (e1, e2)
529    elif isinstance(expr, And):
530       if isinstance(expr.operand1, Not):
531           e1 = genobj.expr_string_to_variable(expr2py(genobj, expr.operand1.operand))
532           e2 = genobj.expr_string_to_variable(expr2py(genobj, expr.operand2))
533           return '(%s &~ %s)' % (e2, e1)
534       elif isinstance(expr.operand2, Not):
535           e1 = genobj.expr_string_to_variable(expr2py(genobj, expr.operand1))
536           e2 = genobj.expr_string_to_variable(expr2py(genobj, expr.operand2.operand))
537           return '(%s &~ %s)' % (e1, e2)
538       else:
539           e1 = genobj.expr_string_to_variable(expr2py(genobj, expr.operand1))
540           e2 = genobj.expr_string_to_variable(expr2py(genobj, expr.operand2))
541           return '(%s & %s)' % (e1, e2)
542    elif isinstance(expr, Sel):
543       sel = genobj.expr_string_to_variable(expr2py(genobj, expr.sel))
544       e1 = genobj.expr_string_to_variable(expr2py(genobj, expr.true_branch))
545       e2 = genobj.expr_string_to_variable(expr2py(genobj, expr.false_branch))
546       return '((%s & %s)|(~(%s) & %s))' %(sel, e1, sel, e2)
547
548def chardef2py(genobj, chardef):
549    genobj.add_assignment(chardef.name, expr2py(genobj, charset_expr_from_cset(chardef)))
550    #genobj.add_assignment(chardef.name, expr2py(genobj, charset_expr(chardef)))
551
552
553def py_chardefmap(chardeflist):
554    defs = ["'%s' : %s" % (d.name,d.name) for d in chardeflist]
555    return  '{%s}' % string.join(defs, ',\n\t')
556
557def chardeflist2py(chardeflist):
558    cgo = CodeGenObject([bit_var(i) for i in range(0,8)],'')
559    for d in chardeflist:
560        chardef2py(cgo, d) 
561    return cgo.showcode()# + "  return "+ py_chardefmap(chardeflist) + "\n"
562
563
564
565def main():
566
567    global options
568    # Option definition
569    option_parser = optparse.OptionParser(usage='python %prog [options] <input file>', version='0.8')
570
571    option_parser.add_option('-b', '--basis_pattern', 
572                             dest='basis_pattern',
573                             type='string',
574                             default='basis_bits.bit_%i',
575                             help='pattern for basis bit streams; default: basis_bits.bit_%i',
576                             )
577    option_parser.add_option('-g', '--gensym_pattern', 
578                             dest='gensym_pattern',
579                             type='string',
580                             default='temp%i',
581                             help='pattern for generated temporaries; default: temp%i',
582                             )
583    option_parser.add_option('-E', '--EBCDIC', 
584                             dest='use_EBCDIC',
585                             action='store_true', 
586                             default=False,
587                             help='generate definitions for EBCDIC input',
588                             )
589    option_parser.add_option('-p', '--pablo', 
590                             dest='Pablo_skeleton',
591                             action='store_true', 
592                             default=False,
593                             help='generate pablo skeleton',
594                             )
595    option_parser.add_option('-t', '--test', 
596                             dest='test_skeleton',
597                             action='store_true', 
598                             default=False,
599                             help='generate pablo test skeleton',
600                             )
601    options, args = option_parser.parse_args(sys.argv[1:])
602
603    # Positional arguments
604    if len(args) == 1:
605        # if the specified argument is not in the DefinitionSet, then assume that it's a filename
606        if args[0] not in DefinitionSet:
607            #define the characters in the list
608            defs = charset_input_parser.input_chardef(args[0])
609        else: defs = DefinitionSet[args[1]]
610        if options.use_EBCDIC:
611            defs = EBCDIC.ascii2ebcdic_chardeflist(defs)       
612        stmts = chardeflist2py(defs)
613        if options.Pablo_skeleton or options.test_skeleton:
614          b = string.split(options.basis_pattern, ".")
615          if len(b) == 2: 
616            basis_struct = string.upper(b[0][0]) + b[0][1:]
617            basis_struct_var = b[0]
618            bit_pattern = b[1]
619          else: 
620            basis_struct = 'Bits'
621            basis_stuct_var = 'bits'
622            bit_pattern = bit[0]
623          struct_defs = "class %s():\n" % basis_struct
624          for i in range(8): struct_defs += "\t" + bit_pattern % i + " = 0\n"
625          struct_sets = {}
626          for d in defs:
627            n = string.split(d.name, ".")
628            if len(n) == 2:
629              if not n[0] in struct_sets.keys(): struct_sets[n[0]] = []
630              struct_sets[n[0]].append(n[1])
631          for k in struct_sets.keys():
632            struct_defs += "\nclass %s():\n" % (string.upper(k[0])+k[1:])
633            for f in struct_sets[k]: struct_defs += "\t" + f + " = 0\n"
634          print struct_defs
635          params = ", ".join([basis_struct_var] + struct_sets.keys())
636          print "\ndef Do_defs(%s):\n" % params
637          print stmts
638          if options.test_skeleton:
639            for d in defs:
640              print '\tprint_register<BitBlock>("%s",%s);\n' % (d.name, d.name)
641          print "\ndef main():\n\tDo_defs(%s)\n" % params
642        else: print stmts 
643
644    else:
645        option_parser.print_usage()
646
647if __name__ == "__main__": main()
648
Note: See TracBrowser for help on using the repository browser.