view anagram/guisupport/ws.cpp @ 21:1c9dac05d040

Add lint-style FALLTHROUGH annotations to fallthrough cases. (in the parse engine and thus the output code) Document this, because the old output causes warnings with gcc10.
author David A. Holland
date Mon, 13 Jun 2022 00:04:38 -0400
parents 13d2b8934445
children
line wrap: on
line source

/*
 * AnaGram, A System for Syntax Directed Programming
 * Copyright 1993-1999 Parsifal Software. All Rights Reserved.
 * See the file COPYING for license and usage terms.
 *
 * ws.cpp - Miscellaneous Windows
 */

#include "agstack.h"
#include "arrays.h"
#include "charsdc.h"
#include "data.h"
#include "dict.h"
#include "dc.h"
#include "items.h"
#include "q1glbl.h"
#include "q1a.h"
#include "rule.h"
#include "stexpdc.h"
#include "stacks.h"
#include "token.h"
#include "tracedc.h"
#include "ut.h"
#include "wm1.h"
#include "ws.h"

//#define INCLUDE_LOGGING
#include "log.h"


#define PUREMARK '%'


int productions_window_ok(int tn) {
  Token token = tn;
  return token.isNotNull() && token->non_terminal_flag;
}

dc_ref productions_window(int tn) {
  Token token = tn;
  dc_ref new_window;

  if (token.isNull() || !token->non_terminal_flag) {
    return dc_ref();
  }
  AgString foot = AgString::format("T%03d: ", tn).concat(token_string(token));
  return dc_ref(new productions_window_dc(token, foot));
}

void productions_window_dc::getLine(unsigned ln) const {
  Token token = token_number;
  Rule rule = token.rule(ln);
  ics();
  append_item(rule, -1);
}

void productions_window_dc::synchCursor(unsigned ln) const {
  Token token = token_number;
  Rule rule = token.rule(ln);
  if (rule.isNotNull()) {
    set_rule_line(rule);
  }
}

productions_window_dc::productions_window_dc(unsigned tn, const AgString foot)
: dc("Productions", foot)
{
  Token token = token_number = tn;
  des->d_size.y = token->ruleList.size();
}


int token_usage_window_ok(unsigned tn) {
  dc_ref new_window;

  if (tn == 0) {
    return 0;
  }
  Token token = tn;

  //for (fn = 0; ++fn <= nforms; ) {
  for (Each<Rule> rule; rule.loopNotFinished(); rule.getNext()) {
    //Rule rule(fn);
    int length = rule->length();
    int fx;

    if (length == 0) {
      continue;
    }
    for (fx = 0; fx < length;) {
      if (rule.token(fx++) != token) {
	continue;
      }
      return 1;
    }
  }
  return 0;
}

dc_ref token_usage_window(unsigned tn) {
  dc_ref new_window;

  if (tn == 0) {
    return NULL;
  }

  Token token = tn;
  AgString foot = AgString::format("T%03d: ", tn).concat(token_string(tn));
  AgStack<int> stack;
  for (Each<Rule> rule; rule.loopNotFinished(); rule.getNext()) {
    int length = rule->length();
    int fx;

    if (length == 0) {
      continue;
    }
    for (fx = 0; fx < length;) {
      if (rule.token(fx++) != token) {
	continue;
      }
      stack.push(rule).push(fx);
    }
  }
  AgArray<int> list = stack;
  if (list.size()) {
    return new usage_dc(list, foot);
  }
  return NULL;
}

dc_ref rule_list_dc::expansion_rules(unsigned ln) {
  ln *= 2;
  Rule rn = rule_list[ln];
  int rx = rule_list[ln+1];

  if (rx >= rn->length()) {
    return NULL;
  }
  return expand_specific_item(this, rn, rx);
}

int rule_list_dc::expansion_rules_ok(unsigned ln) {
  LOGSECTION("rule_list_dc::expansion_rules_ok");
  LOGV(ln);
  return build_item_list_ok(token(ln));
}

void rule_list_dc::getLine(unsigned ln) const {
  ln *= 2;
  ics();
  append_item(rule_list[ln], rule_list[ln+1]);
}

int rule_list_dc::productions_ok(unsigned ln) {
  return productions_window_ok(token(ln));
}

dc_ref rule_list_dc::productions(unsigned ln) {
  return productions_window(token(ln));
}

dc_ref rule_list_dc::rule_context(unsigned ln) {
  ln *= 2;
  return rule_context_window(rule_list[ln]);
}

rule_list_dc::rule_list_dc(const AgArray<int> list,
			   const AgString head, const AgString foot)
  : dc(head, foot), rule_list(list)
{
  des->d_size.y = list.size()/2;
}

int rule_list_dc::set_elements_ok(unsigned ln) {
  return token_set_window_ok(token(ln));
}

dc_ref rule_list_dc::set_elements(unsigned ln) {
  return token_set_window(token(ln));
}

void rule_list_dc::synchCursor(unsigned ln) const {
  LOGSECTION("rule_list_dc::synchCursor");
  unsigned rn = rule_list[2*ln];
  LOGV(ln) LCV(rn);
  set_rule_line(rn);
}

unsigned rule_list_dc::token(unsigned ln) {
  LOGSECTION("rule_list_dc::token");
  LOGV(ln);
  ln *= 2;
  Rule rule = rule_list[ln];
  unsigned rx = rule_list[ln+1];
  unsigned length = rule->length();
  LOGV(rule);
  LOGV(rx);
  LOGV(length);
  if (rx >= length) {
    return 0;
  }
  return rule.token(rx);
}

int rule_list_dc::usage_ok(unsigned ln) {
  return token_usage_window_ok(token(ln));
}

dc_ref rule_list_dc::usage(unsigned ln) {
  return token_usage_window(token(ln));
}

dc_ref rule_context_window(int f) {
  dc_ref new_window;
  int *rl, nr;

  if (f == 0) {
    return NULL;
  }

  AgString foot = AgString::format("R%03d", f);
  AgStack<int> stack;
  rl = ibnfs + ibnfb[f];
  nr = ibnfn[f];
  while (nr--) {
    Token token = *rl++;
    //for (fn = 0; ++fn <= nforms;) {
    for (Each<Rule> rule; rule.loopNotFinished(); rule.getNext()) {
      int length = rule->length();
      int fx;

      if (length == 0) {
	continue;
      }
      for (fx = 0; fx < length;) {
        if (rule.token(fx++) != token) {
	  continue;
	}
        stack.push(rule).push(fx);
      }
    }
  }

  AgArray<int> list = stack;
  if (list.size()) {
    return new rule_context_dc(list, foot);
  }
  return dc_ref();
}

tsd *build_states_table(unsigned *list, int n) {
  tsd *table = init_tsd(3);

  while (n--) {
    int ps = *list++;
    int *is = dict_str(isht_dict, ps);
    int nis = (*is++ - 1)/2;
    while (nis--) {
      int fn = *is++, fx = *is++;
      at(table, ps, fn, fx);
    }
  }
  return table;
}

int previous_states_window_ok(int sn) {
  return sn != 0;
}

dc_ref previous_states_window(int sn) {
  unsigned *list = lstptr(map_state_number[sn], previous_states);
  int n = map_state_number[sn].n_previous_states;
  dc_ref window;
  tsd *table;
  if (sn == 0) {
    return dc_ref();
  }
  AgString foot = AgString::format("S%03d", sn);
  table = build_states_table(list, n);
  return dc_ref(new state_list_dc("Previous States", table, foot));
}

static int state_list_tabs[] = {7,0};
void state_list_dc::getLine(unsigned ln) const {
  int sn, fn, fx, psn = -1;

  if (ln) {
    xtx(state_list, ln-1, &psn, &fn, &fx);
  }
  xtx(state_list, ln, &sn, &fn, &fx);
  if (sn != psn) {
    ssprintf("S%03d:\t", sn);
  }
  else {
    scs('\t');
  }
  append_item(fn, fx);
}



int state_list_dc::expansion_rules_ok(unsigned ln){
  int sn, fn, fx;

  LOGSECTION("expansion_rules_ok");
  xtx(state_list, ln, &sn, &fn, &fx);
  LOGV(ln);
  LOGV(sn);
  LOGV(fn);
  LOGV(fx);

  Rule rule = fn;
  if (fx >= rule->length()) {
    return 0;
  }
  Token tn = rule.token(fx);
  LOGV(tn);
  return tn->non_terminal_flag;
}

dc_ref state_list_dc::expansion_rules(unsigned ln){
  int sn, fn, fx;

  xtx(state_list, ln, &sn, &fn, &fx);
  if (fx >= Rule(fn)->length()) {
    return NULL;
  }
  return expand_specific_item(this, fn, fx);
}

void state_list_dc::synchCursor(unsigned ln) const {
  unsigned rn = rule(ln);
  if (rn) {
    set_rule_line(rn);
  }
}

int state_list_dc::reduction_states_ok(unsigned ln) {
  int sn, fn, fx;

  xtx(state_list, ln, &sn, &fn, &fx);
  return reduction_states_window_ok(fn, fx);
}

dc_ref state_list_dc::reduction_states(unsigned ln) {
  int sn, fn, fx;

  xtx(state_list, ln, &sn, &fn, &fx);
  return reduction_states_window(sn, fn, fx);
}

unsigned state_list_dc::rule(unsigned ln) const {
  int sn, fn, fx;

  xtx(state_list, ln, &sn, &fn, &fx);
  return fn;
}

dc_ref state_list_dc::rule_context(unsigned ln){
  return rule_context_window(rule(ln));
}

int state_list_dc::set_elements_ok(unsigned ln) {
  return token_set_window_ok(token(ln));
}

dc_ref state_list_dc::set_elements(unsigned ln) {
  return token_set_window(token(ln));
}

unsigned state_list_dc::state(unsigned ln) const {
  int sn, fn, fx;

  xtx(state_list, ln, &sn, &fn, &fx);
  return sn;
}

dc_ref state_list_dc::state_expansion(unsigned ln) {
  return state_expansion_window(state(ln));
}

state_list_dc::state_list_dc(const AgString head, tsd* states, const AgString foot)
  : dc(head, foot), state_list(states)
{
  tab_stops = state_list_tabs;
  columnHeadTitle = "State\tCharacteristic Rules";
  des->d_size.y = state_list->nt;
}

unsigned state_list_dc::token(unsigned ln) const {
  int sn, fn, fx;
  int length;

  xtx(state_list, ln, &sn, &fn, &fx);
  Rule rule = fn;
  length = rule->length();
  if (fx >= length) {
    return 0;
  }
  return rule.token(fx);
}

int state_list_dc::usage_ok(unsigned ln) {
  return token_usage_window_ok(token(ln));
}

dc_ref state_list_dc::usage(unsigned ln) {
  return token_usage_window(token(ln));
}


dc_ref conflict_state_window(unsigned sn) {
  dc_ref window;
  tsd *table;

  AgString foot = AgString::format("S%03d", sn);
  table = build_states_table(&sn, 1);
  return dc_ref(new state_list_dc("State Definition", table, foot));
}

int keywords_window_ok(int sn) {
  int kl = map_state_number[sn].key_list;
  return kl != 0;
}

dc_ref keywords_window(int sn) {
  int kl = map_state_number[sn].key_list;
  unsigned *list;
  dc_ref window;

  if (kl == 0) return dc_ref();
  list = (unsigned *) dict_str(key_list_dict,kl);

  AgString foot = AgString::format("S%03d", sn);
  return dc_ref(new keywords_dc(list + 1, *list -1, foot));
}

static int keywords_tabs[] = {7,0};

void keywords_dc::getLine(unsigned ln) const {
  Token tn = keyword_list[ln];
  int key = tn->key;

  ssprintf("T%03d:\t", (int) tn);
  append_key(key);
  if (tn->pure) {
    acs(PUREMARK);
  }
}

keywords_dc::keywords_dc(unsigned *kwl, unsigned nkw, const AgString foot)
  : dc("Keywords", foot)
{
  keyword_list = kwl;
  des->d_size.y = nkw;

  tab_stops = keywords_tabs;
  columnHeadTitle = "Token\tKeyword";
}

int keywords_dc::usage_ok(unsigned ln) {
  return token_usage_window_ok(keyword_list[ln]);
}

dc_ref keywords_dc::usage(unsigned ln) {
  return token_usage_window(keyword_list[ln]);
}

int reduction_states_window_ok(int fn, int fx) {
  LOGSECTION("reduction_states_window_ok");
  LOGV(fn) LCV(fx);
  return fn && fx == Rule(fn)->length();
}

dc_ref reduction_states_window(int sn, int fn, int fx) {
  int cfn;
  unsigned *list;
  dc_ref new_window;
  tsd *table;

  if (fx < Rule(fn)->length()) {
    return NULL;
  }
  cfn = get_reduction_states(sn, fn, fx);
  if (map_completed_form[cfn].n_reduction_states == 0) {
    return dc_ref();
  }

  AgString foot = AgString::format("S%03d:R%03d", sn, fn);
  list = lstptr(map_completed_form[cfn], reduction_states);
  table = build_states_table(list, map_completed_form[cfn].n_reduction_states);
  new_window = new state_list_dc("Reduction States", table, foot);
  return new_window;
}

static tsd *make_trace(void) {
  int s1, s2;
  int k;
  tsd *aux = init_tsd(2);

  s1 = fws();
  k = tis();
  while (k--) {
    s2 = fws();
    at(aux, s1, map_state_number[s2].char_token);
    s1 = s2;
  }
  at(aux, s1, 0);
  rws();
  return aux;
}

tsd *make_stored_trace(int *trace, int depth, int tn) {
  int s1, s2;
  int k;
  tsd *aux = init_tsd(2);

  k = depth - 1;
  s1 = trace[k];
  while (k--) {
    s2 = trace[k];
    at(aux, s1, map_state_number[s2].char_token);
    s1 = s2;
  }
  at(aux, s1, tn);
  return aux;
}

dc_ref aux_trace_window(unsigned sn) {
  tsd *aux;
  dc_ref window;

  sws(sn);
  while (sn) {
    state_number_map *sp = &map_state_number[sn];
    unsigned *list = lstptr(*sp, previous_states);
    int n = sp->n_previous_states;
    while (n--) {
      if (xws(sn = *list++) == 0) {
	break;
      }
    }
  }
  aux = make_trace();
  window = dc_ref(new trace_window_dc("Auxiliary Trace", aux));
  delete_tsd(aux);
  return window;
}


/*
int token_set_window_ok(int tn) {
	int cs;
	int pt;
	int name;

  if (tn == 0) return 0;
	cs = map_token_number[tn].token_set_id;
  if (cs) return 1;
	pt = map_token_number[tn].parse_tree;
	if (pt) {
		cs = map_parse_tree[pt].char_set;
    if (cs) return 1;
	}
	name = map_token_number[tn].token_name;
	if (name) {
		pt = map_token_name[name].parse_tree;
		if (pt)  {
			cs = map_parse_tree[pt].char_set;
      if (cs) return 1;
		}
	}
  return map_token_number[tn].part_number != 0;
}
*/

int token_set_window_ok(int tn) {
  Token token = tn;
  if (token.isNull()) {
    return 0;
  }
  int cs = token->token_set_id;
  if (cs) {
    return 1;
  }
  ParseTree tree = token->parse_tree;
  if (tree.isNotNull()) {
    cs = tree->char_set;
    if (cs) {
      return 1;
    }
  }
  Symbol name = token->token_name;
  if (name.isNotNull()) {
    tree = name->parse_tree;
    if (tree.isNotNull())  {
      cs = tree->char_set;
      if (cs) {
	return 1;
      }
    }
  }
  return token->part_number != 0;
}

/*
dc_ref token_set_window(int tn) {
  int cs;
  int pt;
  int name;
  int pn;

  if (tn == 0) {
    return NULL;
  }
  cs = map_token_number[tn].token_set_id;
  if (cs) {
    return char_set_window(cs);
  }
  pt = map_token_number[tn].parse_tree;
  if (pt) {
    cs = map_parse_tree[pt].char_set;
    if (cs) {
      return char_set_window(cs);
    }
  }
  name = map_token_number[tn].token_name;
  if (name) {
    pt = map_token_name[name].parse_tree;
    if (pt)  {
      cs = map_parse_tree[pt].char_set;
      if (cs) {
	return char_set_window(cs);
      }
    }
  }
  pn = map_token_number[tn].part_number;
  if (pn == 0) {
    return NULL;
  }
  return part_set_window(pn);
}
*/

dc_ref token_set_window(int tn) {
  Token token = tn;
  if (token.isNull()) {
    return NULL;
  }
  int cs = token->token_set_id;
  if (cs) {
    return char_set_window(cs);
  }
  ParseTree tree = token->parse_tree;
  if (tree.isNotNull()) {
    cs = tree->char_set;
    if (cs) {
      return char_set_window(cs);
    }
  }
  Symbol name = token->token_name;
  if (name.isNotNull()) {
    tree = name->parse_tree;
    if (tree.isNotNull()) {
      cs = tree->char_set;
      if (cs) {
	return char_set_window(cs);
      }
    }
  }
  int pn = token->part_number;
  if (pn == 0) {
    return NULL;
  }
  return part_set_window(pn);
}


int char_set_window_ok(int cs) {
  return cs != 0;
}

dc_ref char_set_window(int cs) {
  unsigned *list = (unsigned *) dict_str(char_set_dict,cs);
  dc_ref window;

  if (cs == 0) {
    return dc_ref();
  }
  AgString foot = AgString::format("C%03d", cs);

  return dc_ref(new set_elements_dc(list + 1, *list - 1, foot.pointer()));
}

/* End WS.C */