Skip to content

Commit c71f5e5

Browse files
committed
Implement token-pasting zxbbpp operator
Tests included
1 parent a016d47 commit c71f5e5

11 files changed

Lines changed: 85 additions & 12 deletions

File tree

src/libzxbpp/prepro/macrocall.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
import re
66
import copy
77

8+
from typing import Union
9+
810
from .exceptions import PreprocError
911
from src.api.debug import __DEBUG__
1012

@@ -22,12 +24,12 @@ class MacroCall:
2224
"""
2325
__slots__ = 'table', 'id_', 'callargs', 'lineno'
2426

25-
def __init__(self, lineno: int, table: 'prepro.DefinesTable', id_: str, args=None):
27+
def __init__(self, lineno: int, table: 'prepro.DefinesTable', id_: Union['MacroCall', str], args=None):
2628
""" Initializes the object with the ID table, the ID name and
2729
optionally, the passed args.
2830
"""
2931
self.table: 'prepro.DefinesTable' = table
30-
self.id_: str = id_
32+
self.id_ = id_
3133
self.callargs = args
3234
self.lineno: int = lineno
3335

@@ -108,4 +110,5 @@ def is_defined(self, symbolTable: 'prepro.DefinesTable' = None) -> bool:
108110
if symbolTable is None:
109111
symbolTable = self.table
110112

113+
assert isinstance(self.id_, str)
111114
return symbolTable.defined(self.id_)

src/libzxbpp/prepro/operators.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# -*- coding: utf-8 -*-
2+
# Operators implemented in the preprocessor
3+
4+
5+
from src.libzxbpp import prepro
6+
from src.libzxbpp.prepro.macrocall import MacroCall
7+
8+
9+
class Concatenation(MacroCall):
10+
""" Implements the concatenation (a.k.a. token-paste) (##) operator.
11+
When in a macro body, ID1 ## ID2 becomes
12+
<expanded(ID1)><expanded(ID2)> (concatenated without spaces).
13+
Out of a macro body, ID1 and ID2 are expanded normally and "##" is
14+
also output as is.
15+
"""
16+
def __init__(self, lineno: int, table: 'prepro.DefinesTable', left: MacroCall, right: MacroCall):
17+
super().__init__(lineno=lineno, table=table, id_='')
18+
self.left = left
19+
self.right = right
20+
21+
def __call__(self, symbolTable: 'prepro.DefinesTable' = None) -> str:
22+
return self.left(symbolTable).rstrip() + self.right(symbolTable).lstrip()

src/libzxbpp/zxbpp.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
from .prepro.output import error
3131
from .prepro import DefinesTable, ID, MacroCall, Arg, ArgList
3232
from .prepro.exceptions import PreprocError
33+
from .prepro.operators import Concatenation
3334

3435
from src import arch
3536

@@ -63,6 +64,7 @@ class IfDef(NamedTuple):
6364
('nonassoc', 'DUMMY'),
6465
('left', 'EQ', 'NE', 'LT', 'LE', 'GT', 'GE'),
6566
('right', 'LLP'),
67+
('left', 'PASTE'),
6668
)
6769

6870

@@ -684,6 +686,12 @@ def p_macrocall_args(p):
684686
p[0] = MacroCall(p[2].end_lineno, ID_TABLE, p[1], p[2])
685687

686688

689+
def p_macrocall_paste(p):
690+
""" macrocall : macrocall PASTE macrocall
691+
"""
692+
p[0] = Concatenation(p[1].lineno, ID_TABLE, p[1], p[3])
693+
694+
687695
def p_args(p):
688696
""" args : LLP arglist RRP
689697
"""

src/libzxbpp/zxbpplex.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,8 @@
4242

4343
_tokens = ('STRING', 'TOKEN', 'NEWLINE', '_ENDFILE_', 'FILENAME', 'ID',
4444
'INTEGER', 'EQ', 'PUSH', 'POP', 'LP', 'LLP', 'RRP', 'RP', 'COMMA',
45-
'CONTINUE', 'NUMBER', 'SEPARATOR', 'GT', 'GE', 'LT', 'LE', 'NE'
46-
)
45+
'CONTINUE', 'NUMBER', 'SEPARATOR', 'GT', 'GE', 'LT', 'LE', 'NE',
46+
'PASTE')
4747

4848
reserved_directives = {
4949
'include': 'INCLUDE',
@@ -340,6 +340,10 @@ def t_INITIAL_defexpr_TOKEN(self, t):
340340
r'=>|<=|>=|<>|[$!&|~@:;{}.<>^=+*/%-]'
341341
return t
342342

343+
def t_defexpr_PASTE(self, t):
344+
r'[ \t]*\#\#[ \t]*'
345+
return t
346+
343347
def t_INITIAL_defexpr_asm_SEPARATOR(self, t):
344348
r'[ \t]+'
345349
return t

src/parsetab/tabs.dbm.bak

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
'asmparse', (0, 254311)
2-
'zxnext_asmparse', (254464, 285299)
3-
'zxbparser', (540160, 712099)
4-
'zxbpp', (1252352, 69831)
1+
'zxbpp', (0, 70950)
2+
'asmparse', (71168, 254311)
3+
'zxnext_asmparse', (325632, 285299)
4+
'zxbparser', (611328, 712099)

src/parsetab/tabs.dbm.dat

1.21 KB
Binary file not shown.

src/parsetab/tabs.dbm.dir

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
'asmparse', (0, 254311)
2-
'zxnext_asmparse', (254464, 285299)
3-
'zxbparser', (540160, 712099)
4-
'zxbpp', (1252352, 69831)
1+
'zxbpp', (0, 70950)
2+
'asmparse', (71168, 254311)
3+
'zxnext_asmparse', (325632, 285299)
4+
'zxbparser', (611328, 712099)

tests/functional/token-paste0.bi

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
2+
3+
#define x(a, b) a ## b
4+
5+
x( A , B )
6+
7+
REM Should not be concatenated out of define body
8+
A ## B
9+

tests/functional/token-paste0.out

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#line 1 "token-paste0.bi"
2+
3+
4+
5+
6+
AB
7+
8+
9+
A ## B
10+

tests/functional/token-paste1.bi

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
2+
3+
#define aa(x) (AA x)
4+
5+
#define x(a, b, c) a##b(c)
6+
7+
x(a, a, 1)
8+

0 commit comments

Comments
 (0)