view anagram/agcore/rpz.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 607e3be6bad8
children
line wrap: on
line source

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

#include "arrays.h"
#include "assert.h"
#include "bpe3.h"
#include "config.h"
#include "csexp.h"
#include "dict.h"
#include "error.h"
#include "keyword.h"
#include "myalloc.h"
#include "pgg24-defs.h"
#include "pgg24.h"
#include "q1glbl.h"
#include "rpk.h"
#include "rpz.h"
#include "rproc.h"
#include "rule.h"
#include "symbol.h"
#include "stacks.h"
#include "token.h"
#include "tree.h"
#include "tsd.h"
#include "ut.h"

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


#define PCB pgcb


void definition_1(CharSetExpression *x) {
  LOGSECTION("definition_1");
  int k;
  Symbol id = Symbol::create();
  LOGV(id);
  if (x->recursive(id)) {
    LOGS("Recursive definition");
    warning_here("Recursive definition of character set %s",
		 id->string.pointer());
    delete x;
    return;
  }
  if (id->parse_tree.isNotNull()) {
    warning_here("Redefinition of %s", id->string.pointer());
    delete x;
    return;
  }
  if ((k = id->token_number) != 0) {
    if (Token(k)->non_terminal_flag) {
      warning_here("Redefinition of token T%03d: %s", k, id->string.pointer());
      delete x;
      return;
    }
  }
  LOGS("Ready to identify parse tree");
  ParseTree tree(x);
  LOGV((int) tree) LCV((int) tree->expression);
  id->parse_tree = tree;
  tree->token_name = id;
}


void definition_3(int cn) {
  LOGSECTION("definition_3");
  definition_1(new IndividualCode(cn));
}

void definition_2(int tn) {
  LOGSECTION("definition_2");
  LOGV(tn);
  int t;
  token_number_map *mtn;
  unsigned name;

  Symbol id = Symbol::create();
  LOGV(id);
  if (id->parse_tree.isNotNull()) {
    warning_here("Redefinition of %s", id->string.pointer());
    return;
  }
  if ((t = id->token_number) != 0) {
    mtn = &map_token_number[t];
    if (mtn->non_terminal_flag || mtn->key) {
      warning_here("Redefinition of token T%03d: %s",t, id->string.pointer());
      return;
    }
    shell_production(t,tn);
    return;
  }
  name = map_token_number[tn].token_name;
  if (name == (unsigned) id) {
    return;
  }
  if (name) {
    LOGS("call shell_production") LV(t) LCV(tn);
    shell_production(t,tn);
    return;
  }
  map_token_number[tn].token_name = id;
  id->token_number = tn;
  LOGV(tn) LCV(id);
}

int form_spec_2(int fn, int pn)   {
  LOGSECTION("form_spec_2");
  LOGV(fn) LCV(pn);
  Procedure reductionProc(pn);
  Rule rule(fn);

  rule->proc_name = pn;
  LOGV(rule) LCV(rule->proc_name);
  reductionProc->form_number = rule;
  return fn;
}

int head_list_2(int flag) {
  LOGSECTION("head_list_2");
  unsigned tn;
  token_name();
  tn = fis();
  LOGV(tn) LCV(ntkns);
  assert(tn <= ntkns);
  if (flag) {
    if (grammar_token) {
      log_error("Redefinition of grammar token");
    }
    grammar_token = tn;
  }
  return tn;
}

int mid_line(int pn) {
  LOGSECTION("mid_line");
  Rule rule = form1();
  Procedure proc(pn);
  LOGV(rule);
  LOGV(ruleElementStack.size());
  int bias = ruleElementStack.top().size();
  LOGV(bias);
  rule->immediate_proc = 1;
  rule->proc_name = pn;
  proc->form_number = rule;
  LOGV(rule) LCV(rule->proc_name);
  rule->hostElementList = AgArray<RuleElement>(ruleElementStack.top());
  rule->op_bias = bias;
  return rule;
}

int proc_spec_4(int flag) {
  LOGSECTION("proc_spec_4");

  CSegment cSegment = cSegmentStack.pop();
  Procedure proc(cSegment);
  LOGV(proc);
  proc->value_flag = flag;
  proc->line = PRULE_CONTEXT(PCB)->y;
  proc->col = PRULE_CONTEXT(PCB)->x;
  return proc;
}

static int proc_spec_6(int, int fn) {
  LOGSECTION("proc_spec_6");

  CSegment segment;
  segment.end = segment.begin;
  Procedure proc(segment);
  proc->value_flag = 1;
  proc->form_number = fn;
  return proc;
}


int semantic_productions = 0;


void production(int type) {
  LOGSECTION("production");
  unsigned *fl, *tl, nf, nt,i,j, zl;

  zl = 0;
  fl = (unsigned *) build_list();
  nf = fis();
  tl = (unsigned *) build_list();
  ok_ptr(tl);
  LOGV((int) tl);
  nt = fis();
  LOGV(nt) LCV(nf);
  if (nt > 1) {
    semantic_productions = 1;
  }
  for (j = 0; j < nf; j++) {
    ok_ptr(tl);
    LOGV(fl[j]);
    Rule rule(fl[j]);
    //int pn = rule->proc_name;
    //const unsigned *rp = rule->tokens();
    int rl = rule->length(), i = rl;

    ok_ptr(tl);
    LOGV(fl[j]);
    iws();
    int tokenIndex = 0;
    //while (i--) aws(*rp++);
    while (i--) {
      aws(rule.token(tokenIndex++));
    }
    i = nt;
    rl++;
    while (i--) {
      aws(tl[i]);
      if (list_in_dict(list_base, rl, prod_dict)) {
        log_error("Duplicate production");
      }
      fws();
    }
    rws();
    //check_size(map_proc_name,pn, pn + pn/2);
    rule->prim_tkn = tl[0];
    rule->fast_loop = nt == 1 &&
                     rule->length() == 2 &&
                     tl[0] == (unsigned) rule.token(0);
                     //tl[0] == lstptr(*mfn,tokens)[0];
    if (rule->length() == 0) zl = 1;
    if (rule-> length() == 1) {
      int i = nt;
      unsigned t = rule.token(0);
      while (i--) {
        if (t != tl[i]) {
	  continue;
	}
        warning_here("Suspicious production for %s",
		     Token(t)->token_name->string.pointer());
      }
    }
    if (nt > 1) {
      rule->not_unique_reduction = 1;
      if (rule->proc_name == 0) {
	rule->proc_name = proc_spec_6(rule->line, fl[j]);
      }
    }
  }
  for (i = 0; i < nt; i++) {
    token_number_map *tp = &map_token_number[tl[i]];
    int vt = tp->value_type;
    ok_ptr(tl);
    LOGV((int) tl);
    LOGV(tl[i]) LCV(vt);
    if (nf) {
      tp->non_terminal_flag = 1;
    }
    tp->zero_length_flag = zl;
    tp->sem_det_flag = nt > 1;
    if (type && vt && vt != type) {
      ssprintf("Type Redefinition of T%03d: ", tl[i]);
      atkn(tl[i]);
      log_error();
    }
    if (type) {
      tp->value_type = type;
    }
    ok_ptr(tl);
    LOGV(type);
    for (j = 0; j < nf; j++) {
      at(bnf_table, tl[i], fl[j]);
    }
  }
  LOGS("Ready to free tl");
  ok_ptr(tl);
  LOGV((int) tl);
  DEALLOCATE(tl);
  LOGS("Ready to free fl");
  if (fl != NULL) {
    DEALLOCATE(fl);
  }
  LOGS("Production analysis complete");
}

CharSetExpression *ss2(void) {
  LOGSECTION("ss2");
  Symbol name = Symbol::create();

  LOGV(name->token_number) LCV(name->string);
  if (name->string == "error") {
    Token token = name->token_number;
    LOGV(token);
    if (error_token || token.isNotNull() || name->parse_tree.isNotNull()) {
      return new NamedCharSet(name);
    }
    token = Token::create();
    token->token_name = name;
    name->token_number = token;
    token->value_type = default_input_type;
    error_token = token;
    LOGV(error_token);
    checkParams();
  }
  return new NamedCharSet(name);
}

void token_name(void) {
  LOGSECTION("token_name");

  unsigned symbolCount = Symbol::count();
  Symbol n = Symbol::create();
  int flag = Symbol::count() > symbolCount;  //true if new symbol

  LOGV(n) LCV(ntkns);
  Token tn = n->token_number;
  LOGV(tn) LCV(ntkns);
  if (tn.isNotNull()) {
    sis(tn);
    return;
  }
  n->token_number = Token::create();
  tn = n->token_number;
  tn->token_name = n;
  tn->value_type = 0;
  if (!flag && n->parse_tree.isNotNull()) {
    n->parse_tree = ParseTree();
    warning_here("Redefinition of %s", n->string.pointer());
  }
  sis(tn);                 /* push token on stack */
  return;
}

//int idsx(string_dict *);

/* -> keyword string                                        =vp_s(); */

int vp_s(void) {
  LOGSECTION("vp_s");
  int n;
  int i;

  n = tis();
  if (n > max_key_length) max_key_length = n;
  tss();
  LOGV(string_base);
  if (!case_sensitive) {
    for (i = n; i--; ) {
      string_base[i] = agToUpper(string_base[i]);
    }
  }
  if (n == 0) {
    log_error("Empty keyword string");
  }
  Keyword keyword(string_base);
  LOGV(keyword->string);
  rcs();
  LOGV((int) keyword->token_number);
  if (keyword->token_number.isNull()) {
    keyword->token_number = Token::create();
    Token token = keyword->token_number;
    LOGV((int) token);
    token->key = keyword;
    token->value_type = void_token_type;
    token->operatorCandidate = 1;
  }
  return keyword->token_number;
/*
  if (!idsx(key_dict)) {
    key = fis();
    assert(key == (int) keyword);
    LOGV(key) LCV(keyword);
    check_size(map_key_word, key, key + key/2);
    LOGV(key) LCV(map_key_word[key].token_number) LCV(ntkns);
    return map_key_word[key].token_number;
  }
  if (n > max_key_length) {
    max_key_length = n;
  }
  key = fis();
  LOGV(key) LCV(keyword);
  assert(key == (int) keyword);
  check_size(map_key_word, key,key + key/2 );
  map_key_word[key].token_number = Token::create();
  map_token_number[ntkns].key = key;
  LOGV(key) LCV(map_key_word[key].token_number) LCV(ntkns);
  return ntkns;
*/
}

/* -> left bracket, proper vp rule specs, right bracket     =vp_3(); */

int vp_3(void) {
  LOGSECTION("vp_3");
  int tn;
  int flag,vptn;

  aws(3);
  flag = idl(vp_prod_dict);
  vptn = fis();
  check_size(map_vp_prod_number,vptn,vptn + vptn/2);
  if (flag == 0) {
    tn = map_vp_prod_number[vptn].token_number;
    LOGV(tn) LCV(ntkns);
    return tn;
  }
  sws(form1());
  fdl(vp_prod_dict,vptn);
  fws();
  vp_forms();
  concat_list();
  map_vp_prod_number[vptn].token_number = Token::create();
  gen_vp_prods(ntkns,1,vptn);
  LOGV(ntkns);
  return ntkns;
}

/*
 -> keyword string, '?', blank?...             =vp_5(vp_s());
 -> union:n, '?', blank?...                    =vp_5(form_element_1(n));
*/

int vp_5(int tn) {
  LOGSECTION("vp_5");
  int flag, vptn;

  sws(tn); aws(5);
  flag = idl(vp_prod_dict);
  vptn = fis();
  check_size(map_vp_prod_number,vptn,vptn + vptn/2);
  if (flag == 0) {
    tn = map_vp_prod_number[vptn].token_number;
    return tn;
  }
  map_vp_prod_number[vptn].token_number = Token::create();
  sws(form1());
  aws(makeRule(tn));
  gen_vp_prods(ntkns,0,vptn);
  return ntkns;
}

int vp_8a(int fn) {
  LOGSECTION("vp_8a");
  token_number_map *tp;

  Token::create();
  tp = &map_token_number[ntkns];
  tp->non_terminal_flag = 1;
  map_form_number[fn].prim_tkn = ntkns;
  tp->zero_length_flag = 1;
  tp->fine_structure = 1;
  tp->immediate_action = 1;
  at(bnf_table, ntkns, fn);
  LOGV(ntkns) LCV(tp->immediate_action);
  return ntkns;
}

//static void build_choice(int tn)   {
static void build_choice(Token token)   {
  LOGSECTION("build_choice");
  int *fl, nf, j;
  int i, zl;
  //token_number_map *tp;


  zl = 0;
  vp_forms();
  fl = list_base;
  nf = rws();
  //tp = &map_token_number[tn];
  //if (nf) tp->non_terminal_flag = 1;
  if (nf) {
    token->non_terminal_flag = 1;
  }
  for (i = 0; i < nf; i++) {
    Rule rule(fl[i]);
    //rule->prim_tkn = tn;
    rule->prim_tkn = token;
    if (rule->length() == 0) {
      zl = 1;
    }
  }
  //tp->zero_length_flag = zl;
  token->zero_length_flag = zl;
  for (j = 0; j < nf; j++) {
    //at(bnf_table,tn,fl[j]);
    at(bnf_table,(int) token,fl[j]);
  }
}

//static void alter_prod(int tb, int nt, int tn, int vf) {
static void alter_prod(Token tb, int nt, Token token, VpRule vpRule) {
  LOGSECTION("alter_prod");

  LOGV(vpRule) LCV(token) LCV(tb) LCV(nt) LCV(Token::count());

  int i,j;
  iws();
  for (i = tb, j = nt; j--; i++) {
    //if (i == tn) {
    if (i == (int) token) {
      //aws(vf);
      aws(vpRule);
      continue;
    }
    AgStack<RuleElement> elementStack;
    elementStack.push(RuleElement(i,0));
    //VpRule vpRule(vf);
    for (unsigned k = 0; k < vpRule->elementList.size(); k++) {
      elementStack.push(vpRule->elementList[k]);
    }
    VpRule newRule(elementStack, vpRule->procedureName);
    aws(newRule);
  }
  build_choice(token);
}

static void alternate(void) {
  LOGSECTION("alternate");
  //int tb = ntkns+1;
  Token tb = Token::create();
  int *vfl = build_list();
  int nt = fis();
  //int tn  = tb, k;
  Token tn;
  int k;

  for (k = 1; k < nt; k++) tn = Token::create();
  iws();
  for (k = 0; k < nt; k++)  {
    tn = tb + k;
    alter_prod(tb,nt,tn,vfl[k]);
    ruleElementStack.push(AgStack<RuleElement>()).top()
      .push(RuleElement(tn,0));
    aws(vp_form3(0));
  }
  DEALLOCATE(vfl);
}

int vp_9(void){
  LOGSECTION("vp_9");
  alternate();
  return vp_1();
}

int vp_10(void){
  LOGSECTION("vp_10");
  alternate();
  return vp_3();
}