Skip to content

Commit 3ecff2a

Browse files
committed
Revised version of grammar (symbol and literal chunks)
1 parent 3a38f9b commit 3ecff2a

File tree

1 file changed

+55
-11
lines changed

1 file changed

+55
-11
lines changed

textworld/textgen/__init__.py

Lines changed: 55 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from tatsu.model import NodeWalker
2-
from typing import Iterable, Optional, Tuple
2+
from typing import Iterable, Optional, Tuple, List
33

44
from textworld.textgen.model import TextGrammarModelBuilderSemantics
55
from textworld.textgen.parser import TextGrammarParser
@@ -18,32 +18,75 @@ def full_form(self, include_adj=True) -> str:
1818
return adj + "|" + noun
1919

2020

21-
class LiteralAlternative(Alternative):
21+
class LiteralChunk:
2222
"""
23-
An alternative from a literal string.
23+
It creates an object with a [str] value for every single literal.
24+
literal is defined as any string which is not a symbol, i.e. it is not bounded by hashtags.
2425
"""
26+
def __init__(self, value: str):
27+
self._value = value
28+
2529

26-
def __init__(self, value: str):
30+
class SymbolChunk:
31+
"""
32+
It creates an object with a [str] value for every single symbol.
33+
symbol is defined as any string in between two consecutive hashtags, e.g. #it_is_a_symbol#.
34+
"""
35+
def __init__(self, value: str):
2736
self._value = value
2837

38+
39+
class LiteralAlternative(Alternative):
40+
"""
41+
An alternative from a literal string and represents it as a chunk of literal and symbol objects.
42+
"""
43+
def __init__(self, node: str):
44+
self._node = node
45+
# self._val_chunk contains the objects which make the string.
46+
# It is equivalent to self._value in LiteralAlternative.
47+
self._val_chunk = self._symbol_finder(self._node)
48+
49+
def _symbol_finder(self, node):
50+
self.chunks = []
51+
while node:
52+
is_has_tag = [i for i, ltr in enumerate(node) if ltr == '#']
53+
if is_has_tag:
54+
if node[:is_has_tag[0]]:
55+
self.chunks.append(LiteralChunk(node[:is_has_tag[0]]))
56+
self.chunks.append(SymbolChunk(node[is_has_tag[0]:is_has_tag[1] + 1]))
57+
else:
58+
self.chunks.append(SymbolChunk(node[is_has_tag[0]:is_has_tag[1] + 1]))
59+
60+
node = node[is_has_tag[1] + 1:]
61+
else:
62+
if node:
63+
self.chunks.append(LiteralChunk(node))
64+
break
65+
return self.chunks
66+
2967
def split_form(self, include_adj=True) -> Tuple[Optional[str], str]:
30-
return None, self._value
68+
return None, self._node
3169

3270

33-
class AdjectiveNounAlternative(Alternative):
71+
class AdjectiveNounAlternative(LiteralAlternative):
3472
"""
3573
An alternative that specifies an adjective and a noun.
3674
"""
3775

38-
def __init__(self, adjective: str, noun: str):
39-
self._adjective = adjective
40-
self._noun = noun
76+
def __init__(self, adj_node: str, n_node: str):
77+
self._adj_node = adj_node
78+
self._n_node = n_node
79+
# self._adj_chunk contains the objects which make the adjective string.
80+
# self._noun_chunk contains the objects which make the noun string.
81+
# These are equivalent to self._adjective and self._noun in AdjectiveNounAlternative.
82+
self._adj_chunk = self._symbol_finder(self._adj_node)
83+
self._noun_chunk = self._symbol_finder(self._n_node)
4184

4285
def split_form(self, include_adj=True) -> Tuple[Optional[str], str]:
4386
if include_adj:
44-
return self._adjective, self._noun
87+
return self._adj_node, self._n_node
4588
else:
46-
return None, self._noun
89+
return None, self._n_node
4790

4891

4992
class MatchAlternative(Alternative):
@@ -70,6 +113,7 @@ def __init__(self, symbol: str, alternatives: Iterable[Alternative]):
70113

71114

72115
class _Converter(NodeWalker):
116+
73117
def walk_list(self, node):
74118
return [self.walk(child) for child in node]
75119

0 commit comments

Comments
 (0)