Expand the test coverage, add octals
This commit is contained in:
parent
8cd91ecb8c
commit
6a33fa1016
2 changed files with 57 additions and 11 deletions
|
@ -272,32 +272,55 @@ class Parser(SexpParser):
|
||||||
def parse_sqlist(cls, f: PosTrackingBufferedReader):
|
def parse_sqlist(cls, f: PosTrackingBufferedReader):
|
||||||
return cls.parse_delimeted(f, "[", "]", lambda *args: ListToken(*args, ListType.SQUARE))
|
return cls.parse_delimeted(f, "[", "]", lambda *args: ListToken(*args, ListType.SQUARE))
|
||||||
|
|
||||||
|
# FIXME (arrdem 2020-07-18):
|
||||||
|
# Break this apart into middleware or composable features somehow?
|
||||||
@classmethod
|
@classmethod
|
||||||
def handle_symbol(cls, buff, pos):
|
def handle_symbol(cls, buff, pos):
|
||||||
# Parsing integers
|
def _sign(m, idx):
|
||||||
if m := re.fullmatch(r"[+-]?\d[\d_]*", buff):
|
if m.group(idx) == '-':
|
||||||
return IntegerToken(int(buff.replace("_", "")), buff, pos)
|
return -1
|
||||||
|
else:
|
||||||
|
return 1
|
||||||
|
|
||||||
# Parsing integers with bases
|
# Parsing integers with bases
|
||||||
elif m := re.fullmatch(r"(\d+)r([a-z0-9_]+)", buff):
|
if m := re.fullmatch(r"([+-]?)(\d+)r([a-z0-9_]+)", buff):
|
||||||
return IntegerToken(int(m.group(2).replace("_", "")), int(m.group(1)), buff, pos)
|
return IntegerToken(
|
||||||
|
_sign(m, 1) * int(m.group(3).replace("_", ""),
|
||||||
|
int(m.group(2))),
|
||||||
|
buff,
|
||||||
|
pos,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Parsing hex numbers
|
||||||
|
if m := re.fullmatch(r"([+-]?)0[xX]([A-Fa-f0-9_]*)", buff):
|
||||||
|
val = m.group(2).replace("_", "")
|
||||||
|
return IntegerToken(_sign(m, 1) * int(val, 16), buff, pos)
|
||||||
|
|
||||||
|
# Parsing octal numbers
|
||||||
|
if m := re.fullmatch(r"([+-]?)0([\d_]*)", buff):
|
||||||
|
val = m.group(2).replace("_", "")
|
||||||
|
return IntegerToken(_sign(m, 1) * int(val, 8), buff, pos)
|
||||||
|
|
||||||
|
# Parsing integers
|
||||||
|
if m := re.fullmatch(r"([+-]?)\d[\d_]*", buff):
|
||||||
|
return IntegerToken(int(buff.replace("_", "")), buff, pos)
|
||||||
|
|
||||||
# Parsing fractions
|
# Parsing fractions
|
||||||
elif m := re.fullmatch(r"([+-]?\d[\d_]*)/(\d[\d_]*)", buff):
|
if m := re.fullmatch(r"([+-]?)(\d[\d_]*)/(\d[\d_]*)", buff):
|
||||||
return FractionToken(
|
return FractionToken(
|
||||||
Fraction(
|
Fraction(
|
||||||
int(m.group(1).replace("_", "")),
|
int(m.group(2).replace("_", "")),
|
||||||
int(m.group(2).replace("_", ""))),
|
int(m.group(3).replace("_", ""))),
|
||||||
buff,
|
buff,
|
||||||
pos,
|
pos,
|
||||||
)
|
)
|
||||||
|
|
||||||
# Parsing floats
|
# Parsing floats
|
||||||
elif re.fullmatch(r"[+-]?\d[\d_]*(\.\d[\d_]*)?(e[+-]?\d[\d_]*)?", buff):
|
if re.fullmatch(r"([+-]?)\d[\d_]*(\.\d[\d_]*)?(e[+-]?\d[\d_]*)?", buff):
|
||||||
return FloatToken(float(buff), buff, pos)
|
return FloatToken(float(buff), buff, pos)
|
||||||
|
|
||||||
else:
|
# Default behavior
|
||||||
return SymbolToken(buff, buff, pos)
|
return SymbolToken(buff, buff, pos)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def parse_symbol(cls, f: PosTrackingBufferedReader):
|
def parse_symbol(cls, f: PosTrackingBufferedReader):
|
||||||
|
@ -331,6 +354,7 @@ class Parser(SexpParser):
|
||||||
buff = str(rtb)
|
buff = str(rtb)
|
||||||
return CommentToken(buff, buff, pos)
|
return CommentToken(buff, buff, pos)
|
||||||
|
|
||||||
|
|
||||||
## Parsing interface
|
## Parsing interface
|
||||||
def parses(buff: str,
|
def parses(buff: str,
|
||||||
parser: SexpParser = Parser,
|
parser: SexpParser = Parser,
|
||||||
|
|
|
@ -20,10 +20,32 @@ def test_parse_list():
|
||||||
('2', 2),
|
('2', 2),
|
||||||
('103', 103),
|
('103', 103),
|
||||||
('504', 504),
|
('504', 504),
|
||||||
|
# Sign prefixes
|
||||||
('-1', -1),
|
('-1', -1),
|
||||||
('+1', +1),
|
('+1', +1),
|
||||||
|
# Underscores as whitespace
|
||||||
|
('1_000_000', 1e6),
|
||||||
('+1_000', 1000),
|
('+1_000', 1000),
|
||||||
('-1_000', -1000),
|
('-1_000', -1000),
|
||||||
|
# Variable base
|
||||||
|
('2r1', 1),
|
||||||
|
('2r10', 2),
|
||||||
|
('2r100', 4),
|
||||||
|
('2r101', 5),
|
||||||
|
('+2r10', 2),
|
||||||
|
('-2r10', -2),
|
||||||
|
# Octal
|
||||||
|
('00', 0),
|
||||||
|
('01', 1),
|
||||||
|
('010', 8),
|
||||||
|
('+010', 8),
|
||||||
|
('-010', -8),
|
||||||
|
# Hex
|
||||||
|
('0x0', 0),
|
||||||
|
('0xF', 15),
|
||||||
|
('0x10', 16),
|
||||||
|
('+0x10', 16),
|
||||||
|
('-0x10', -16),
|
||||||
])
|
])
|
||||||
def test_parse_num(txt, val):
|
def test_parse_num(txt, val):
|
||||||
"""Some trivial cases of parsing numbers."""
|
"""Some trivial cases of parsing numbers."""
|
||||||
|
|
Loading…
Reference in a new issue