source: proto/charsetcompiler/charset_compiler.py @ 609

Last change on this file since 609 was 609, checked in by cameron, 9 years ago

charset compiler check-in

File size: 28.7 KB
Line 
1#
2#  Character Class Compiler
3#
4#  Version 0.7 - August 14, 2009
5#     Adding generation of Python code;  parabix 2 definitions
6#  Copyright (c) 2007, 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 re, binascii, string
32
33#
34#  Character sets are defined as lists of items that
35#  are either individual characters or ranges of contiguous
36#  characters.
37#
38class CharSetDef:
39    """Definitions of character sets.   Examples:
40    CharSetDef('alpha_', ['a-z', 'A-Z', '_'])
41    CharDef('semicolon', ';') (equiv. to CharSetDef('semicolon', [';']))
42    """
43    def __init__(self, name, items, invert = False):
44        self.name = name
45        self.items = items
46        self.complemented = invert
47    def show(self): 
48        if self.complemented:
49            return "CharSetDef(%s, %s, True)" % (self.name, self.items)
50        else: return "CharSetDef(%s, %s)" % (self.name, self.items)
51
52       
53class CharDef(CharSetDef):
54    def __init__(self, name, char, invert = False):
55        self.name = name
56        self.items = [char]
57        self.complemented = invert
58    def show(self): 
59        if self.complemented:
60            return "CharDef(%s, '\\%X', True)" % (self.name, ord(self.items[0]))
61        else: return "CharDef(%s, '\\%X')" % (self.name, ord(self.items[0]))
62
63
64#
65# UTF-8 bytes occurring in the additional XML 1.1 line break
66# characters NEL and LS.
67
68UTF8_XML11_WS_bytes = [CharDef('NEL1', chr(0xC2)),
69                        CharDef('NEL2', chr(0x85)),
70                        CharDef('LS1', chr(0xE2)),
71                        CharDef('LS2', chr(0x80)),
72                        CharDef('LS3', chr(0xA8))]
73           
74DefinitionSet = {}
75
76
77
78DefinitionSet['WS_Control_10'] = [CharSetDef('control.x00_x1F', ['\x00-\x1F']),
79                                  CharDef('control.CR', '\x0D'),
80                                  CharDef('control.LF', '\x0A'),
81                                  CharDef('control.HT', '\x09'),
82                                  CharDef('control.SP', ' '),
83                                  CharSetDef('lex.WS', ['\x0D', '\x0A', '\x09', ' '])]
84
85DefinitionSet['WS_Control_10_EBCDIC'] = [CharSetDef('Control', ['\x00-\x03', '\x37',
86                                                                '\x2d-\x2f', '\x16',
87                                                                '\x0b-\x13', '\x3c-\x3d',
88                                                                '\x32', '\x26-\x27',
89                                                                '\x18-\x19', '\x3f', 
90                                                                '\x1c-\x1f']),
91                                         CharDef('CR', '\x0D'),
92                                         CharDef('LF', '\x25'),
93                                         CharDef('HT', '\x05'),
94                                         CharDef('SP', '\x40')]
95
96DefinitionSet['WS_Control_11_EBCDIC'] = [CharSetDef('Control', ['\x00-\x3f']),
97                                         CharDef('CR', '\x0D'),
98                                         CharDef('LF', '\x25'),
99                                         CharDef('HT', '\x05'),
100                                         CharDef('SP', '\x40'),
101                                         CharDef('NEL', '\x15')]
102
103
104DefinitionSet['WS_Control_11_ISO8859'] = [CharSetDef('Control', ['\x00-\x1F', '\x7F', '\x80-\x9F']),
105                                          CharDef('CR', '\x0D'),
106                                          CharDef('LF', '\x0A'),
107                                          CharDef('HT', '\x09'),
108                                          CharDef('SP', ' '),
109                                          CharDef('NEL', '\x85')]
110
111DefinitionSet['Markup'] = [CharDef('RefStart', '&'),
112                           CharDef('Semicolon', ';'),
113                           CharDef('LAngle', '<'),
114                           CharDef('RAngle', '>'),
115                           CharDef('RBracket', ']'),
116                           CharDef('Hyphen', '-'),
117                           CharDef('QMark', '?'),
118                           CharDef('Equals', "="),
119                           CharDef('SQuote', "'"),
120                           CharDef('DQuote', '"'),
121                           CharDef('Slash', '/')
122                           ]
123
124DefinitionSet['Digit_and_Hex'] = [CharSetDef('Digit', ['0-9']),
125                                  CharSetDef('Hex', ['0-9', 'A-F', 'a-f'])]
126
127DefinitionSet['Markup2'] = DefinitionSet['Markup'] + DefinitionSet['Digit_and_Hex']
128
129DefinitionSet['LexicalItems'] = [CharSetDef('MarkupStart', ['<', '&']),
130                                 CharDef('RAngle', '>'),
131                                 CharDef('RBracket', ']'),
132                                 CharDef('Hyphen', '-'),
133                                 CharDef('QMark', '?'),
134                                 CharSetDef('Quote', ['"', "'", '<', '&']),
135                                 CharSetDef('NameFollow', [';', '=', '/', '>', '?', ')', '[', '|', '?', '*', '+', ','])
136                                 ]
137DefinitionSet['LexicalItems2'] = [CharSetDef('MarkupStart', ['<', '&']),
138                                 CharDef('RAngle', '>'),
139                                 CharDef('RBracket', ']'),
140                                 CharDef('Hyphen', '-'),
141                                 CharDef('QMark', '?'),
142                                 CharSetDef('Quote', ['"', "'", '<', '&']),
143                                 CharSetDef('NameFollow', [' -,', '/', ';-?', '[-^', '{-~'])
144                                 ]
145
146
147
148DefinitionSet['Digit_and_Hex'] = [CharSetDef('lex.Digit', ['0-9']),
149                                  CharSetDef('lex.Hex', ['0-9', 'A-F', 'a-f'])]
150                                 
151DefinitionSet['LexicalItems_with_Digit'] = DefinitionSet['LexicalItems2'] + DefinitionSet['Digit_and_Hex']
152
153DefinitionSet['LI_with_MarkupPass'] = DefinitionSet['LexicalItems_with_Digit'] + [CharSetDef('AmpHashSlash', ['&', '#', '/'])]
154
155#
156# Following definitions for the parabix2 unbounded bitstream prototype
157#
158# First all the special characters in the XML delimiters.
159
160xml_marks =    [CharDef('lex.RefStart', '&'),
161                CharDef('lex.Semicolon', ';'),
162                CharDef('lex.LAngle', '<'),
163                CharDef('lex.RAngle', '>'),
164                CharDef('lex.LBracket', '['),
165                CharDef('lex.RBracket', ']'),
166                CharDef('lex.Exclam', '!'),
167                CharDef('lex.QMark', '?'),
168                CharDef('lex.Hyphen', '-'),
169                CharDef('lex.Equals', "="),
170                CharDef('lex.SQuote', "'"),
171                CharDef('lex.DQuote', '"'),
172                CharDef('lex.Slash', '/'),
173                CharDef('lex.Hash', '#'),
174                CharDef('lex.x', 'x'),
175                CharDef('lex.Colon', ':')
176                ]
177#
178# NameFollow: all characters that may legally follow an XML name, plus
179# any others that may not be used in names.
180# 1. All non-WS characters that may legally follow an XML name.
181namefollow = [CharSetDef('lex.NameFollow', [';', '=', '/', '>', '?', ')', '[', '|', '?', '*', '+', ','])]
182#
183# NameScan: all ASCII characters that may legally occur in a Name,
184# plus all UTF-8 prefix and suffix bytes.
185namescan = [CharSetDef('lex.NameScan', ['_', '-', '.', '0-:', 'A-Z', 'a-z', '\x80-\xFF'])]
186
187#
188namelex = [CharSetDef('lex.ASCII_name_start', ['_', ':', 'A-Z', 'a-z']),
189           CharSetDef('lex.ASCII_name_char', ['_', '-', '.', '0-:', 'A-Z', 'a-z']),
190           CharSetDef('lex.NameScan', ['_', '-', '.', '0-:', 'A-Z', 'a-z', '\x80-\xFF'])]
191
192#
193# Byte classifications in UTF-8 validation.
194UTF8_defs = [CharSetDef('u8.unibyte', ['\x00-\x7F']),
195             CharSetDef('u8.prefix', ['\xC0-\xFF']),
196             CharSetDef('u8.prefix2', ['\xC0-\xDF']),
197             CharSetDef('u8.prefix3', ['\xE0-\xEF']),
198             CharSetDef('u8.prefix4', ['\xF0-\xFF']),
199             CharSetDef('u8.suffix', ['\x80-\xBF']),
200             CharSetDef('u8.badprefix', ['\xC0-\xC1', '\xF5-\xFF']),
201             CharDef('u8.xE0', '\xE0'),
202             CharDef('u8.xED', '\xED'),
203             CharDef('u8.xF0', '\xF0'),
204             CharDef('u8.xF4', '\xF4'),
205             CharSetDef('u8.xA0_xBF', ['\xA0-\xBF']),
206             CharSetDef('u8.x80_x9F', ['\x80-\x9F']),
207             CharSetDef('u8.x90_xBF', ['\x90-\xBF']),
208             CharSetDef('u8.x80_x8F', ['\x80-\x8F'])]
209
210
211#
212UTF8_BOM_bytes = [CharDef('u8.xEF', '\xEF'), CharDef('u8.xBF', '\xBF'), CharDef('u8.xBE', '\xBE')]
213
214DefinitionSet['parabix2'] = (xml_marks + namelex + DefinitionSet['WS_Control_10']
215                             + DefinitionSet['Digit_and_Hex'] + UTF8_defs + UTF8_BOM_bytes)
216                             
217DefinitionSet['UTF8'] = UTF8_defs
218
219DefinitionSet['CSV'] = [CharDef('BackSlash', '\\'),
220                        CharDef('DQuote', '"'),
221                        CharDef('SQuote', '\''),
222                        CharDef('CR', '\x0D'),
223                        CharDef('LF', '\x0A'),
224                        CharDef('Comma', ','),
225                        CharDef('HT', '\x09'),
226                        CharDef('Period', '.')]
227
228
229#
230# Symbolic Representations of Boolean Expressions
231#
232
233class BoolExpr:
234   """The BoolExpr class and its subclasses provide a symbolic
235      representation of Boolean expressions.
236   """
237   pass
238
239class Var(BoolExpr):
240    def __init__(self, varname):
241        self.varname = varname
242    def show(self): return 'Var("' + self.varname + '")'
243
244class TrueLiteral(BoolExpr):
245    def __init__(self):
246        self.value = True
247    def show(self): return 'T'
248
249class FalseLiteral(BoolExpr):
250    def __init__(self):
251        self.value = False
252    def show(self): return 'F'
253
254class Not(BoolExpr):
255    def __init__(self, expr):
256        self.operand = expr
257    def show(self): return 'Not(%s)' % (self.operand.show())
258
259class And(BoolExpr):
260    def __init__(self, expr1, expr2):
261        self.operand1 = expr1
262        self.operand2 = expr2
263    def show(self): return 'And(%s, %s)' % (self.operand1.show(), self.operand2.show())
264
265class Or(BoolExpr):
266    def __init__(self, expr1, expr2):
267        self.operand1 = expr1
268        self.operand2 = expr2
269    def show(self): return 'Or(%s, %s)' % (self.operand1.show(), self.operand2.show())
270
271class Xor(BoolExpr):
272    def __init__(self, expr1, expr2):
273        self.operand1 = expr1
274        self.operand2 = expr2
275    def show(self): return 'Xor(%s, %s)' % (self.operand1.show(), self.operand2.show())
276
277class Sel(BoolExpr):
278    def __init__(self, expr1, expr2, expr3):
279        self.sel = expr1
280        self.true_branch = expr2
281        self.false_branch = expr3
282    def show(self): return 'Sel(%s, %s, %s)' % (self.sel.show(), self.true_branch.show(), self.false_branch.show())
283
284
285#
286# Optimizing Constructors for Boolean Expressions
287# - Maintaining Assembler Instruction Form:
288#   - All boolean algebraic rules involving true/false applied.
289#   - Negations restricted:
290#       - no negations within or (DeMorgan's to nand)
291#       - at most one negation within and
292#
293
294def make_not(expr):
295    if isinstance(expr, TrueLiteral):
296        return FalseLiteral()
297    elif isinstance(expr, FalseLiteral):
298        return TrueLiteral()
299    elif isinstance(expr, Not):
300        return expr.operand
301    else: return Not(expr)
302
303def make_and(expr1, expr2):
304    if isinstance(expr1, TrueLiteral):
305        return expr2
306    elif isinstance(expr2, TrueLiteral):
307        return expr1
308    elif isinstance(expr1, FalseLiteral):
309        return FalseLiteral()
310    elif isinstance(expr2, FalseLiteral):
311        return FalseLiteral()
312    elif equal_exprs(expr1, expr2): return expr1
313    elif isinstance(expr1, Not):
314        if isinstance(expr2, Not):
315            return make_not(make_or(expr1.operand, expr2.operand))
316        elif equal_exprs(expr1.operand, expr2): return FalseLiteral()
317        else: return And(expr1, expr2)
318    elif isinstance(expr2, Not):
319        if equal_exprs(expr1, expr2.operand): return FalseLiteral()
320        else: return And(expr1, expr2)
321    else: return And(expr1, expr2)
322
323def make_or(expr1, expr2):
324    if isinstance(expr1, FalseLiteral):
325        return expr2
326    elif isinstance(expr2, FalseLiteral):
327        return expr1
328    elif isinstance(expr1, TrueLiteral):
329        return TrueLiteral()
330    elif isinstance(expr2, TrueLiteral):
331        return TrueLiteral()
332    elif isinstance(expr1, Not):
333        return make_not(make_and(expr1.operand, make_not(expr2)))
334    elif isinstance(expr2, Not):
335        return make_not(make_and(make_not(expr1), expr2.operand))
336    elif equal_exprs(expr1, expr2): return expr1
337    elif isinstance(expr1, And) and isinstance(expr2, And):
338        # These optimizations factor out common components that
339        # can occur when sets are formed by union (e.g., union of
340        # [a-z] and [A-Z].
341        if equal_exprs(expr1.operand1, expr2.operand1):
342            return make_and(expr1.operand1, make_or(expr1.operand2, expr2.operand2))
343        elif equal_exprs(expr1.operand2, expr2.operand2):
344            return make_and(expr1.operand2, make_or(expr1.operand1, expr2.operand1))
345        elif equal_exprs(expr1.operand1, expr2.operand2):
346            return make_and(expr1.operand1, make_or(expr1.operand2, expr2.operand1))
347        elif equal_exprs(expr1.operand2, expr2.operand1):
348            return make_and(expr1.operand2, make_or(expr1.operand1, expr2.operand2))
349        else: return Or(expr1, expr2)
350    else: return Or(expr1, expr2)
351
352def make_sel(if_expr, T_expr, F_expr):
353    if isinstance(if_expr, TrueLiteral):
354        return T_expr
355    elif isinstance(if_expr, FalseLiteral):
356        return F_expr
357    elif isinstance(T_expr, TrueLiteral):
358        # if x then T else y = x or y
359        return make_or(if_expr, F_expr) 
360    elif isinstance(T_expr, FalseLiteral):
361        # if x then F else y = not(x) and y
362        return make_and(make_not(if_expr), F_expr) 
363    elif isinstance(F_expr, FalseLiteral):
364        # if x then y else F = x and y
365        return make_and(if_expr, T_expr) 
366    elif isinstance(F_expr, TrueLiteral):
367        # if x then y else T = not(x) or y
368        return make_or(make_not(if_expr), T_expr)
369    elif equal_exprs(T_expr, F_expr):
370        return T_expr
371    else: return Sel(if_expr, T_expr, F_expr)
372
373
374def make_xor(expr1, expr2):
375    if isinstance(expr1, FalseLiteral):
376        return expr2
377    elif isinstance(expr1, FalseLiteral):
378        return expr1
379    elif isinstance(expr1, TrueLiteral):
380        return make_not(expr2)
381    elif isinstance(expr2, TrueLiteral):
382        return make_not(expr1)
383    elif isinstance(expr1, Not) and isinstance(expr2, Not):
384        return make_xor(expr1.operand, expr2.operand)
385    else: return Xor(expr1, expr2)
386
387def equal_exprs(e1, e2):
388    if isinstance(e1, FalseLiteral): return isinstance(e2, FalseLiteral)
389    elif isinstance(e1, TrueLiteral): return isinstance(e2, TrueLiteral)
390    elif isinstance(e1, Var) and isinstance(e2, Var):
391        return e1.varname == e2.varname
392    elif isinstance(e1, Not) and isinstance(e2, Not):
393        return equal_exprs(e1.operand, e2.operand)
394    elif isinstance(e1, And) and isinstance(e2, And):
395        if equal_exprs(e1.operand1, e2.operand1):
396            return equal_exprs(e1.operand2, e2.operand2)
397        elif equal_exprs(e1.operand1, e2.operand2):
398            return equal_exprs(e1.operand2, e2.operand1)
399        else: return False
400    elif isinstance(e1, Or) and isinstance(e2, Or):
401        if equal_exprs(e1.operand1, e2.operand1):
402            return equal_exprs(e1.operand2, e2.operand2)
403        elif equal_exprs(e1.operand1, e2.operand2):
404            return equal_exprs(e1.operand2, e2.operand1)
405        else: return False
406    elif isinstance(e1, Xor) and isinstance(e2, Xor):
407        if equal_exprs(e1.operand1, e2.operand1):
408            return equal_exprs(e1.operand2, e2.operand2)
409        elif equal_exprs(e1.operand1, e2.operand2):
410            return equal_exprs(e1.operand2, e2.operand1)
411        else: return False
412    elif isinstance(e1, Sel) and isinstance(e2, Sel):
413        if equal_exprs(e1.sel, e2.sel):
414             if equal_exprs(e1.true_branch, e2.true_branch):
415                 return equal_exprs(e1.false_branch, e2.false_branch)
416             else: return False
417        else: return False
418
419
420#
421#
422#  Boolean Expressions for Character Class Definitions
423#
424
425def bit_var(n):
426    return 'bit[%i]' % n
427def make_bitv(n):
428    return Var(bit_var(n))
429
430# Deprecated
431def make_2bit_test(var1, var2, bit_pattern):
432  if bit_pattern == 0: 
433    return make_not(make_or(var1, var2))
434  elif bit_pattern == 1:
435    return make_and(make_not(var1), var2)
436  elif bit_pattern == 2:
437    return make_and(var1, make_not(var2))
438  else: return make_and(var1, var2)
439
440# Deprecated
441def make_8bit_test(bit_pattern):
442  return make_and(make_and(make_2bit_test(make_bitv(0), make_bitv(1), (bit_pattern >> 6) & 3),
443                           make_2bit_test(make_bitv(2), make_bitv(3), (bit_pattern >> 4) & 3)),
444                  make_and(make_2bit_test(make_bitv(4), make_bitv(5), (bit_pattern >> 2) & 3),
445                           make_2bit_test(make_bitv(6), make_bitv(7), (bit_pattern) & 3)))
446
447
448def make_bit_test(pattern, bit_count):
449    bit_terms = []
450    test_bit = 2**(bit_count - 1)
451    for i in range(0, bit_count):
452        if (pattern & test_bit) == 0:
453            bit_terms.append(make_not(make_bitv(i)))
454        else: bit_terms.append(make_bitv(i))
455        test_bit >>= 1
456    while len(bit_terms) > 1:
457        new_terms = []
458        for i in range(0, len(bit_terms)/ 2):
459            new_terms.append(make_and(bit_terms[2*i], bit_terms[2*i+1]))
460        if len(bit_terms) % 2 == 1:
461            new_terms.append(bit_terms[-1])
462        bit_terms = new_terms
463    return bit_terms[0]
464
465
466def char_test_expr(ch):
467    return make_bit_test(ord(ch), 8)
468    #return make_8bit_test(ord(ch))
469
470def GE_Range(N, n):
471    if N == 0: return TrueLiteral()
472    elif N % 2 == 0 and (n >> (N - 2)) == 0:
473        return make_or(make_or(make_bitv(8-N), make_bitv(9-N)),
474                        GE_Range(N - 2, n))
475    elif N % 2 == 0 and (n >> (N - 2)) == 3:   # >= 11xxxx
476        return make_and(make_and(make_bitv(8-N), make_bitv(9-N)),
477                        GE_Range(N - 2, n - (3 << (N-2))))
478    elif N >= 1:
479        hi_bit = n & (1 << (N-1))
480        lo_bits = n - hi_bit
481        lo_range = GE_Range(N-1, lo_bits)
482        if hi_bit == 0:
483            # If the hi_bit of n is not set, then whenever the corresponding bit
484            # is set in the target, the target will certainly be >=.  Otherwise,
485            # the value of GE_range(N-1, lo_bits) is required.
486            return make_or(make_bitv(8-N), lo_range)
487        else: 
488            # If the hi_bit of n is set, then the corresponding bit must be set
489            # in the target for >= and GE_range(N-1, lo_bits) must also be true.
490            return make_and(make_bitv(8-N), lo_range)
491
492def LE_Range(N, n):
493    # If an N-bit pattern is all ones, then it is always
494    # true that any n-bit value is LE this pattern.
495    # Handling this as a special case avoids an overflow
496    # issue with n+1 requiring more than N bits.
497    if n+1 == 2 ** N:
498        return TrueLiteral()
499    else:
500        return make_not(GE_Range(N, n+1))
501
502BadRange = Exception()
503
504
505def Make_Range(n1, n2):  # require n2 >= n1
506    diff_bits = n1 ^ n2
507    diff_count = 0
508    while diff_bits > 0:
509        diff_count += 1
510        diff_bits >>= 1
511    if n2 < n1 or diff_count > 8: raise BadRange()
512    common = make_bit_test(n1 >> diff_count, 8 - diff_count)
513    if diff_count == 0: return common
514    mask = 2**(diff_count-1) - 1
515    lo_test = GE_Range(diff_count-1, n1 & mask)
516    hi_test = LE_Range(diff_count-1, n2 & mask)
517    return make_and(common, make_sel(make_bitv(8-diff_count), hi_test, lo_test))
518
519# Deprecated   
520def Inclusive_Range(N, n1, n2):  # require n2 >= n1
521    if N == 0: return TrueLiteral()
522    elif n1 >= 2**(N-1):
523        return make_and(make_bitv(8-N), Inclusive_Range(N-1, n1 - 2**(N-1), n2 - 2**(N-1)))
524    elif n2 < 2**(N-1):
525        return make_and(make_not(make_bitv(8-N)), Inclusive_Range(N-1, n1, n2))
526    else:
527        n2_lo = n2 - 2**(N-1)
528        lo_test = GE_Range(N-1, n1)
529        hi_test = LE_Range(N-1, n2_lo)
530        # special optimization?
531        # if n2_lo + 1 == n1: return make_xor(make_bit_test(8-N), lo_test)
532        return make_sel(make_bitv(8-N), lo_test, hi_test)
533
534
535
536
537BadCharSetItem = Exception()
538
539def char_or_range_expr(charset_item):
540    if len(charset_item) == 1:
541        return char_test_expr(charset_item[0])
542    elif len(charset_item) == 3:
543        if charset_item[1] == '-' and ord(charset_item[0]) <= ord(charset_item[2]):
544             return Make_Range(ord(charset_item[0]), ord(charset_item[2]))
545             #  return Inclusive_Range(8, ord(charset_item[0]), ord(charset_item[2]))
546    print charset_item
547    raise BadCharSetItem
548
549def charset_expr(chardef):
550    e1 = char_or_range_expr(chardef.items[0])
551    for i in range(1, len(chardef.items)):
552        e1 = make_or(e1, char_or_range_expr(chardef.items[i]))
553    if chardef.complemented: return make_not(e1)
554    else: return e1
555
556
557
558#
559#
560#  Code Generation
561#
562class CodeGenObject:
563    def __init__(self, predeclared, typedecl='BitBlock '):
564        self.gensym_template = 'temp%i'
565        self.gensym_counter = 0
566        self.generated_code = []
567        self.common_expression_map = {}
568        for sym in predeclared: self.common_expression_map[sym] = sym
569        self.typedecl = typedecl
570    def add_assignment(self, varname, expr):
571        self.common_expression_map[expr] = varname
572        self.generated_code.append(%s%s = %s;\n' % (self.typedecl, varname, expr))
573    def expr_string_to_variable(self, expr_string):
574        if self.common_expression_map.has_key(expr_string): 
575            return self.common_expression_map[expr_string]
576        else:
577            self.gensym_counter += 1
578            sym = self.gensym_template % self.gensym_counter
579            self.add_assignment(sym, expr_string)
580            return sym
581    def showcode(self):
582        s = ''
583        for stmt in self.generated_code: s += stmt
584        return s
585
586
587
588def expr2simd(genobj, expr):
589    """Translate a Boolean expression into three-address Altivec code
590       using code generator object genobj.
591    """
592    if isinstance(expr, TrueLiteral): return 'simd_const_1(1)'
593    elif isinstance(expr, FalseLiteral): return 'simd_const_1(0)'
594    elif isinstance(expr, Var): return expr.varname
595    elif isinstance(expr, Not):
596       e = genobj.expr_string_to_variable(expr2simd(genobj, expr.operand))
597       return 'simd_andc(simd_const_1(1), %s)' % (e)
598    elif isinstance(expr, Or):
599       e1 = genobj.expr_string_to_variable(expr2simd(genobj, expr.operand1))
600       e2 = genobj.expr_string_to_variable(expr2simd(genobj, expr.operand2))
601       return 'simd_or(%s, %s)' % (e1, e2)
602    elif isinstance(expr, Xor):
603       e1 = genobj.expr_string_to_variable(expr2simd(genobj, expr.operand1))
604       e2 = genobj.expr_string_to_variable(expr2simd(genobj, expr.operand2))
605       return 'simd_xor(%s, %s)' % (e1, e2)
606    elif isinstance(expr, And):
607       if isinstance(expr.operand1, Not):
608           e1 = genobj.expr_string_to_variable(expr2simd(genobj, expr.operand1.operand))
609           e2 = genobj.expr_string_to_variable(expr2simd(genobj, expr.operand2))
610           return 'simd_andc(%s, %s)' % (e2, e1)
611       elif isinstance(expr.operand2, Not):
612           e1 = genobj.expr_string_to_variable(expr2simd(genobj, expr.operand1))
613           e2 = genobj.expr_string_to_variable(expr2simd(genobj, expr.operand2.operand))
614           return 'simd_andc(%s, %s)' % (e1, e2)
615       else:
616           e1 = genobj.expr_string_to_variable(expr2simd(genobj, expr.operand1))
617           e2 = genobj.expr_string_to_variable(expr2simd(genobj, expr.operand2))
618           return 'simd_and(%s, %s)' % (e1, e2)
619    elif isinstance(expr, Sel):
620       sel = genobj.expr_string_to_variable(expr2simd(genobj, expr.sel))
621       e1 = genobj.expr_string_to_variable(expr2simd(genobj, expr.true_branch))
622       e2 = genobj.expr_string_to_variable(expr2simd(genobj, expr.false_branch))
623       return 'simd_if(%s, %s, %s)' %(sel, e1, e2)
624
625def chardef2simd(genobj, chardef):
626    genobj.add_assignment(chardef.name, expr2simd(genobj, charset_expr(chardef)))
627
628def chardeflist2simd(chardeflist):
629    cgo = CodeGenObject([bit_var(i) for i in range(0,8)])
630    for d in chardeflist:
631        chardef2simd(cgo, d)
632    return cgo.showcode()
633
634
635
636def expr2py(genobj, expr):
637    """Translate a Boolean expression into three-address python code
638       using code generator object genobj.
639    """
640    if isinstance(expr, TrueLiteral): return '-1'
641    elif isinstance(expr, FalseLiteral): return '0'
642    elif isinstance(expr, Var): return expr.varname
643    elif isinstance(expr, Not):
644       e = genobj.expr_string_to_variable(expr2py(genobj, expr.operand))
645       return '(~%s)' % (e)
646    elif isinstance(expr, Or):
647       e1 = genobj.expr_string_to_variable(expr2py(genobj, expr.operand1))
648       e2 = genobj.expr_string_to_variable(expr2py(genobj, expr.operand2))
649       return '(%s | %s)' % (e1, e2)
650    elif isinstance(expr, Xor):
651       e1 = genobj.expr_string_to_variable(expr2py(genobj, expr.operand1))
652       e2 = genobj.expr_string_to_variable(expr2py(genobj, expr.operand2))
653       return '(%s ^ %s)' % (e1, e2)
654    elif isinstance(expr, And):
655       if isinstance(expr.operand1, Not):
656           e1 = genobj.expr_string_to_variable(expr2py(genobj, expr.operand1.operand))
657           e2 = genobj.expr_string_to_variable(expr2py(genobj, expr.operand2))
658           return '(%s &~ %s)' % (e2, e1)
659       elif isinstance(expr.operand2, Not):
660           e1 = genobj.expr_string_to_variable(expr2py(genobj, expr.operand1))
661           e2 = genobj.expr_string_to_variable(expr2py(genobj, expr.operand2.operand))
662           return '(%s &~ %s)' % (e1, e2)
663       else:
664           e1 = genobj.expr_string_to_variable(expr2py(genobj, expr.operand1))
665           e2 = genobj.expr_string_to_variable(expr2py(genobj, expr.operand2))
666           return '(%s & %s)' % (e1, e2)
667    elif isinstance(expr, Sel):
668       sel = genobj.expr_string_to_variable(expr2py(genobj, expr.sel))
669       e1 = genobj.expr_string_to_variable(expr2py(genobj, expr.true_branch))
670       e2 = genobj.expr_string_to_variable(expr2py(genobj, expr.false_branch))
671       return '((%s & %s)|(~(%s) & %s))' %(sel, e1, sel, e2)
672
673def chardef2py(genobj, chardef):
674    genobj.add_assignment(chardef.name, expr2py(genobj, charset_expr(chardef)))
675
676
677def py_chardefmap(chardeflist):
678    defs = ["'%s' : %s" % (d.name,d.name) for d in chardeflist]
679    return  '{%s}' % string.join(defs, ',\n\t')
680
681def chardeflist2py(chardeflist):
682    cgo = CodeGenObject([bit_var(i) for i in range(0,8)],'')
683    for d in chardeflist:
684       chardef2py(cgo, d) 
685    return cgo.showcode()# + "  return "+ py_chardefmap(chardeflist) + "\n"
686
687
688def code_gen_for_transcode(transcode_tbl_h, transcode_tbl_l):
689  cgo = CodeGenObject([bit_var(i) for i in range(0,8)])
690  xor_tbl_l = [transcode_tbl_l[code] ^ code for code in range(256)]
691  code_gen_for_transcode_8bit(cgo, "x16h", transcode_tbl_h)
692  code_gen_for_transcode_8bit(cgo, "x16l", xor_tbl_l)
693  return cgo.showcode()
694
695def code_gen_for_transcode_8bit(cgo, pfx, tbl):
696  for bit in range(8):
697    bit_mask = 256 >> bit
698    in_run = False
699    first_expr_found = False
700    bit_expr = FalseLiteral()
701    for code in range(256):
702      if tbl[code] & bit_mask != 0:
703        if not in_run:
704          in_run = True
705          run_start = code
706      else:
707        if in_run:
708          if run_start == code-1:
709            e1 = char_test_expr(chr(code - 1))
710          else:
711            e1 = Make_Range(run_start, code - 1)
712          if first_expr_found:
713            bit_expr = make_or(bit_expr, e1)
714          else:
715            first_expr_found = True
716            bit_expr = e1
717    if first_expr_found:
718      cgo.add_assignment("%s[%i]" % (pfx, bit), expr2simd(cgo, bit_expr))
719
720# Work with tables from
721# /home/cameron/glibc-2.3.5/localedata/charmaps/
722
723charmap_line_RE = re.compile("<U([0-9A-F][0-9A-F])([0-9A-Z][0-9A-Z])>\s+/x([0-9a-f][0-9a-f])\s")
724
725def read_char_map(file):
726  f = open(file)
727  lines = f.readlines()
728  matches = [charmap_line_RE.match(l) for l in lines]
729  u16hi = [ord(binascii.unhexlify(m.group(1))) for m in matches if m]
730  u16lo = [ord(binascii.unhexlify(m.group(2))) for m in matches if m]
731  codes = [ord(binascii.unhexlify(m.group(3))) for m in matches if m]
732  codes_OK = [c for c in range(256) if codes[c] == c]
733  if len(codes_OK) != 256:
734    print("Code map failure reading %s" % file)
735  return (u16hi, u16lo)
736
737import codecs
738def ascii2ebcdic_chardeflist(defs):
739        encoder = codecs.getencoder('cp037')
740        return [xlate_chardef(d, encoder) for d in defs]
741
742def xlate_char_or_range(charset_item, encoder):
743    if len(charset_item) == 1:
744        return encoder(charset_item[0])
745    elif len(charset_item) == 3:
746        if charset_item[1] == '-' and ord(charset_item[0]) <= ord(charset_item[2]):
747             return Make_Range(ord(charset_item[0]), ord(charset_item[2]))
748             #  return Inclusive_Range(8, ord(charset_item[0]), ord(charset_item[2]))
749    print charset_item
750    raise BadCharSetItem
751       
752def xlate_chardef(chardef, encoder):
753  if isinstance(chardef, CharDef):
754    return CharDef(chardef.name, encoder(chardef.items[0])[0], chardef.complemented)
755  else:
756    cdefs = []
757    for item in chardef.items:
758        if len(item) == 1: cdefs.append(encoder(item)[0])
759        elif len(item) == 3:
760          for v in range(ord(item[0]), ord(item[-1])+1):
761            cdefs.append(encoder(chr(v))[0])
762        else: raise BadCharSetItem
763    return CharSetDef(chardef.name, cdefs, chardef.complemented)
764
765import charset_input_parser
766def input_chardef(filename):
767    """
768    Returns a list of declared CharSet from the declarations in the input file
769    """
770    defs = []
771    charset_declaration_list = charset_input_parser.processCharsetInput(filename)
772   
773    for charset_declaration in charset_declaration_list:
774        defs.append(CharSetDef (charset_declaration[0], charset_declaration[1]))
775
776    return defs
777                                 
778import sys
779def main():
780    if len(sys.argv) == 2:
781        # if the specified argument is not in the DefinitionSet, then assume that it's a filename
782        if sys.argv[1] not in DefinitionSet:
783            #define the characters in the list
784            defs = input_chardef(sys.argv[1])
785            print chardeflist2simd(defs)
786        else:
787            print chardeflist2simd(DefinitionSet[sys.argv[1]])
788    elif len(sys.argv) == 3 and sys.argv[2] == 'EBCDIC':
789        defs = ascii2ebcdic_chardeflist(DefinitionSet[sys.argv[1]])
790        print chardeflist2simd(defs)
791    else:
792        print "Usage python charset_compiler.py <name> [EBCDIC]"
793        for k in DefinitionSet.keys(): print k
794
795if __name__ == "__main__": main()
Note: See TracBrowser for help on using the repository browser.