diff options
author | Timotej Lazar <timotej.lazar@araneo.org> | 2015-02-04 18:47:07 +0100 |
---|---|---|
committer | Aleš Smodiš <aless@guru.si> | 2015-08-11 14:26:01 +0200 |
commit | 001739a6a93cceeb29f81ea2281ade0bef1a8645 (patch) | |
tree | 814a0890841ab55799329c76452ba25ce693caca /monkey/prolog/util.py | |
parent | 6a104bf8e2baea162d7f9f1d439dd8f671ddd413 (diff) |
Move monkey.prolog to root module
Diffstat (limited to 'monkey/prolog/util.py')
-rw-r--r-- | monkey/prolog/util.py | 152 |
1 files changed, 0 insertions, 152 deletions
diff --git a/monkey/prolog/util.py b/monkey/prolog/util.py deleted file mode 100644 index 8d8b266..0000000 --- a/monkey/prolog/util.py +++ /dev/null @@ -1,152 +0,0 @@ -#!/usr/bin/python3 - -from .lexer import lexer, operators -from ..util import Token - -# Return a list of tokens in [text]. -def tokenize(text): - lexer.input(text) - return [Token(t.type, t.value, t.lexpos) for t in lexer] - -# Return a one-line string representation of [tokens]. -def stringify(tokens): - def token_str(t): - if t.type in ('PERIOD', 'COMMA'): - return str(t) + ' ' - if t.type in operators.values(): - return ' ' + str(t) + ' ' - return str(t) - return ''.join(map(token_str, tokens)) - -# Yield the sequence of rules in [code]. -def split(code): - tokens = tokenize(code) - start = 0 - for idx, token in enumerate(tokens): - if token.type == 'PERIOD' and idx - start > 1: - yield stringify(tokens[start:idx]) - start = idx + 1 - -# Return a list of lines in [code] and a list of rule ranges. -def decompose(code): - lines = [] - rules = [] - tokens = tokenize(code) - tokens.append(Token('EOF')) - - line = [] - parens = [] - rule_start = 0 - for t in tokens: - if t.type == 'SEMI': - if line != []: - lines.append(tuple(line)) - line = [] - lines.append((t,)) - continue - if not parens: - if t.type in ('PERIOD', 'FROM', 'COMMA', 'EOF'): - if line != []: - lines.append(tuple(line)) - line = [] - if t.type in ('PERIOD', 'EOF') and rule_start < len(lines): - rules.append((rule_start, len(lines))) - rule_start = len(lines) - continue - if t.type in ('LPAREN', 'LBRACKET', 'LBRACE'): - parens.append(t.type) - elif parens: - if t.type == 'RPAREN' and parens[-1] == 'LPAREN': - parens.pop() - elif t.type == 'RBRACKET' and parens[-1] == 'LBRACKET': - parens.pop() - elif t.type == 'RBRACE' and parens[-1] == 'LBRACE': - parens.pop() - line.append(t) - return lines, rules - -# Format a list of [lines] according to [rules] (as returned by decompose). -def compose(lines, rules): - code = '' - for start, end in rules: - for i in range(start, end): - line = lines[i] - if i > start: - code += ' ' - code += stringify(line) - if i == end-1: - code += '.\n' - elif i == start: - code += ' :-\n' - else: - if line and line[-1].type != 'SEMI' and lines[i+1][-1].type != 'SEMI': - code += ',' - code += '\n' - return code.strip() - -# Rename variables in [tokens] to A0, A1, A2,… in order of appearance. -def rename_vars(tokens, names=None): - if names is None: - names = {} - next_id = len(names) - - # Return a new list. - tokens = list(tokens) - for i in range(len(tokens)): - if tokens[i].type == 'PERIOD': - names.clear() - next_id = 0 - elif tokens[i] == Token('VARIABLE', '_'): - tokens[i] = Token('VARIABLE', 'A{}'.format(next_id)) - next_id += 1 - elif tokens[i].type == 'VARIABLE': - cur_name = tokens[i].val - if cur_name not in names: - names[cur_name] = 'A{}'.format(next_id) - next_id += 1 - tokens[i] = Token('VARIABLE', names[cur_name]) - return tokens - -# transformation = before → after; applied on line which is part of rule -# return mapping from formal vars in before+after to actual vars in rule -# line and rule should of course not be normalized -def map_vars(before, after, line, rule): - mapping = {} - new_index = 0 - for i in range(len(before)): - if line[i].type == 'VARIABLE': - formal_name = before[i].val - if line[i].val != '_': - actual_name = line[i].val - else: - actual_name = 'New'+str(new_index) - new_index += 1 - mapping[formal_name] = actual_name - - remaining_formal = [t.val for t in after if t.type == 'VARIABLE' and t.val not in mapping.keys()] - remaining_actual = [t.val for t in rule if t.type == 'VARIABLE' and t.val != '_' and t.val not in mapping.values()] - - while len(remaining_actual) < len(remaining_formal): - remaining_actual.append('New'+str(new_index)) - new_index += 1 - - for i, formal_name in enumerate(remaining_formal): - mapping[formal_name] = remaining_actual[i] - - return mapping - -# Basic sanity check. -if __name__ == '__main__': - code = 'dup([H|T], [H1|T1]) :- dup(T1, T2). ' - lines, rules = decompose(code) - print(compose(lines, rules)) - - var_names = {} - before = rename_vars(tokenize("dup([A0|A1], [A2|A3])"), var_names) - after = rename_vars(tokenize("dup([A0|A1], [A5, A4|A3])"), var_names) - - line = lines[0] - rule = tokenize(code) - - mapping = map_vars(before, after, line, rule) - print(mapping) |