Browse Source

Finish implementing Builder for all existing Nodes; BuildStack.

tags/v0.1
Ben Kurtovic 12 years ago
parent
commit
219b9086d2
5 changed files with 87 additions and 19 deletions
  1. +1
    -1
      mwparserfromhell/nodes/heading.py
  2. +1
    -1
      mwparserfromhell/nodes/tag.py
  3. +7
    -4
      mwparserfromhell/parser/build_stack.py
  4. +77
    -13
      mwparserfromhell/parser/builder.py
  5. +1
    -0
      mwparserfromhell/parser/tokens.py

+ 1
- 1
mwparserfromhell/nodes/heading.py View File

@@ -30,7 +30,7 @@ class Heading(Node):
self._level = level self._level = level


def __unicode__(self): def __unicode__(self):
return ("=" * self.level) + self.title + ("=" * self.level)
return ("=" * self.level) + unicode(self.title) + ("=" * self.level)


def __iternodes__(self, getter): def __iternodes__(self, getter):
yield None, self yield None, self


+ 1
- 1
mwparserfromhell/nodes/tag.py View File

@@ -67,7 +67,7 @@ class Tag(Node):
TAGS_INVISIBLE = set((TAG_REF, TAG_GALLERY, TAG_MATH, TAG_NOINCLUDE)) TAGS_INVISIBLE = set((TAG_REF, TAG_GALLERY, TAG_MATH, TAG_NOINCLUDE))
TAGS_VISIBLE = set(range(300)) - TAGS_INVISIBLE TAGS_VISIBLE = set(range(300)) - TAGS_INVISIBLE


def __init__(self, type_, tag, contents, attrs=None, showtag=True,
def __init__(self, type_, tag, contents=None, attrs=None, showtag=True,
self_closing=False, open_padding=0, close_padding=0): self_closing=False, open_padding=0, close_padding=0):
self._type = type_ self._type = type_
self._tag = tag self._tag = tag


+ 7
- 4
mwparserfromhell/parser/build_stack.py View File

@@ -20,17 +20,20 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE. # SOFTWARE.


from ..smart_list import SmartList
from ..wikicode import Wikicode

__all__ = ["BuildStack"] __all__ = ["BuildStack"]


class BuildStack(object): class BuildStack(object):
def __init__(self): def __init__(self):
pass
self._stacks = []


def write(self, item): def write(self, item):
pass
self._stacks[-1].append(item)


def push(self): def push(self):
pass
self._stacks.append([])


def pop(self): def pop(self):
pass
return Wikicode(SmartList(self._stacks.pop()))

+ 77
- 13
mwparserfromhell/parser/builder.py View File

@@ -24,10 +24,8 @@ import re


from . import tokens from . import tokens
from .build_stack import BuildStack from .build_stack import BuildStack
from ..nodes import Template, Text
from ..nodes.extras import Parameter
from ..smart_list import SmartList
from ..wikicode import Wikicode
from ..nodes import Heading, HTMLEntity, Tag, Template, Text
from ..nodes.extras import Attribute, Parameter


__all__ = ["Builder"] __all__ = ["Builder"]


@@ -36,22 +34,19 @@ class Builder(object):
self._tokens = [] self._tokens = []
self._stack = BuildStack() self._stack = BuildStack()


def _pop(self):
return Wikicode(SmartList(stack.pop()))

def _handle_parameter(self, key): def _handle_parameter(self, key):
showkey = False showkey = False
self._stack.push() self._stack.push()
while self._tokens: while self._tokens:
token = self._tokens.pop(0) token = self._tokens.pop(0)
if isinstance(token, tokens.TEMPLATE_PARAM_EQUALS): if isinstance(token, tokens.TEMPLATE_PARAM_EQUALS):
key = self._pop()
key = self._stack.pop()
showkey = True showkey = True
self._stack.push() self._stack.push()
elif isinstance(token, (tokens.TEMPLATE_PARAM_SEPARATOR, elif isinstance(token, (tokens.TEMPLATE_PARAM_SEPARATOR,
tokens.TEMPLATE_CLOSE)):
tokens.TEMPLATE_CLOSE)):
self._tokens.insert(0, token) self._tokens.insert(0, token)
value = self._pop()
value = self._stack.pop()
return Parameter(key, value, showkey) return Parameter(key, value, showkey)
else: else:
self._stack.write(self._handle_token()) self._stack.write(self._handle_token())
@@ -65,7 +60,7 @@ class Builder(object):
token = self._tokens.pop(0) token = self._tokens.pop(0)
if isinstance(token, tokens.TEMPLATE_PARAM_SEPARATOR): if isinstance(token, tokens.TEMPLATE_PARAM_SEPARATOR):
if not params: if not params:
name = self._pop()
name = self._stack.pop()
param = self._handle_parameter(min(int_key_range - int_keys)) param = self._handle_parameter(min(int_key_range - int_keys))
if re.match(r"[1-9][0-9]*$", param.key.strip()): if re.match(r"[1-9][0-9]*$", param.key.strip()):
int_keys.add(int(param.key)) int_keys.add(int(param.key))
@@ -73,21 +68,90 @@ class Builder(object):
params.append(param) params.append(param)
elif isinstance(token, tokens.TEMPLATE_CLOSE): elif isinstance(token, tokens.TEMPLATE_CLOSE):
if not params: if not params:
name = self._pop()
name = self._stack.pop()
return Template(name, params) return Template(name, params)
else: else:
self._stack.write(self._handle_token()) self._stack.write(self._handle_token())


def _handle_entity(self):
token = self._tokens.pop(0)
if isinstance(token, tokens.HTML_ENTITY_NUMERIC):
token = self._tokens.pop(0)
if isinstance(token, tokens.HTML_ENTITY_HEX):
token = self._tokens.pop(0)
return HTMLEntity(token.text, named=False, hexadecimal=True)
return HTMLEntity(token.text, named=False, hexadecimal=False)
return HTMLEntity(token.text, named=True, hexadecimal=False)

def _handle_heading(self, token):
level = token.level
self._stack.push()
while self._tokens:
token = self._tokens.pop(0)
if isinstance(token, tokens.HEADING_BLOCK):
title = self._stack.pop()
return Heading(title, level)
else:
self._stack.write(self._handle_token())

def _handle_attribute(self):
name, quoted = None, False
self._stack.push()
while self._tokens:
token = self._tokens.pop(0)
if isinstance(token, tokens.TAG_ATTR_EQUALS):
name = self._stack.pop()
self._stack.push()
elif isinstance(token, tokens.TAG_ATTR_QUOTE):
quoted = True
elif isinstance(token, (tokens.TAG_ATTR_START,
tokens.TAG_CLOSE_OPEN)):
self._tokens.insert(0, token)
if name is not None:
return Attribute(name, self._stack.pop(), quoted)
return Attribute(self._stack.pop(), quoted=quoted)
else:
self._stack.write(self._handle_token())

def _handle_tag(self, token):
type_, showtag, attrs = token.type, token.showtag, attrs
self._stack.push()
while self._tokens:
token = self._tokens.pop(0)
if isinstance(token, tokens.TAG_ATTR_START):
attrs.append(self._handle_attribute())
elif isinstance(token, tokens.TAG_CLOSE_OPEN):
open_pad = token.padding
tag = self._stack.pop()
self._stack.push()
elif isinstance(token, tokens.TAG_CLOSE_SELFCLOSE):
tag = self._stack.pop()
return Tag(type_, tag, attrs=attrs, showtag=showtag,
self_closing=True, open_padding=token.padding)
elif isinstance(token, tokens.TAG_OPEN_CLOSE):
contents = self._stack.pop()
elif isinstance(token, tokens.TAG_CLOSE_CLOSE):
return Tag(type_, tag, contents, attrs, showtag, self_closing,
open_pad, token.padding)
else:
self._stack.write(self._handle_token())

def _handle_token(self): def _handle_token(self):
token = self._tokens.pop(0) token = self._tokens.pop(0)
if isinstance(token, tokens.TEXT): if isinstance(token, tokens.TEXT):
return Text(token.text) return Text(token.text)
elif isinstance(token, tokens.TEMPLATE_OPEN): elif isinstance(token, tokens.TEMPLATE_OPEN):
return self._handle_template() return self._handle_template()
elif isinstance(token, tokens.HTML_ENTITY_START):
return self._handle_entity()
elif isinstance(token, tokens.HEADING_BLOCK):
return self._handle_heading(token)
elif isinstance(token, tokens.TAG_OPEN_OPEN):
return self._handle_tag(token)


def build(self, tokens): def build(self, tokens):
self._tokens = tokens self._tokens = tokens
self._stack.push() self._stack.push()
while self._tokens: while self._tokens:
self._stack.write(self._handle_token()) self._stack.write(self._handle_token())
return self._pop()
return self._stack.pop()

+ 1
- 0
mwparserfromhell/parser/tokens.py View File

@@ -55,6 +55,7 @@ HTML_ENTITY_END = make("HTML_ENTITY_END") # ;
HEADING_BLOCK = make("HEADING_BLOCK") # =... HEADING_BLOCK = make("HEADING_BLOCK") # =...


TAG_OPEN_OPEN = make("TAG_OPEN_OPEN") # < TAG_OPEN_OPEN = make("TAG_OPEN_OPEN") # <
TAG_ATTR_START = make("TAG_ATTR_START")
TAG_ATTR_EQUALS = make("TAG_ATTR_EQUALS") # = TAG_ATTR_EQUALS = make("TAG_ATTR_EQUALS") # =
TAG_ATTR_QUOTE = make("TAG_ATTR_QUOTE") # " TAG_ATTR_QUOTE = make("TAG_ATTR_QUOTE") # "
TAG_CLOSE_OPEN = make("TAG_CLOSE_OPEN") # > TAG_CLOSE_OPEN = make("TAG_CLOSE_OPEN") # >


Loading…
Cancel
Save