Parser to parse string templates like "Hello $name". Loosely based on (public domain, Ka-Ping Yee)
| 1579 | |
| 1580 | |
| 1581 | class Parser: |
| 1582 | """Parser to parse string templates like "Hello $name". |
| 1583 | |
| 1584 | Loosely based on <http://lfw.org/python/Itpl.py> (public domain, Ka-Ping Yee) |
| 1585 | """ |
| 1586 | |
| 1587 | namechars = "abcdefghijklmnopqrstuvwxyz" "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_" |
| 1588 | |
| 1589 | def __init__(self): |
| 1590 | self.reset() |
| 1591 | |
| 1592 | def reset(self): |
| 1593 | self.pos = 0 |
| 1594 | self.level = 0 |
| 1595 | self.text = "" |
| 1596 | |
| 1597 | def parse(self, text): |
| 1598 | """Parses the given text and returns a parse tree.""" |
| 1599 | self.reset() |
| 1600 | self.text = text |
| 1601 | return self.parse_all() |
| 1602 | |
| 1603 | def parse_all(self): |
| 1604 | while True: |
| 1605 | dollar = self.text.find("$", self.pos) |
| 1606 | if dollar < 0: |
| 1607 | break |
| 1608 | nextchar = self.text[dollar + 1] |
| 1609 | if nextchar in self.namechars: |
| 1610 | yield _Node("text", self.text[self.pos : dollar]) |
| 1611 | self.pos = dollar + 1 |
| 1612 | yield self.parse_expr() |
| 1613 | |
| 1614 | # for supporting ${x.id}, for backward compatibility |
| 1615 | elif nextchar == "{": |
| 1616 | saved_pos = self.pos |
| 1617 | self.pos = dollar + 2 # skip "${" |
| 1618 | expr = self.parse_expr() |
| 1619 | if self.text[self.pos] == "}": |
| 1620 | self.pos += 1 |
| 1621 | yield _Node("text", self.text[self.pos : dollar]) |
| 1622 | yield expr |
| 1623 | else: |
| 1624 | self.pos = saved_pos |
| 1625 | break |
| 1626 | else: |
| 1627 | yield _Node("text", self.text[self.pos : dollar + 1]) |
| 1628 | self.pos = dollar + 1 |
| 1629 | # $$ is used to escape $ |
| 1630 | if nextchar == "$": |
| 1631 | self.pos += 1 |
| 1632 | |
| 1633 | if self.pos < len(self.text): |
| 1634 | yield _Node("text", self.text[self.pos :]) |
| 1635 | |
| 1636 | def match(self): |
| 1637 | match = tokenprog.match(self.text, self.pos) |
| 1638 | if match is None: |