def parse_slice(tla, required, precedence): location = tla.location expr = parse_expr(tla, False, precedence) if expr is None: condition = lambda: tla.value.near == tla.value.balanced else: condition = lambda: tla.value.balanced if ahead_string(tla, '.:', ':.') and condition(): mode = ('incr' if tla.step().string == '.:' else 'decr') start = expr stop = parse_expr(tla, False, precedence) if start is None: start = Constant(tla.location, 'symbol', 'null') if stop is None: stop = Constant(tla.location, 'symbol', 'null') stride = Constant(tla.location, 'symbol', 'null') step = Constant(tla.location, 'symbol', 'null') if ahead_string(tla, '::') and tla.value.balanced: expect(tla, 'operator') stride = parse_expr(tla, False, precedence) if ahead_string(tla, '..') and tla.value.balanced: expect(tla, 'operator') step = parse_expr(tla, False, precedence) return Struct(location, mode, start, stop, stride, step) if expr is None: return parse_expr(tla, required, precedence) return expr
def parse_fullterm(tla, required): term = parse_term(tla, required) while not tla.empty and tla.value.near: location = tla.location if ahead(tla, 'attribute'): string = expect(tla, 'attribute').string term = Struct(location, 'attribute', term, Constant(location, 'attribute', string[1:])) elif ahead(tla, 'leftparen'): expect(tla, 'leftparen') term = parse_arglist(tla, location, term) term.group = 'call' expect(tla, 'rightparen') elif ahead(tla, 'leftbracket'): expect(tla, 'leftbracket') term = parse_arglist(tla, location, term) term.group = 'index' expect(tla, 'rightbracket') elif ahead_string(tla, ';'): expect(tla, 'operator') term = Struct(location, 'call', term, Struct(location, "block")) elif ahead_string(tla, '.;'): expect(tla, 'operator') term = Struct(location, 'attribute', term, Struct(location, "block")) else: break return term
def parse_sentence(tla, required=True): location = tla.location head = parse_word(tla, required, 10) if head is None: return if ahead_string(tla, '=', ':', ':='): operator = Constant(tla.location, 'operator', expect(tla, 'operator').string) blocks = find_placeholders(head) if len(blocks) > 0: raise Exception( "%s: not allowed on toplevel lhs side of '=' or ':'." % linecol(blocks[0].location)) return Struct(location, 'infix', operator, head, parse_sentence(tla)) sentence = Struct(location, 'sentence', head) for word in repeated(parse_word, tla, False, 0): sentence.append(word) blocks = find_placeholders(sentence) if ahead(tla, 'indent'): expect(tla, 'indent') if len(blocks) > 1: raise Exception("%s: cannot fill this placeholder" % linecol(blocks[0].location)) elif len(blocks) > 0: block = blocks[0] for item in parse_block(tla): block.append(item) else: sentence.append(Struct(location, 'block', *parse_block(tla))) expect(tla, 'dedent') elif len(blocks) > 0: raise Exception("%s: cannot fill this placeholder" % linecol(blocks[0].location)) return sentence
def p_intnum_or_id(p): """ INTNUM_OR_ID : INTNUM | ID """ if p.slice[1].type == 'INTNUM': p[0] = Constant(p[1]) else: p[0] = Variable(p[1])
def parse_slot(tla, required, precedence): if precedence >= 10: return parse_slice(tla, required, precedence) location = tla.location slic = parse_slice(tla, required, precedence) if ahead_string(tla, '=', ':'): operator = Constant(tla.location, 'operator', expect(tla, 'operator').string) return Struct(location, 'infix', operator, slic, parse_slot(tla, required, precedence)) return slic
def parse_expr(tla, required, precedence): location = tla.location if ahead(tla, 'operator') and tla.value.string in prefix_operators: if tla.value.near <> tla.value.balanced and tla.value.string <> 'not': raise Exception("%s: This is not C" % linecol(tla.location)) operator = Constant(tla.location, 'operator', expect(tla, 'operator').string) expr = Struct(location, 'prefix', operator, parse_expr(tla, True, prefix_operators[operator.value])) else: expr = parse_fullterm(tla, required) while ahead(tla, 'operator') and tla.value.string in infix_operators: prec = infix_operators[tla.value.string] if prec <= precedence or not tla.value.balanced: break prex = prec - (tla.value.string in right_binding) operator = Constant(tla.location, 'operator', expect(tla, 'operator').string) expr = Struct(location, 'infix', operator, expr, parse_expr(tla, True, prex)) return expr
def p_term(p): """ TERM : ID | INTNUM | FLOATNUM | STRING | MATRIX | FUNCTION_CALL | ID "'" | '-' ID """ if len(p) == 3: p[0] = Variable(str(p[1]) + str(p[2])) elif p.slice[1].type == 'ID': p[0] = Variable(p[1]) elif p.slice[1].type == 'INTNUM': p[0] = Constant(p[1]) elif p.slice[1].type == 'FLOATNUM': p[0] = Constant(p[1]) elif p.slice[1].type == 'STRING': p[0] = Constant(p[1]) else: p[0] = p[1]
def parse_term(tla, required): location = tla.location if ahead(tla, 'symbol'): return Constant(location, 'symbol', expect(tla, 'symbol').string) elif ahead_string(tla, ';'): expect(tla, 'operator') return Struct(location, 'block') elif ahead(tla, 'string'): string = expect(tla, 'string').string return Constant(location, 'string', string[1:-1]) elif ahead(tla, 'number'): string = expect(tla, 'number').string if ahead(tla, 'flot'): if not tla.value.near: raise Exception( "%s: decimal expression supposed to be typed with no spacing" % (linecol(tla.location))) string += expect(tla, 'flot').string return Constant(location, 'float', string) return Constant(location, 'number', string) elif ahead(tla, 'leftparen'): expect(tla, 'leftparen') if ahead(tla, 'operator'): operator = Constant(tla.location, 'operator', expect(tla, 'operator').string) expect(tla, 'rightparen') return operator else: term = parse_arglist(tla, location) expect(tla, 'rightparen') if ahead_string(tla, '->'): expect(tla, 'operator') blocks = find_placeholders(term) if len(blocks) > 0: raise Exception( "%s: not allowed inside function argument list" % linecol(blocks[0].location)) return parse_function(tla, location, term) elif len(term) == 1 and term[0].group != 'block': return term[0] else: term.group = 'tuple' return term elif ahead(tla, 'leftbracket'): expect(tla, 'leftbracket') arglist = parse_arglist(tla, location) arglist.group = 'list' expect(tla, 'rightbracket') return arglist elif ahead_string(tla, '->'): expect(tla, 'operator') return parse_function(tla, location, Struct(location, 'arglist')) elif ahead_string(tla, '@'): expect(tla, 'operator') term = Constant(location, 'self', None) if ahead(tla, '.'): raise Exception("%s: you're serious?" % (linecol(tla.location))) if ahead(tla, 'symbol') and tla.value.near: term = Struct( location, 'attribute', term, Constant(tla.location, 'attribute', expect(tla, 'symbol').string)) return term elif required: raise Exception( "%s: a term is missing after '%s'" % (linecol(tla.previous_location), tla.previous_value.string))