def test_creation(self): builder = UnitRefBuilder() assert not builder.leading_space assert not builder.casegen assert not builder.randgen assert builder.randgen_name is None assert builder.randgen_percent == 50
def test_create_concrete(self): builder = UnitRefBuilder() builder.identifier = "id" with pytest.raises(ValueError): builder.create_concrete() builder.type = UnitType.alias modifiers = builder._build_modifiers_repr() assert isinstance(modifiers, ModifiersRepresentation) assert not modifiers.casegen assert not modifiers.randgen assert modifiers.randgen.name is None assert modifiers.randgen.percentage == 50 assert not modifiers.randgen.opposite unit_ref = builder.create_concrete() assert isinstance(unit_ref, UnitReference) assert not unit_ref._leading_space assert unit_ref._unit_type == UnitType.alias assert unit_ref._name == "id"
def _parse_rule(self, tokens): """ Handles the tokens `tokens` that contain a rule (inside a unit definition). Returns the rule (`Rule`) that `tokens` represent. """ # TODO replace this with a (stateful) iterator to make it more readable rule_contents = [] current_builder = None leading_space = False slot_value = None i = 0 while i < len(tokens): token = tokens[i] if token.type == TerminalType.whitespace: leading_space = True if current_builder is not None: rule_contents.append(current_builder.create_concrete()) current_builder = None # Units and rule contents elif token.type == TerminalType.word: rule_contents.append(Word(token.text, leading_space)) leading_space = False elif ( token.type in \ (TerminalType.alias_ref_start, TerminalType.slot_ref_start, TerminalType.intent_ref_end) ): if current_builder is not None: rule_contents.append(current_builder.create_concrete()) current_builder = UnitRefBuilder() current_builder.leading_space = leading_space if token.type == TerminalType.alias_ref_start: current_builder.type = UnitType.alias elif token.type == TerminalType.slot_ref_start: current_builder.type = UnitType.slot elif token.type == TerminalType.intent_ref_start: current_builder.type = UnitType.intent elif ( token.type in \ (TerminalType.alias_ref_end, TerminalType.slot_ref_end, TerminalType.intent_ref_end) ): rule_contents.append(current_builder.create_concrete()) current_builder = None leading_space = False elif token.type == TerminalType.unit_identifier: current_builder.identifier = token.text elif token.type == TerminalType.choice_start: if current_builder is not None: rule_contents.append(current_builder.create_concrete()) current_builder = ChoiceBuilder() current_builder.leading_space = leading_space last_internal_choice_token = \ find_index_last_choice_content(tokens, i) if last_internal_choice_token is not None: i += 1 if tokens[i].type == TerminalType.casegen_marker: current_builder.casegen = True i += 1 internal_rules = \ self._parse_choice( tokens[i:last_internal_choice_token + 1] ) current_builder.rules = internal_rules i = last_internal_choice_token else: self.input_file_manager.syntax_error( "Inconsistent choice start and ending.") elif token.type == TerminalType.choice_end: rule_contents.append(current_builder.create_concrete()) current_builder = None leading_space = False # Modifiers elif token.type == TerminalType.casegen_marker: current_builder.casegen = True elif token.type == TerminalType.randgen_marker: current_builder.randgen = True elif token.type == TerminalType.opposite_randgen_marker: current_builder.randgen_opposite = True elif token.type == TerminalType.randgen_name: current_builder.randgen_name = token.text elif token.type == TerminalType.percentgen_marker: pass elif token.type == TerminalType.percentgen: current_builder.randgen_percent = \ self._str_to_int( token.text, "Couldn't parse the percentage " + \ "for the random generation modifier." ) elif token.type == TerminalType.variation_marker: pass elif token.type == TerminalType.variation_name: current_builder.variation = token.text elif token.type == TerminalType.arg_marker: pass elif token.type == TerminalType.arg_value: current_builder.arg_value = token.text elif token.type == TerminalType.slot_val_marker: pass elif token.type == TerminalType.slot_val: slot_value = token.text else: raise ValueError( # Should never happen "Detected invalid token type in rule: " + \ token.type.name + " for text '" + token.text + "'." ) i += 1 if current_builder is not None: rule_contents.append(current_builder.create_concrete()) if self._current_unit_declaration is not None: return Rule(self._current_unit_declaration.full_name, rule_contents, slot_value) # NOTE can only come from an interactive command (the 'rule' command) return Rule(None, rule_contents, slot_value)