class LenSubsScanner(MyScanner): """Following clapack, we remove ftnlen arguments, which f2c puts after a char * argument to hold the length of the passed string. This is just a nuisance in C. """ def __init__(self, info, name='<ftnlen>'): MyScanner.__init__(self, info, name) self.paren_count = 0 def beginArgs(self, text): if self.paren_count == 0: self.begin('args') self.paren_count += 1 return text def endArgs(self, text): self.paren_count -= 1 if self.paren_count == 0: self.begin('') return text digits = Re('[0-9]+') iofun = Re(r'\([^;]*;') decl = Re(r'\([^)]*\)[,;' + '\n]') any = Re('[.]*') S = Re('[ \t\n]*') cS = Str(',') + S len_ = Re('[a-z][a-z0-9]*_len') iofunctions = Str("s_cat", "s_copy", "s_stop", "s_cmp", "i_len", "do_fio", "do_lio") + iofun # Routines to not scrub the ftnlen argument from keep_ftnlen = (Str('ilaenv_') | Str('s_rnge')) + Str('(') lexicon = Lexicon([ (iofunctions, TEXT), (keep_ftnlen, beginArgs), State('args', [ (Str(')'), endArgs), (Str('('), beginArgs), (AnyChar, TEXT), ]), (cS + Re(r'[1-9][0-9]*L'), IGNORE), (cS + Str('ftnlen') + Opt(S + len_), IGNORE), (cS + sep_seq(['(', 'ftnlen', ')'], S) + S + digits, IGNORE), (Bol + Str('ftnlen ') + len_ + Str(';\n'), IGNORE), (cS + len_, TEXT), (AnyChar, TEXT), ])
def sep_seq(sequence, sep): pat = Str(sequence[0]) for s in sequence[1:]: pat += sep + Str(s) return pat
def _init(self): comma = Str(",") whitespace = Rep1(Any(" \t\n")) open_parenthesis = Str("(") close_parenthesis = Str(")") letter = Range("AZaz") digit = Range("09") prefix = letter + Rep(letter) + Str(".") identifier = prefix + letter + Rep(letter | digit | Str("_")) comparators = NoCase(Str("=", "!=", "<", "<=", ">", ">=", "like", "in")) string_literal = Str("'") + Rep(AnyBut("'") | Str(" ") | Str("\\'")) + Str("'") integer_literal = Opt(Str("+", "-")) + Rep1(digit) float_literal = Opt(Str("+", "-")) + Rep1(digit) + Str(".") + Rep1(digit) operands = NoCase(Str("AND", "OR")) null = Str("NULL") COMMA = 1 OPEN_PARENTHESIS = 2 CLOSE_PARENTHESIS = 3 NULL = 4 OPERAND = 5 COMPARATOR = 6 STRING_LITERAL = 7 INTEGER_LITERAL = 8 FLOAT_LITERAL = 9 IDENTIFIER = 10 self._lexicon = Lexicon( [ (whitespace, IGNORE), (comma, COMMA), (open_parenthesis, OPEN_PARENTHESIS), (close_parenthesis, CLOSE_PARENTHESIS), (null, NULL), (operands, OPERAND), (comparators, COMPARATOR), (string_literal, STRING_LITERAL), (integer_literal, INTEGER_LITERAL), (float_literal, FLOAT_LITERAL), (identifier, IDENTIFIER), ] ) self._mapper = { COMMA: self.comma_handler, OPEN_PARENTHESIS: self.open_parenthesis_handler, CLOSE_PARENTHESIS: self.close_parenthesis_handler, NULL: self.null_handler, OPERAND: self.operand_handler, COMPARATOR: self.comparator_handler, STRING_LITERAL: self.string_literal_handler, INTEGER_LITERAL: self.integer_literal_handler, FLOAT_LITERAL: self.float_literal_handler, IDENTIFIER: self.identifier_handler, }
def _init(self): comma = Str(',') whitespace = Rep1(Any(' \t\n')) open_parenthesis = Str('(') close_parenthesis = Str(')') letter = Range('AZaz') digit = Range('09') prefix = letter + Rep(letter) + Str('.') identifier = prefix + letter + Rep(letter | digit | Str('_')) comparators = NoCase(Str('=', '!=', '<', '<=', '>', '>=', 'like', 'in')) string_literal = Str('\'') + Rep(AnyBut('\'') | Str(' ') | Str("\\'")) + Str('\'') integer_literal = Opt(Str('+', '-')) + Rep1(digit) float_literal = Opt(Str('+', '-')) + Rep1(digit) + Str('.') + Rep1(digit) operands = NoCase(Str('AND', 'OR')) null = Str('NULL') COMMA = 1 OPEN_PARENTHESIS = 2 CLOSE_PARENTHESIS = 3 NULL = 4 OPERAND = 5 COMPARATOR = 6 STRING_LITERAL = 7 INTEGER_LITERAL = 8 FLOAT_LITERAL = 9 IDENTIFIER = 10 self._lexicon = Lexicon([(whitespace, IGNORE), (comma, COMMA), (open_parenthesis, OPEN_PARENTHESIS), (close_parenthesis, CLOSE_PARENTHESIS), (null, NULL), (operands, OPERAND), (comparators, COMPARATOR), (string_literal, STRING_LITERAL), (integer_literal, INTEGER_LITERAL), (float_literal, FLOAT_LITERAL), (identifier, IDENTIFIER)]) self._mapper = { COMMA: self.comma_handler, OPEN_PARENTHESIS: self.open_parenthesis_handler, CLOSE_PARENTHESIS: self.close_parenthesis_handler, NULL: self.null_handler, OPERAND: self.operand_handler, COMPARATOR: self.comparator_handler, STRING_LITERAL: self.string_literal_handler, INTEGER_LITERAL: self.integer_literal_handler, FLOAT_LITERAL: self.float_literal_handler, IDENTIFIER: self.identifier_handler, }
class DiceScanner(Scanner): digit1 = Range("19") digit = Str("0") | digit1 number = digit1 + Rep(digit) dice = NoCase(Any("dw")) plusminus = Any("+-") def scan_number(self, text): self.stack.append(int(text)) self.begin('gotnum') def scan_number2(self, text): # after a die, self.multiplier is set d = int(text) result = 0 self.produce('output', '(') for x in xrange(self.multiplier): number = random.randint(1, d) result += number self.produce('output', number) if x + 1 < self.multiplier: self.produce('output', '+') self.produce('output', ')') self.stack.append(result) # go back to default state self.begin('') def scan_dice(self, text): self.multiplier = 1 self.begin('afterdie') def scan_dice2(self, text): # stack has a multiplier on top self.multiplier = self.stack.pop() self.begin('afterdie') def scan_mod(self, text): self.stack.append(text) self.produce('output', text) self.begin('start') def scan_mod2(self, text): # calc after num: need to produce prev num self.produce('output', self.stack[-1]) self.scan_mod(text) def handle_endline(self, text): self.produce('output', self.stack[-1]) lexicon = Lexicon([ (dice, scan_dice), (number, scan_number), (plusminus, scan_mod), (Rep1(Any(" ")), IGNORE), State('start', [ (dice, scan_dice), (number, scan_number), (Rep1(Any(" ")), IGNORE), ]), State('gotnum', [ (dice, scan_dice2), (Rep1(Any(" ")), IGNORE), (plusminus, scan_mod2), (Eol, handle_endline), ]), State('afterdie', [ (number, scan_number2), (Rep1(Any(" ")), IGNORE), ]), ]) def __init__(self, f): Scanner.__init__(self, self.lexicon, f) self.stack = [] self.begin('start') self.result = 0