You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
77 lines
3.0 KiB
Python
77 lines
3.0 KiB
Python
11 years ago
|
#!/usr/bin/env python
|
||
|
# encoding: utf-8
|
||
|
|
||
|
"""Parses tokens into text objects."""
|
||
|
|
||
|
from UltiSnips.text_objects._lexer import tokenize, EscapeCharToken, \
|
||
|
VisualToken, TransformationToken, TabStopToken, MirrorToken, \
|
||
|
PythonCodeToken, VimLCodeToken, ShellCodeToken
|
||
|
from UltiSnips.position import Position
|
||
|
from UltiSnips.text_objects._escaped_char import EscapedChar
|
||
|
from UltiSnips.text_objects._mirror import Mirror
|
||
|
from UltiSnips.text_objects._python_code import PythonCode
|
||
|
from UltiSnips.text_objects._shell_code import ShellCode
|
||
|
from UltiSnips.text_objects._tabstop import TabStop
|
||
|
from UltiSnips.text_objects._transformation import Transformation
|
||
|
from UltiSnips.text_objects._viml_code import VimLCode
|
||
|
from UltiSnips.text_objects._visual import Visual
|
||
|
|
||
|
_TOKEN_TO_TEXTOBJECT = {
|
||
|
EscapeCharToken: EscapedChar,
|
||
|
VisualToken: Visual,
|
||
|
ShellCodeToken: ShellCode,
|
||
|
PythonCodeToken: PythonCode,
|
||
|
VimLCodeToken: VimLCode,
|
||
|
}
|
||
|
|
||
|
def _resolve_ambiguity(all_tokens, seen_ts):
|
||
|
"""$1 could be a Mirror or a TabStop. This figures this out."""
|
||
|
for parent, token in all_tokens:
|
||
|
if isinstance(token, MirrorToken):
|
||
|
if token.number not in seen_ts:
|
||
|
seen_ts[token.number] = TabStop(parent, token)
|
||
|
else:
|
||
|
Mirror(parent, seen_ts[token.number], token)
|
||
|
|
||
|
def _create_transformations(all_tokens, seen_ts):
|
||
|
"""Create the objects that need to know about tabstops."""
|
||
|
for parent, token in all_tokens:
|
||
|
if isinstance(token, TransformationToken):
|
||
|
if token.number not in seen_ts:
|
||
|
raise RuntimeError(
|
||
|
"Tabstop %i is not known but is used by a Transformation"
|
||
|
% token.number)
|
||
|
Transformation(parent, seen_ts[token.number], token)
|
||
|
|
||
|
def _do_parse(all_tokens, seen_ts, parent_to, text, indent):
|
||
|
"""Recursive function that actually creates the objects."""
|
||
|
tokens = list(tokenize(text, indent, parent_to.start))
|
||
|
for token in tokens:
|
||
|
all_tokens.append((parent_to, token))
|
||
|
if isinstance(token, TabStopToken):
|
||
|
ts = TabStop(parent_to, token)
|
||
|
seen_ts[token.number] = ts
|
||
|
|
||
|
_do_parse(all_tokens, seen_ts, ts, token.initial_text, indent)
|
||
|
else:
|
||
|
klass = _TOKEN_TO_TEXTOBJECT.get(token.__class__, None)
|
||
|
if klass is not None:
|
||
|
klass(parent_to, token)
|
||
|
|
||
|
def parse_text_object(parent_to, text, indent):
|
||
|
"""Parses a text object from 'text' assuming the current 'indent'. Will
|
||
|
instantiate all the objects and link them as children to parent_to. Will
|
||
|
also put the initial text into Vim."""
|
||
|
seen_ts = {}
|
||
|
all_tokens = []
|
||
|
|
||
|
_do_parse(all_tokens, seen_ts, parent_to, text, indent)
|
||
|
_resolve_ambiguity(all_tokens, seen_ts)
|
||
|
_create_transformations(all_tokens, seen_ts)
|
||
|
|
||
|
if 0 not in seen_ts:
|
||
|
mark = all_tokens[-1][1].end # Last token is always EndOfText
|
||
|
m1 = Position(mark.line, mark.col)
|
||
|
TabStop(parent_to, 0, mark, m1)
|
||
|
parent_to.replace_initial_text()
|