view anagram/guisupport/ws.cpp @ 15:f5acaf0c8a29

Don't cast through "volatile int". Causes a gcc warning nowadays. XXX: should put something else back here to frighten the optimizer
author David A. Holland
date Tue, 31 May 2022 01:00:55 -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 */