11from tatsu .model import NodeWalker
2- from typing import Iterable , Optional , Tuple
2+ from typing import Iterable , Optional , Tuple , List
33
44from textworld .textgen .model import TextGrammarModelBuilderSemantics
55from 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
4992class MatchAlternative (Alternative ):
@@ -70,6 +113,7 @@ def __init__(self, symbol: str, alternatives: Iterable[Alternative]):
70113
71114
72115class _Converter (NodeWalker ):
116+
73117 def walk_list (self , node ):
74118 return [self .walk (child ) for child in node ]
75119
0 commit comments