Skip to content

Commit

Permalink
New operator and misc tweaks.
Browse files Browse the repository at this point in the history
- Added TM operator and k builtin variable
- Redefined -l flag, added -P and -S
- Made strip operators with regex more robust
- Updated documentation
  • Loading branch information
dloscutoff committed Jun 12, 2015
1 parent 2d75c72 commit db31988
Show file tree
Hide file tree
Showing 8 changed files with 144 additions and 67 deletions.
12 changes: 8 additions & 4 deletions Documentation/Command-line flags.md
Expand Up @@ -12,13 +12,17 @@ When Pip is called without any of these flags, the default is stdin for interact

### List formatting

`-p` When printing lists, Pretty-print them by executing RP on them first
`-p` Pretty-print lists by executing RP on them first

`-s` When printing lists, join them on Space first
`-s` Join lists on space

`-n` When printing lists, join them on Newline first
`-n` Join lists on newline

`-l` When printing lists, join each item (if a list) on space, then join the list on newline (i.e. print list as multiple Lines)
`-l` Join each item on empty string, then join results on newline (i.e. print list as multiple lines)

`-P` Execute RP on each item, then join results on newline

`-S` Join each item on space, then join results on newline

The default is to join lists on empty string, as in CJam.

Expand Down
4 changes: 4 additions & 0 deletions Documentation/Operators.md
Expand Up @@ -190,6 +190,10 @@ U/B/T = Unary/Binary/Ternary

<pre>TB U</pre> Convert decimal integer to binary

<pre>TM B</pre> Trim string by given number of characters from front and end (takes Scalar for same amt on both sides or Range for different amts)

<pre>TM U</pre> Trim first and last characters from string

<pre>UC U</pre> Convert to UPPERCASE

<pre>UQ U</pre> Keep only unique values from iterable
Expand Down
2 changes: 2 additions & 0 deletions Documentation/Pre-defined variables.md
Expand Up @@ -6,6 +6,8 @@ For the most up-to-date catalogue, see list near the top of `execution.py`. The

`i` 0

`k` `", "`

`l` Empty list

`m` 1000 (mnemonic: Roman numeral M)
Expand Down
6 changes: 6 additions & 0 deletions Documentation/Regex operations.md
Expand Up @@ -39,3 +39,9 @@ Usage: `xINs`
Usage: `sRxp`

Replace each match of Pattern `x` in Scalar `s` with replacement (Pattern or Scalar) `p`.

### Split: ^

Usage: `s^x`

Split Scalar `s` on occurrences of Pattern `x`. If `x` contains matching groups, they are included in the resulting List.
141 changes: 89 additions & 52 deletions execution.py
Expand Up @@ -29,6 +29,7 @@ def __init__(self, listFormat=None, showWarnings=False):
"_": Block([], tokens.Name("a")),
"h": Scalar("100"),
"i": Scalar("0"),
"k": Scalar(", "),
"l": List([]),
"m": Scalar("1000"),
"n": Scalar("\n"),
Expand Down Expand Up @@ -1007,11 +1008,13 @@ def LSTRIP(self, string, extra=None):
patternStr = str(extra)
if patternStr == "":
return string
string = str(string)
oldString = str(string)
beginning = re.compile("^" + patternStr)
while beginning.search(string):
string = beginning.sub("", string)
return Scalar(string)
newString = beginning.sub("", oldString)
while oldString != newString:
oldString = newString
newString = beginning.sub("", oldString)
return Scalar(newString)
elif extra is None:
return Scalar(str(string).lstrip())
else:
Expand Down Expand Up @@ -1564,11 +1567,13 @@ def RSTRIP(self, string, extra=None):
patternStr = str(extra)
if patternStr == "":
return string
string = str(string)
oldString = str(string)
end = re.compile(patternStr + "$")
while end.search(string):
string = end.sub("", string)
return Scalar(string)
newString = end.sub("", oldString)
while oldString != newString:
oldString = newString
newString = end.sub("", oldString)
return Scalar(newString)
elif extra is None:
return Scalar(str(string).rstrip())
else:
Expand Down Expand Up @@ -1714,48 +1719,6 @@ def STREQUAL(self, lhs, rhs):
result = False
return Scalar(result)

def STRIP(self, string, extra=None):
if extra is nil:
return string
elif type(extra) is Scalar:
extra = str(extra)
elif type(extra) in (Pattern, List, Range) or extra is None:
pass
else:
self.err.warn("Unimplemented argtype for rhs of STRIP:",
type(extra))
return nil

if type(string) in (List, Range):
return List(self.STRIP(item, extra) for item in string)
elif type(string) is Scalar:
if type(extra) in (List, Range):
for item in extra:
string = self.STRIP(string, item)
return string
elif type(extra) is str:
return Scalar(str(string).strip(extra))
elif type(extra) is Pattern:
# Python doesn't have a regex strip operation--we have to
# roll our own
patternStr = str(extra)
if patternStr == "":
return string
string = str(string)
beginning = re.compile("^" + patternStr)
while beginning.search(string):
string = beginning.sub("", string)
end = re.compile(patternStr + "$")
while end.search(string):
string = end.sub("", string)
return Scalar(string)
elif extra is None:
return Scalar(str(string).strip())
else:
self.err.warn("Unimplemented argtype for lhs of STRIP:",
type(string))
return nil

def STRGREATER(self, lhs, rhs):
if type(lhs) is type(rhs) is Scalar:
result = str(lhs) > str(rhs)
Expand Down Expand Up @@ -1796,6 +1759,52 @@ def STRGREATEREQ(self, lhs, rhs):
result = False
return Scalar(result)

def STRIP(self, string, extra=None):
if extra is nil:
return string
elif type(extra) is Scalar:
extra = str(extra)
elif type(extra) in (Pattern, List, Range) or extra is None:
pass
else:
self.err.warn("Unimplemented argtype for rhs of STRIP:",
type(extra))
return nil

if type(string) in (List, Range):
return List(self.STRIP(item, extra) for item in string)
elif type(string) is Scalar:
if type(extra) in (List, Range):
for item in extra:
string = self.STRIP(string, item)
return string
elif type(extra) is str:
return Scalar(str(string).strip(extra))
elif type(extra) is Pattern:
# Python doesn't have a regex strip operation--we have to
# roll our own
patternStr = str(extra)
if patternStr == "":
return string
oldString = str(string)
beginning = re.compile("^" + patternStr)
newString = beginning.sub("", oldString)
while oldString != newString:
oldString = newString
newString = beginning.sub("", oldString)
end = re.compile(patternStr + "$")
newString = end.sub("", oldString)
while oldString != newString:
oldString = newString
newString = end.sub("", oldString)
return Scalar(newString)
elif extra is None:
return Scalar(str(string).strip())
else:
self.err.warn("Unimplemented argtype for lhs of STRIP:",
type(string))
return nil

def STRLESS(self, lhs, rhs):
if type(lhs) is type(rhs) is Scalar:
result = str(lhs) < str(rhs)
Expand Down Expand Up @@ -1904,8 +1913,36 @@ def TOBASE(self, number, base=None):
number //= base
return Scalar(sign + result)
else:
self.err.warn("Unimplemented argtype for TOBASE:",
type(number))
self.err.warn("Unimplemented argtype for TOBASE:", type(number))
return nil

def TRIM(self, string, extra=None):
if type(string) is Range:
# Apply memberwise to elements of Range (a flag takes care of the
# List case
return List(self.TRIM(element, extra) for element in string)

if extra is None:
front = back = 1
elif type(extra) is Scalar:
front = back = int(extra)
elif type(extra) is Range:
front = extra.getLower() or 0
back = extra.getUpper() or 0
elif extra is nil:
return string
else:
self.err.warn("Unimplemented argtype for rhs of TRIM:",
type(extra))
return nil

if type(string) is Scalar:
front = max(front, 0)
back = max(back, 0)
return Scalar(str(string)[front:-back])
else:
self.err.warn("Unimplemented argtype for lhs of TRIM:",
type(string))
return nil

def UNIQUE(self, iterable):
Expand Down
8 changes: 5 additions & 3 deletions operators.py
Expand Up @@ -193,14 +193,16 @@ def copy(self):
("X", "STRMUL", "L", "", RVALS | IN_LAMBDA | RANGE_EACH | LIST_EACH),
],
[2,
("||", "STRIP", "L", "", RVALS | IN_LAMBDA ),
("|>", "LSTRIP", "L", "", RVALS | IN_LAMBDA ),
("<|", "RSTRIP", "L", "", RVALS | IN_LAMBDA ),
("||", "STRIP", "L", "", RVALS | IN_LAMBDA),
("|>", "LSTRIP", "L", "", RVALS | IN_LAMBDA),
("<|", "RSTRIP", "L", "", RVALS | IN_LAMBDA),
("TM", "TRIM", "L", "", RVALS | IN_LAMBDA | LIST_EACH),
],
[1,
("||", "STRIP", "L", "", RVALS | IN_LAMBDA | LIST_EACH),
("|>", "LSTRIP", "L", "", RVALS | IN_LAMBDA | LIST_EACH),
("<|", "RSTRIP", "L", "", RVALS | IN_LAMBDA | LIST_EACH),
("TM", "TRIM", "L", "", RVALS | IN_LAMBDA | LIST_EACH),
("LC", "LOWERCASE", "L", None, RVALS | IN_LAMBDA | LIST_EACH),
("UC", "UPPERCASE", "L", None, RVALS | IN_LAMBDA | LIST_EACH),
],
Expand Down
18 changes: 15 additions & 3 deletions pip.py
Expand Up @@ -22,7 +22,7 @@
from errors import FatalError
import sys, argparse

VERSION = "0.15.06.08"
VERSION = "0.15.06.11"

def pip(interactive=True):
if interactive:
Expand Down Expand Up @@ -67,8 +67,8 @@ def pip(interactive=True):
action="store_true")
listFormats.add_argument("-l",
"--lines",
help="output list items space-concatenated on"
+ " separate lines",
help="output list items on separate lines, " +
"concatenated",
action="store_true")
listFormats.add_argument("-n",
"--newline",
Expand All @@ -78,6 +78,11 @@ def pip(interactive=True):
"--repr",
help="print lists in repr form",
action="store_true")
listFormats.add_argument("-P",
"--reprlines",
help="output list items on separate lines, " +
"repr'd",
action="store_true")
argparser.add_argument("-r",
"--readlines",
help="read args from lines of stdin",
Expand All @@ -86,6 +91,11 @@ def pip(interactive=True):
"--space",
help="concatenate lists on space",
action="store_true")
listFormats.add_argument("-S",
"--spacelines",
help="output list items on separate lines, " +
"space-concatenated",
action="store_true")
argparser.add_argument("-v",
"--verbose",
help="show extra messages",
Expand All @@ -102,7 +112,9 @@ def pip(interactive=True):
if options.debug:
options.warnings = options.verbose = options.repr = True
listFormat = ("p" if options.repr else
"P" if options.reprlines else
"s" if options.space else
"S" if options.spacelines else
"n" if options.newline else
"l" if options.lines else
None)
Expand Down
20 changes: 15 additions & 5 deletions ptypes.py
Expand Up @@ -266,7 +266,9 @@ class List:
# n: Join on newline
# p: Pretty-print: use the repr instead (useful for debugging)
# s: Join on space
# l: Print as multiple lines, with each line joined on space
# l: Print as multiple lines, with each line joined on empty string
# P: Print as multiple lines, with each line repr'd
# S: Print as multiple lines, with each line joined on space
outFormat = None

def __init__(self, value=None):
Expand Down Expand Up @@ -299,14 +301,22 @@ def __str__(self):
elif self.outFormat == "s":
return " ".join(str(i) for i in self._value)
elif self.outFormat == "l":
# Each item in the list is a line, which in turn is joined on
# empty string
return "\n".join(i.joined("") if type(i) is List else str(i)
for i in self._value)
elif self.outFormat == "P":
# Each item in the list is a line, which in turn is repr'd
return "\n".join(repr(i) for i in self._value)
elif self.outFormat == "S":
# Each item in the list is a line, which in turn is joined on
# space
return "\n".join(i.joinOnSpace() if type(i) is List else str(i)
return "\n".join(i.joined(" ") if type(i) is List else str(i)
for i in self._value)

def joinOnSpace(self):
return " ".join(i.joinOnSpace() if type(i) is List else str(i)
for i in self._value)
def joined(self, separator):
return separator.join(i.joined(separator) if type(i) is List else str(i)
for i in self._value)

def __repr__(self):
return "[" + ";".join(repr(i) for i in self._value) + "]"
Expand Down

0 comments on commit db31988

Please sign in to comment.