def _parse_phases(self, v_str): if v_str == 'all': self.val[kw.PHASES] = v_str # list(all_phase_labels) else: phase_labels = ParseUtil.comma_split_strip(v_str) for phase_label in phase_labels: if len(phase_label) == 0: return "Expected comma-separated list of phase labels, found {}".format( phase_labels) # else: # if phase_label not in all_phase_labels: # return "Undefined phase label '{}'.".format(phase_label) self.val[kw.PHASES] = phase_labels return None
def __init__(self, phase_obj, lineno, label, after_label, all_linelabels, parameters, global_variables): self.lineno = lineno self.label = label self.parameters = parameters self.all_linelabels = all_linelabels self.is_help_line = False self.stimulus = None # A dict with an intensity for each element in stimulus_elememts self.action = None self.action, logic = ParseUtil.split1_strip(after_label, sep=PHASEDIV) if logic is None: raise ParseException(lineno, f"Missing separator '{PHASEDIV}' on phase line.") action_list = ParseUtil.comma_split_strip(self.action) first_element, _, _ = ParseUtil.parse_element_and_intensity(action_list[0], variables=None, safe_intensity_eval=True) self.is_help_line = (len(action_list) == 1) and (first_element not in parameters.get(STIMULUS_ELEMENTS)) if self.is_help_line: self.stimulus = None if action_list[0] != '': check_action(action_list[0], parameters, global_variables, lineno, all_linelabels) else: self.stimulus, err = ParseUtil.parse_elements_and_intensities(self.action, global_variables, safe_intensity_eval=True) if err: raise ParseException(lineno, err) for element in self.stimulus: if element not in parameters.get(STIMULUS_ELEMENTS): raise ParseException(lineno, f"Expected a stimulus element, got '{element}'.") self.action = None if len(logic) == 0: raise ParseException(lineno, f"Line with label '{label}' has no conditions.") self.conditions = PhaseLineConditions(phase_obj, lineno, self.is_help_line, logic, parameters, all_linelabels, global_variables)
def _parse(self, lineno, is_help_line, condition_and_actions, logicpart_index, n_logicparts, parameters, all_linelabels, global_variables): ''' Args: condition_and_actions (str): Examples are "b=5: x:2, y=2, ROWLBL", "x:2, y:2, ROWLBL", "@break" "x=1: @break" "x:1" "@break, x:1" ''' self.condition = None ca_list = ParseUtil.comma_split_strip(condition_and_actions) found_condition = False any_rowlbl_prob = False found_rowlbl = False goto_list = list() goto_list_index = list() for i, ca in enumerate(ca_list): err = f"Invalid statement '{ca}'." n_colons = ca.count(':') if n_colons == 0: contains_condition = False action = ca elif n_colons == 1: before_colon, after_colon = ParseUtil.split1_strip(ca, ':') contains_condition = self._is_condition(before_colon, parameters) if contains_condition: if self.condition is not None: # Cannot have multiple conditions raise ParseException(lineno, f"Multiple conditions ('{self.condition}' and '{before_colon}') found in '{condition_and_actions}'.") self.condition = before_colon action = after_colon else: action = ca elif n_colons == 2: colon_inds = [m.start() for m in re.finditer(':', ca)] if colon_inds[1] - colon_inds[0] == 1: raise ParseException(lineno, err) before_first_colon, after_first_colon = ParseUtil.split1_strip(ca, ':') if not self._is_condition(before_first_colon, parameters): raise ParseException(lineno, err) if self.condition is not None: # Cannot have multiple conditions raise ParseException(lineno, f"Multiple conditions ('{self.condition}' and '{before_first_colon}') found in '{condition_and_actions}'.") contains_condition = True self.condition = before_first_colon action = after_first_colon else: raise ParseException(lineno, err) if contains_condition and found_rowlbl: raise ParseException(lineno, f"Found condition '{self.condition}' after row label '{','.join(goto_list)}'.") found_condition = found_condition or contains_condition is_rowlbl, is_rowlbl_prob = self._is_rowlbl(action, all_linelabels) any_rowlbl_prob = (any_rowlbl_prob or is_rowlbl_prob) if is_rowlbl: found_rowlbl = True goto_list.append(action) goto_list_index.append(i) else: check_action(action, parameters, global_variables, lineno, all_linelabels) if found_rowlbl: err = f"Row label(s) must be the last action(s). Found '{action}' after row-label." raise ParseException(lineno, err) if found_condition: # self.condition is not None: self.conditional_actions.append(action) else: self.unconditional_actions.append(action) is_last_action = (i == len(ca_list) - 1) if is_last_action and not is_rowlbl: raise ParseException(lineno, f"Last action must be a row label, found '{action}'.") if found_condition: self.condition_is_behavior = (self.condition in parameters.get(BEHAVIORS)) cond_depends_on_behavior, err = ParseUtil.depends_on(self.condition, parameters.get(BEHAVIORS)) if err is not None: raise ParseException(lineno, err) if cond_depends_on_behavior and is_help_line: raise ParseException(lineno, "Condition on help line cannot depend on response.") goto_str = ','.join(goto_list) # A deterministic ROWLBL cannot have elif/else continuation if (not found_condition) and found_rowlbl and not any_rowlbl_prob: if logicpart_index < n_logicparts - 1: err = f"The unconditional goto row label '{goto_str}' cannot be continued." raise ParseException(lineno, err) if len(goto_list) > 0: self._parse_goto(goto_str, lineno, all_linelabels, global_variables)