Mercurial > ~dholland > hg > ag > index.cgi
diff anagram/agcore/bpe3.cpp @ 0:13d2b8934445
Import AnaGram (near-)release tree into Mercurial.
author | David A. Holland |
---|---|
date | Sat, 22 Dec 2007 17:52:45 -0500 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/anagram/agcore/bpe3.cpp Sat Dec 22 17:52:45 2007 -0500 @@ -0,0 +1,3115 @@ +/* + * AnaGram, A System for Syntax Directed Programming + * Copyright 1993-2002 Parsifal Software. All Rights Reserved. + * See the file COPYING for license and usage terms. + * + * bpe3.cpp - build parse engine, rev. 3 + */ + +#include <ctype.h> +#include <stdarg.h> +#include <time.h> +#include "port.h" + +#include "agarray.h" +#include "agbaltree.h" +#include "agcstack.h" +#include "agdict.h" +#include "agstring.h" +#include "arrays.h" +#include "assert.h" +#include "build.h" +#include "bpe3.h" +#include "bpu.h" +#include "binsort.h" +#include "cd.h" +#include "config.h" +#include "csexp.h" +#include "dict.h" +#include "error.h" +#include "file.h" +#include "keyword.h" +#include "minmax.h" +#include "myalloc.h" +#include "operations.h" +#include "p.h" +#include "q1a.h" +#include "q1glbl.h" +#include "q5.h" +#include "rproc.h" +#include "rpz.h" +#include "rule.h" +#include "symbol.h" +#include "stacks.h" +#include "token.h" +#include "tsd.h" +#include "ut.h" +#include "version.h" + +//#define INCLUDE_LOGGING +#include "log.h" + + +AgStack<CSegment> extensionStack; +AgStack<CSegment> cSegmentStack; +int nPrologueSegments; + + +static const char *copyrightMessage = "copyright"; + +static const char *control_block_type = "$_pcb_type"; +static const char *structNameTemplate = "%_pcb_struct"; +static const char *input_type_name = "$_it_type"; /* dp(input_type_name); */ +static const char *typedef_name = "$_token_type"; +static const char *value_stack_type = "$_vs_type"; + + + +static unsigned *rproc, nrproc; +static void define_my_macros(const char *); +static int really_old_style; + +static int actual_stack_size = 0; +static time_t infile_time_stamp; +string_dict *my_macros = NULL; +static AgString pe_file_name; +int pe_line_count; + +static const char *LOCUS = ""; +static const char *VOIDB = "void "; +static const char *constWord = "const "; +static Cast grammar_type; +static int input_token_type = 0; +static AgString ln_file_name; +static AgString ln_pe_name; +static unsigned max_engine_index = 0; +static unsigned max_pn = 0; +static const char *missing_diagnostic = "Missing %s"; +static const char *nearWord = "near "; +static const int parserLineLength = 76; +static AgString sfn; +static const char *unexpected_diagnostic = "Unexpected %s"; +static const char *voidWord = "void"; + +char buildErrorMsg[80] = ""; + +static int parserWriteError; +static int headerWriteError; + +static AgBalancedTree< Triple<int> > anomalyCases; + +typedef enum { + accept_key, + set_key, + jmp_key, + end_key, + no_match_key, + cf_accept_key, + cf_set_key, + cf_end_key +} key_words; + + +static void gen_input_code(void) { + char modes[40]; + const char *ps; + + write_code_segment(lines_and_columns ? "init col" : "init nocol"); + strcpy(modes, pointer_input ? " ptr" : " char"); + if (event_driven) { + strcat(modes," sink"); + } + //if (key_dict->nsx > 1) { + // strcat(modes," key"); + //} + if (Keyword::count() > 1) { + strcat(modes," key"); + } + sss("init macros"); + ass(modes); + acs(0); + define_my_macros(string_base); + rcs(); + select_write_fragment("init", modes, ""); + + ps = lines_and_columns ? " col" : ""; + sss("trk macros"); + ass(modes); + ass(ps); + acs(0); + define_my_macros(string_base); + rcs(); + select_write_fragment("trk", modes, ps); + ps = ""; + sss("get"); + ass(modes); + ass(ps); + acs(0); + define_my_macros(string_base); + rcs(); +} + +static void stack_null_rules(int f) { + int *rtl = ibnfs + ibnfb[f]; + int nrt = ibnfn[f]; + while (nrt-- && !map_token_number[rtl[nrt]].subgrammar) { + xws(rtl[nrt]); + } +} + +static int check_anomaly(int sn, int f, int n, int tn) { + LOGSECTION("check_anomaly"); + LOGV(sn) LCV(f) LCV(n) LCV(tn); + + state_number_map *sp = &map_state_number[sn]; + const int *rtl; + unsigned nrt; + unsigned i; + + if (anomalyCases.insert(Triple<int>(sn, f, n))) { + return 0; + } + + if (n) { + unsigned *p = lstptr(*sp, previous_states); + int nt = sp->n_previous_states; + + n--; + while (nt--) { + int ns = *p++; + int rs = check_anomaly(ns, f, n, tn); + if (rs) { + return rs; + } + } + return 0; + } + + rtl = ibnfs + ibnfb[f]; + nrt = ibnfn[f]; + iws(); + while (nrt-- && !map_token_number[rtl[nrt]].subgrammar) { + aws(rtl[nrt]); + } + for (i = 0; i < (unsigned) tis(); i++) { + int t = list_base[i]; + const unsigned *px = lstptr(*sp, completions); + int kn = sp->n_completions; + int flag = 0; + + while (kn--) { + const int rtk = *px++, g = *px++; + int rs; + if (rtk != t) { + continue; + } + rs = check_anomaly(sn, g, Rule(g)->length()-1, tn); + if (rs) { + return rws(),rs; + } + flag++; + break; + } + if (flag) { + continue; + } + px = lstptr(*sp, gotos); + kn = sp->n_gotos; + while (kn--) { + int rtk = *px++, s = *px++; + int fx; + unsigned *rp; + unsigned nr; + + if (rtk != t) { + continue; + } + if (shift_token(tn, s)) { + break; + } + Rule rule = ruleReducedBy(tn, s); + if (rule.isNotNull()) { + fx = rule->length(); + if (fx) { + int rs = check_anomaly(sn, rule, fx-1, tn); + if (rs) { + return rws(), rs; + } + continue; + } + stack_null_rules(rule); + continue; + } + sp = &map_state_number[s]; + nr = sp->n_completed_forms; + if (nr == 0) { + return rws(), s; + } + rp = lstptr(*sp, completed_forms); + for (i = 0; i < nr; i++) { + fx = Rule(rp[i])->length(); + if (fx) { + int rs = check_anomaly(sn, rp[i], fx-1, tn); + if (rs) { + return rws(),rs; + } + continue; + } + stack_null_rules(rp[i]); + } + } + } + rws(); + return 0; +} + + +/* + * reducing_token(tn, sn) returns 0 if tn is not a reducing token in state sn. + * Otherwise it returns the number of the rule it reduces. + */ + +static void check_keys(int sn) { + LOGSECTION("check_keys"); + LOGV(sn); + int kl = map_state_number[sn].key_list; + unsigned *token_list = lstptr(map_state_number[sn], t_actions); + unsigned nt = map_state_number[sn].n_actions; + int k; + const int *kp; + int nk; + + if (kl == 0) { + /* no keywords in this state; return */ + return; + } + + AgBalancedTree<AgArray<int> > parseErrorTree; + AgBalancedTree<AgArray<int> > noParseErrorTree; + + //LOGSECTION("check_keys"); + kp = dict_str(key_list_dict, kl); /* get list of keyword tokens */ + nk = *kp++ - 1; /* length of list */ + LOGV(sn) LCV(nt) LCV(nk); + for (k = 0; k < nk; k++) { /* for each keyword token */ + int flag = 0; + unsigned t; + unsigned char *ks; + Token keywordToken = kp[k]; + //unsigned kf = reducing_token(kp[k], sn); + Rule rule = ruleReducedBy(keywordToken, sn); + int rs; + int rt; + int i; + LOGSECTION("keyword loop"); + LOGV(k) LCV(keywordToken) LCV(rule); + + /* if kp[k] doesn't reduce anything or is marked anomalous, continue */ + + //if (kf == 0 || map_token_number[kp[k]].reserved_word) { + // continue; + //} + if (rule.isNull() || keywordToken->reserved_word) { + continue; + } + + /* kf is non-zero, therefore kp[k] reduces rule kf. */ + + Keyword key = keywordToken->key; /* get actual key index */ + KeywordDescriptor &keyDescriptor(key); + //rt = key->reserve; + rt = keyDescriptor.reserve; + LOGV(rt); + + //ks = key_string(keywordToken); + //ks = (unsigned char *) key->string.pointer(); + ks = (unsigned char *) keyDescriptor.string.pointer(); + LOGV(ks) LCV(key); + AgStack<int> tokenList; + unsigned char *ksp = ks; + while (*ksp) { + tokenList.push(map_char_number[*ksp++ - min_char_number].token_number); + } + int listSize = tokenList.size(); + LOGV(listSize); + AgArray<int> tokenArray(listSize); + while(listSize--) { + tokenArray[listSize] = tokenList[listSize]; + } + if (parseErrorTree.includes(tokenArray)) { + continue; + } + + //if (keyword_problem(sn, ks, key) < 0) { + // continue; + //} + if (!noParseErrorTree.includes(tokenArray)) { + if (keyword_problem(sn, tokenArray, key) < 0) { + parseErrorTree.insert(tokenArray); + continue; + } + noParseErrorTree.insert(tokenArray); + } + + t = map_char_number[*ks - min_char_number].token_number; + +/* if (string_cannot_be_shifted((unsigned char *)ks, sn)) continue; */ + + LOGV(nt); + for (i = 0; flag == 0 && (unsigned) i < nt; i++) { + const unsigned char *kks; + unsigned length; + int rts; + + //if (reducing_token(token_list[i],sn) == kf) continue; + if (ruleReducedBy(token_list[i],sn) == rule) continue; + + flag = token_list[i] == t; + if (flag) { + break; + } + + kks = key_string(token_list[i]); + if (kks == NULL) { + continue; + } + + //rts = map_key_word[map_token_number[token_list[i]].key].reserve; + //rts = Keyword(map_token_number[token_list[i]].key)->reserve; + rts = map_token_number[token_list[i]].key->reserve; + + if (rt == rts) { + continue; + } + length = strlen((const char *) kks); + flag = length < strlen((const char *) ks) + && strncmp((const char *) ks,(const char *) kks, length) == 0; + } + if (!flag) { + continue; + } + rs = check_anomaly(sn,rule, rule->length(), keywordToken); + anomalyCases.reset(); + if (rs) { + at(key_mess, sn, (int) keywordToken, (int) rule, rs); + } + } +} + +void build_parse_table(void) { + unsigned n; + unsigned sn; + int default_off = !default_reductions || error_token != 0; + + LOGSECTION("build_parse_table"); + parse_table_length = 0; + max_pn = 0; + LOGV(nforms_base); + LOGV(nforms); + if (traditional_engine) nforms_base = nforms; + n = (n_gotos + n_completions + n_reductions + + n_default_reductions + nits); + check_size(a_actions_list,n,n); + check_size(t_actions_list,n,n); + check_size(p_actions_list,n,n); + + LOGS("call build_key_tables"); + LOGV(nforms_base); + LOGV(nforms); + build_key_tables(); + + nstates = nits; + LOGV(nstates); + + for (sn = 0; sn < nstates; sn++) { + int default_ok = !default_off; + state_number_map *sp = &map_state_number[sn]; + int error_flag = 0; + int error_act = pe_syn_error, error_pn = 0; + const int *items = dict_str(isht_dict, sn); + int null_token_flag = 0; + int null_token_form = 0; + unsigned tn, pn; + pe_parser_action act; + const unsigned *p; + unsigned i; + + LOGV(sn); + LOGV(sp->n_completed_forms) LCV(sp->n_completions); + if (sp->n_completed_forms == 1) { + const unsigned *fp = lstptr(*sp, completed_forms); + Rule rule(*fp); + RuleDescriptor &ruleDescriptor(rule); +/* + if (!default_ok && default_reductions) { + default_ok = !rule->proc_name || rule->immediate_proc; + } + default_ok &= rule->length() != 0; +*/ + if (!default_ok && default_reductions) { + default_ok = !ruleDescriptor.reductionRequired + || ruleDescriptor.immediate_proc; + //default_ok = !ruleDescriptor.proc_name + // || ruleDescriptor.immediate_proc; + } + default_ok &= ruleDescriptor.length() != 0; + } + default_ok &= !traditional_engine; + if (default_ok) { + int fn, fx; + items++; + fn = *items++; + fx = *items++; + if (fx > 1 && Rule(fn).token(fx-1)==Token(error_token)) { + default_ok=0; + } + } + + iws(); + + /* first fast loops on terminal tokens */ + n = find_completions(sn, &p); + for (i = 0; i < n; i++) { + Token token = *p++; + Rule rule = pn = *p++; + //assert(pn <= nforms_base); + assert((unsigned) rule <= nforms_base); + //if (tn == error_token) default_ok = 0; + if ((int) token == error_token) default_ok = 0; + + //Rule rule(pn); + //Token token(tn); + if (token->non_terminal_flag) { + continue; + } + if (!rule->fast_loop) { + continue; + } + if (rule.isNull()) { + act = pe_shift_accept; + } + else if (!token->non_terminal_flag && + rule->length() == 2 && + ibnfn[(int) rule] == 1 && + error_token != token && + rule.token(0) == rule->prim_tkn) + { + act = pe_skip_reduce; + //if (rule->proc_name == 0) { + if (rule->reductionRequired == 0) { + act = pe_skip; + } + } + //else if (rule->proc_name || ibnfn[(int) rule] > 1) + else if (rule->reductionRequired || ibnfn[(int) rule] > 1) { + act = pe_shift_reduce; + } + else { + act = pe_shift_simple_reduce; + } + aws(act); aws(token); aws(rule); + LOGV(act) LCV(token) LCV(rule); + } + /* then completions by terminal tokens */ + n = find_completions(sn, &p); + for (i = 0; i < n; i++) { + Token token = *p++; + Rule rule = pn = *p++; + assert( (unsigned) rule <= nforms_base); + if ((int) token == error_token) { + default_ok = 0; + } + if (token->non_terminal_flag) { + continue; + } + if (rule->fast_loop) { + continue; + } + if (rule.isNull()) { + act = pe_shift_accept; + } + //else if (rule->proc_name || ibnfn[(int)rule] > 1) + else if (rule->reductionRequired || ibnfn[(int)rule] > 1) { + act = pe_shift_reduce; + } + else { + act = pe_shift_simple_reduce; + } + if ((int) token == error_token) { + error_act = act; + error_pn = (int) rule; + error_flag = 1; + continue; + } + aws(act); aws((int) token); aws((int)rule); + LOGV(act) LCV((int) token) LCV((int) rule); + } + /* go_tos on terminal tokens first */ + n = find_gotos(sn, &p); + for (i = 0; i < n; i++) { + tn = *p++; pn = *p++; + if (map_token_number[tn].non_terminal_flag) { + continue; + } + if ((int) tn == error_token) { + default_ok = 0; + error_act = pe_go_to; + error_pn = pn; + error_flag = 1; + continue; + } + aws(pe_go_to); aws(tn); aws(pn); + LOGV(pe_go_to) LCV(tn) LCV(pn); + } + + /* now reductions */ + LOGS("Now reductions") LCV(sp->n_reductions); + p = lstptr(*sp,reductions); + n = sp->n_reductions; + LOGV(default_ok) LCV(sp->n_completed_forms); + if (default_ok == 0 || sp->n_completed_forms != 1) { + for (i = 0; i < n; i++) { + tn = *p++; pn = *p++; + assert(pn <= nforms_base); + if (tn == 0) { + null_token_flag = 1; + null_token_form = pn; + continue; + } + act = pe_simple_reduce; + Rule rule(pn); + if (pn == 0) { + act = pe_accept; + } + //else if (rule->proc_name || ibnfn[(int) rule] > 1) + else if (rule->reductionRequired || ibnfn[(int) rule] > 1) { + act = pe_reduce_form; + } + else if (rule->length() == 0 + && !traditional_engine + && !rule_coverage + && (int) tn != error_token) { + unsigned *p; + unsigned n,t; + + p = lstptr(*sp, gotos); + n = sp->n_gotos; + t = rule->prim_tkn; + while (n && *p++ != t) { + p++; + n--; + } + if (n && x2d(*p, tn)) { + LOGSECTION("pe_null_go_to"); + pn = *p; + LOGV(sn) LCV(pn) LCV(tn) LCV(t) LCV(new_next_state(sn, tn)); + act = pe_null_go_to; + } + } + aws(act); aws(tn); aws(pn); + LOGV(act) LCV(tn) LCV(pn); + } + } + + if (error_flag) { + aws(error_act); aws(error_token); aws(error_pn); + LOGV(error_act) LCV(error_token) LCV(error_pn); + } + /* default action */ + LOGS("default action"); + if (null_token_flag) { + pn = null_token_form; + act = pe_simple_reduce; + if (pn == 0) { + act = pe_accept; + } + //else if (Rule(pn)->proc_name || ibnfn[pn] > 1) + else if (Rule(pn)->reductionRequired || ibnfn[pn] > 1) { + act = pe_reduce_form; + } + } + else if (default_ok && + sp->n_completed_forms == 1) { + //form_number_map *fp; + + p = lstptr(*sp,completed_forms); + pn = *p++; + LOGV(pn); + + assert(pn <= nforms_base); + Rule rule(pn); + act = pe_simple_reduce; + if (pn == 0) { + act = pe_accept; + } + //else if (rule->proc_name || ibnfn[pn] > 1) + else if (rule->reductionRequired || ibnfn[pn] > 1) { + act = pe_reduce_form; + } + else if (sp->n_gotos == 0) { + act = pe_simple_reduce; + } + } + else { + act = pe_syn_error, pn = sn; + } + + { + int *lb = list_base; + unsigned n = rws()/3; + int k = n; + tsd *tt = spec_tsd(n, 3); + sp->n_terminals = (int) n; + while (k--) { + int a = *lb++, t = *lb++, p = *lb++; + at(tt, t,a,p); + } + sort_tuples(tt, 1); + iws(); + lb = tt->sb + 3*n; + while (n--) { + int p = *--lb, a = *--lb, t = *--lb; + aws(a), aws(t), aws(p); + LOGV(a) LCV(t) LCV(p); + } + delete_tsd(tt); + } + + aws(act); aws(0); aws(pn); + LOGV(act) LCV(0) LCV(pn); + iws(); + n = find_completions(sn, &p); + for (i = 0; i < n; i++) { + //token_number_map *tp; + //form_number_map *fp; + + tn = *p++; + pn = *p++; + + Token token(tn); + if (!token->non_terminal_flag) { + continue; + } + Rule rule(pn); + if (pn == 0) { + act = pe_shift_accept; + } + //else if (rule->proc_name || ibnfn[pn] > 1) + else if (rule->reductionRequired || ibnfn[pn] > 1) { + act = pe_shift_reduce; + } + else { + act = pe_shift_simple_reduce; + } + aws(act); aws(tn); aws(pn); + LOGV(act) LCV(tn) LCV(pn); + } + n = find_gotos(sn,&p); + for (i = 0; i < n; i++) { + tn = *p++; + pn = *p++; + if (!map_token_number[tn].non_terminal_flag) { + continue; + } + aws(pe_go_to); aws(tn); aws(pn); + LOGV(pe_go_to) LCV(tn) LCV(pn); + } + + + { + int *lb = list_base; + unsigned n = rws()/3; + int k = n; + tsd *tt = spec_tsd(n, 3); + while (k--) { + int a = *lb++, t = *lb++, p = *lb++; + at(tt, t,a,p); + } + sort_tuples(tt, 1); + iws(); + lb = tt->sb; + while (n--) { + int t = *lb++, a = *lb++, p = *lb++; + aws(a), aws(t), aws(p); + LOGV(a) LCV(t) LCV(p); + } + delete_tsd(tt); + } + concat_list(); + select_actions(0); + sp->a_actions_index = store_list(a_actions_list); + rws(); + select_actions(1); + sp->t_actions_index = store_list(t_actions_list); + rws(); + select_actions(2); + sp->p_actions_index = store_list(p_actions_list); + rws(); + n = rws()/3; + parse_table_length += (sp->n_actions = n); + + p = lstptr(*sp, p_actions); + for (i = 0; i < n; i++) max_pn = max(max_pn, p[i]); + } + LOGS("Ready to check keywords"); + if (event_driven) parse_table_length++; + if (Keyword::count() > 1) { + if (badRecursionFlag) { + ssprintf("Keyword anomaly analysis aborted: %s", badRecursionFlag); + log_error(); + } + else { + for (sn = 0; sn < nstates; sn++) { + check_keys(sn); + } + } + } +} + +static void wr_char_map(const int *l) { + int i = min_char_number; + int k = 0; + unsigned n = *l++ - 1; + + assert(n <= n_chars); + for (; n--; l++) { + assert(*l >= min_char_number && *l <= max_char_number); + for (; i <= *l; i++) { + wpe(" %d,", i == *l); + if (++k < 24) { + continue; + } + wpe("\n"); + k = 0; + } + } + for (; i <= max_char_number; i++) { + wpe(" 0,"); + if (++k < 24) { + continue; + } + wpe("\n"); + k = 0; + } + if (k) { + wpe("\n"); + } +} + +static void write_key_tables(void) { + unsigned sn; + unsigned ps, *p; + int i; + unsigned ch, act, parm, jmp; + const char *cs; + const char *type = ntkns <= 255 ? "char" : ntkns <= 65535 ? "short" : "int"; + unsigned ncs = char_set_dict->nsx; + int nkw = Keyword::count(); + //int *map_cs_ax = local_array(ncs, int); + LocalArray<int> map_cs_ax(ncs); + //int *map_kw_tn = local_array(nkw, int); + LocalArray<int> map_kw_tn(nkw); + //unsigned char *cs_flag = local_array(ncs, unsigned char); + LocalArray<unsigned char> cs_flag(ncs); + int ncm; + int npt = 0; + + memset(cs_flag, 0, ncs); + memset(map_kw_tn, 0, nkw * sizeof(int)); + + { + ncm = 0; + wpe("\nstatic %sunsigned char %sag_key_itt[] = {\n", constWord, LOCUS); + for (i = 1; i < nkw; i++) { + //unsigned cs = map_key_word[i].reserve; + Keyword keyword = i; + KeywordDescriptor &keywordDescriptor(keyword); + //int cs = keyword->reserve; + int cs = keywordDescriptor.reserve; + assert(cs < (int) ncs); + if (cs == 0) { + continue; + } + if (cs_flag[cs] == 0) { + map_cs_ax[cs] = ncm*n_chars - min_char_number; + ncm++; + cs_flag[cs] = ncm != 0; + wr_char_map(dict_str(char_set_dict, cs)); + } + //map_kw_tn[i] = map_key_word[i].token_number; + //map_kw_tn[i] = keyword->token_number; + map_kw_tn[i] = keywordDescriptor.token_number; + } + wpe(" 0\n};\n\nstatic %sunsigned short %sag_key_pt[] = {\n", + constWord, LOCUS); + ps = 2; + cs = ""; + for (i = 1; i < nkw; i++) { + Keyword keyword = i; + //int csn = map_key_word[i].reserve; + int csn = keyword->reserve; + if (csn == 0) { + continue; + } + ps += wpe("%s%3d,%3d", cs, map_cs_ax[csn], map_kw_tn[i]); + map_kw_tn[i] = npt; + npt += 2; + if (ps > 64) { + ps = 0, cs = ",\n"; + } + else { + cs = ","; + } + } + wpe("%s0\n};\n",cs); + } + cs = " "; + ps = 2; + p = (unsigned *) key_table->sb; + wpe("\nstatic %sunsigned char %sag_key_ch[] = {\n", constWord, LOCUS); + for (i = 0; i < (int) key_table->nt; i++) { + + ch = *p++; + act = *p++; + parm = *p++; + jmp = *p++; + + if (!case_sensitive) { + ch = agToUpper((char) ch); + } + ps += wpe("%s%3d", cs, ch); + if (ps > 72) { + ps = 0, cs = ",\n "; + } + else { + cs = ","; + } + } + wpe("\n};\n"); + + cs = " "; + ps = 2; + p = (unsigned *) key_table->sb; + wpe("\nstatic %sunsigned char %sag_key_act[] = {\n", constWord, LOCUS); + for (i = 0; i < (int) key_table->nt; i++) { + //int key; + + ch = *p++; + act = *p++; + parm = *p++; + jmp = *p++; + + //key = map_token_number[parm].key; + Keyword key = map_token_number[parm].key; + //if (key && map_key_word[key].reserve) switch (act) { + if (key.isNotNull() && key->reserve) { + switch (act) { + case accept_key: act = cf_accept_key; + break; + case set_key: act = cf_set_key; + break; + case end_key: act = cf_end_key; + break; + } + } + ps += wpe("%s%1d", cs, act); + if (ps > 72) { + ps = 0, cs = ",\n "; + } + else { + cs = ","; + } + } + wpe("\n};\n"); + + cs = " "; + ps = 2; + p = (unsigned *) key_table->sb; + + wpe("\nstatic %sunsigned %s %sag_key_parm[] = {\n",constWord, type, LOCUS); + for (i = 0; i < (int) key_table->nt; i++) { + //int key; + + ch = *p++; + act = *p++; + parm = *p++; + jmp = *p++; + + //key = map_token_number[parm].key; + Keyword key = map_token_number[parm].key; + //if (key && map_key_word[key].reserve) switch (act) { + if (key.isNotNull() && key->reserve) { + switch (act) { + case accept_key: + case set_key: + case end_key: + parm = map_kw_tn[(int) key]; + } + } + ps += wpe("%s%3d", cs, parm); + if (ps > 72) { + ps = 0, cs = ",\n "; + } + else { + cs = ","; + } + } + wpe("\n};\n"); + + cs = " "; + ps = 2; + p = (unsigned *) key_table->sb; + + /* + * Originally this was (equivalent to) + * + * size = key_table->nt + * + * but that was commented out and replaced with (code equivalent to) + * + * size = n_key_ends; + * + * but that definitely breaks if there are more than 256 keywords; + * see for example manykw.syn in the test suite. It's also clear + * from the parse engine code that there can be cases where + * n_key_ends matters. So take the max. I think token numbers + * (where one would check ntkns as above) are not involved here. + * + * - dholland 6/3/2007 + */ + + unsigned size = max(key_table->nt, n_key_ends); + type = size <= 255 ? "char" + : size <= 65535 ? "short" + : "int"; + + wpe("\nstatic %sunsigned %s %sag_key_jmp[] = {\n", constWord, type, LOCUS); + for (i = 0; i < (int) key_table->nt; i++) { + + ch = *p++; + act = *p++; + parm = *p++; + jmp = *p++; + + ps += wpe("%s%3d", cs, jmp); + if (ps > 72) { + ps = 0, cs = ",\n "; + } + else { + cs = ","; + } + } + wpe("\n};\n"); + + cs = " "; + ps = 2; + + if (key_table->nt > 65535) { + type = "int"; + } + else if (key_table->nt >255) { + type = "short"; + } + else { + type = "char"; + } + + wpe("\nstatic %sunsigned %s %sag_key_index[] = {\n", constWord, type, LOCUS); + for (sn = 0; sn < nstates; sn++) { + ps += wpe("%s%3d", cs, map_state_number[sn].key_index); + if (ps > 72) { + ps = 0, cs = ",\n "; + } + else { + cs = ","; + } + } + if (event_driven) { + wpe("%s%3d", cs, 0); + } + wpe("\n};\n"); + + ps = 2; + wpe("\nstatic %sunsigned char %sag_key_ends[] = {\n", constWord, LOCUS); + if (n_key_ends) { + for (i = 0; i < (int) n_key_ends; ) { + char *s = key_ends+i; + int k = 3*strlen(s) + 4; + cs = ""; + if (ps + k> 72) { + cs = "\n", ps = 0; + } + sss(cs); + if (case_sensitive) { + while (*s) { + apprintf("%u,", (unsigned char) *s++); + } + } + else { + while (*s) { + apprintf("%u,", (unsigned char) agToUpper(*s++)); + } + } + ass("0, "); + acs(0); + ps += wss(); + i += strlen(key_ends+i)+1; + } + } + else { + wpe(" 0"); + } + wpe("\n};\n"); +} + +static const char *more = ","; +static int lm = 1; +static const char *line = ",\n "; + +static void write_parse_table_actions (void) { + const char *cs = " "; + unsigned ks; + unsigned sx = 0; + int kw = 0; + + wpe("\nstatic unsigned %schar %sag_astt[%d] = {\n", + constWord, LOCUS, parse_table_length); + + for (ks = 0; ks < nstates; ks++) { + state_number_map *sp = &map_state_number[ks]; + unsigned *p = lstptr(*sp, a_actions); + int n = sp->n_actions; + int i; + + for (i = 0; i < n; i++) { + unsigned an = *p++; + int nc = ssprintf("%u", an); + if (an > pe_recover) { + assert(0); + } + sx++; + if (kw + nc >= parserLineLength) { + cs = line; + kw = -2; + } + wps(cs); + kw += strlen(cs) + wss(); + cs = more; + } + sp->engine_index = sx - 1; + } + if (event_driven) { + wpe("%s%d\n};\n\n", cs, pe_recover); + max_engine_index = sx; + return; + } + wpe("\n};\n\n"); + max_engine_index = sx -1; +} + +static void write_parse_table_params (void) { + const char *cs = ""; + unsigned ks; + unsigned sx = 0; + int lc = 0; + unsigned np = max_pn; + const char *type = np <= 255 ? "char" : np <= 65535 ? "short" : "int"; + + wpe("\nstatic %sunsigned %s %sag_pstt[] = {\n", constWord, type, LOCUS); + for (ks = 0; ks < nstates; ks++) { + state_number_map *sp = &map_state_number[ks]; + int kw = 0; + unsigned *p = lstptr(*sp, p_actions); + int n = sp->n_actions; + int i; + + for (i = 0; i < n; i++) { + int nc = ssprintf("%u", *p++); + sx++; + if (kw + nc + lc >= parserLineLength) { + cs = line; + kw = 0; + } + wps(cs); + kw += strlen(cs) + wss(); + cs = more; + lc = lm; + } + sp->engine_index = sx - 1; + wps(",\n"); + cs = ""; + lc = 0; + } + if (event_driven) { + wpe(" 0\n};\n\n"); + max_engine_index = sx; + return; + } + wpe("\n};\n\n"); + max_engine_index = sx -1; +} + +static void set_my_macro(const char *, const char *, ...) PRINTFFY (2,3); + +static void write_parse_table_tokens (void) { + const char *cs = ""; + unsigned ks; + unsigned sx = 0; + int lc = 0; + const char *type = ntkns <= 255 ? "char" : ntkns <= 65535 ? "short" : "int"; + + set_my_macro("AG_TSTT_TYPE","%sunsigned %s", constWord, type); + set_my_macro("AG_TSTT_CAST","unsigned %s", type); + wpe("static %sunsigned %s %sag_tstt[] = {\n", constWord, type, LOCUS); + + for (ks = 0; ks < nstates; ks++) { + state_number_map *sp = &map_state_number[ks]; + //int nterm = 0; + int kw = 0; + unsigned *p = lstptr(*sp, t_actions); + int n = sp->n_actions; + int i; + + for (i = 0; i < n; i++) { + int nc; + int tn = *p++; + + //if (tn && !map_token_number[tn].non_terminal_flag) nterm++; + nc = ssprintf("%u",tn); + sx++; + if (kw + nc + lc >= parserLineLength) { + cs = line; + kw = 0; + } + wps(cs); + kw += strlen(cs) + wss(); + cs = more; + lc = lm; + } + sp->engine_index = sx - 1; + wps(",\n"); + cs = ""; + lc = 0; + } + if (event_driven) { + wpe(" 0\n};\n\n"); + max_engine_index = sx; + return; + } + max_engine_index = sx -1; + wpe("\n};\n\n"); +} + +static void write_header(const char *pname) { + if (rule_coverage) { + AgString cfile = subs_template(simple_file_name.pointer(), + coverage_file_name.pointer(), '#'); + + set_my_macro("AG_COUNT_FILE", "\"%s\"", cfile.pointer()); + set_my_macro("AG_COUNT_FILE_ID", "%ldL", (long) infile_time_stamp); + set_my_macro("AG_READ_COUNTS", "%s%s_read_counts(%s)", + VOIDB, pname, voidWord); + set_my_macro("AG_WRITE_COUNTS", "%s%s_write_counts(%s)", + VOIDB, pname, voidWord); + define_macro("READ_COUNTS", "%s_read_counts()", pname); + define_macro("WRITE_COUNTS", "%s_write_counts()", pname); + set_my_macro("AG_COUNT_FILE_RC", "%d", nforms_base+1); + set_my_macro("AG_RULE_COUNT", "%s_nrc", pname); + + set_my_macro("AG_COUNT_RULE_P", "%s_nrc[(PCB).ag_ap]++;", pname); + set_my_macro("AG_COUNT_RULE_Z", "%s_nrc[0]++;", pname); + + wpe("unsigned %s_nrc[%d];\n", pname, nforms_base+1); + write_code_segment("read write counts"); + //DEALLOCATE(cfile); + } + else { + set_my_macro("AG_COUNT_RULE_P", "%s", ""); + set_my_macro("AG_COUNT_RULE_Z", "%s", ""); + define_macro("READ_COUNTS", "%s", ""); + define_macro("WRITE_COUNTS", "%s", ""); + } +} + +static void writePrologue() { + LOGSECTION("writePrologue"); + LOGV(nPrologueSegments); + if (nPrologueSegments == 0) { + return; + } + nPrologueSegments = 1; + CSegment &segment = cSegmentStack[0]; + if (segment.length() + && fwrite(segment.begin, segment.length(), 1, pe_file) == 0) { + parserWriteError = EOF; + } + count_pe_line((const char *)segment.begin, segment.length()); +} + +static void writeEmbeddedC() { + LOGSECTION("writeEmbeddedC"); + int n = cSegmentStack.size(); + int i = nPrologueSegments; + while (i < n) { + CSegment &segment = cSegmentStack[i]; + if (line_numbers) { + wpe("#line %d \"%s\"\n", segment.line, ln_file_name.pointer()); + } + else { + wpe("/* Line %d, %s */\n", segment.line, ln_file_name.pointer()); + } + if (segment.length() + && fwrite(segment.begin, segment.length(),1,pe_file) == 0) { + parserWriteError = EOF; + } + count_pe_line((const char *) segment.begin, segment.length()); + if (line_numbers) { + wpe("#line %d \"%s\"\n", pe_line_count+2, ln_pe_name.pointer()); + } + i++; + } + if ((unsigned) nPrologueSegments < cSegmentStack.size()) { + wps("\n"); + } +} + +static void writePCBExtensions() { + LOGSECTION("writePCBExtensions"); + int n = extensionStack.size(); + int i = 0; + while (i < n) { + CSegment &segment = extensionStack[i]; + headerWriteError = fprintf(h_file, "/* Line %d, %s */\n", + segment.line, ln_file_name.pointer()); + if (fwrite(segment.begin, segment.length(),1,h_file) == 0) { + headerWriteError = 1; + } + i++; + } +} + +static void define_proc(Procedure proc, int ilFlag, AgString thisArg, + AgString thisArgc) { + LOGSECTION("define_proc"); + const char *cs = thisArgc.pointer(); + const char *ft = proc->cast == 1 ? voidWord : Cast(proc->cast)->pointer(); + const char *ilString = ilFlag ? "inline " : ""; + AgString ns = proc_name_string(proc); + LOGV(proc) LCV(cs) LCV(ft) LCV(proc->cast) LCV(ns); + wpe("\nstatic %s%s %s%s(", ilString, ft, nearWord, ns.pointer()); + + //AgArray<RuleElement> elementList = Rule(proc->form_number)->elementList; + Rule rule(proc->form_number); + int bias = rule->op_bias; + LOGV(rule) LCV(bias); + AgArray<RuleElement> elementList = + bias ? rule->hostElementList : rule->elementList; + + if (really_old_style) { + unsigned j; + for (j = 0; j < elementList.size(); j++) { + RuleElement &element = elementList[j]; + if (element.cVariable == 0) { + continue; + } + wpe("%s%s",cs, cVariableList[element.cVariable].pointer()); + cs = ", "; + } + wpe(")\n"); + for (j = 0; j < elementList.size(); j++) { + RuleElement &element = elementList[j]; + if (element.cVariable == 0) { + continue; + } + wpe(" %s %s;\n", + Cast(element.token->value_type)->pointer(), + cVariableList[element.cVariable].pointer()); + //dict_str(cast_dict, element.token->value_type), + //element.cVariable->pointer()); + } + wpe("{\n"); + } + else { + unsigned j; + int argCount = 0; + for (j = 0; j < elementList.size(); j++) { + RuleElement &element = elementList[j]; + if (element.cVariable == 0) { + continue; + } + const char *reference = ""; + Cast type = element.token->value_type; + if (type.wrapperRequired()) { + reference = "&"; + } + + //wpe("%s%s %s", cs, + // dict_str(cast_dict, element.token->value_type), + // element.cVariable->pointer()); + + wpe("%s%s %s%s", cs, + Cast(element.token->value_type)->pointer(), reference, + cVariableList[element.cVariable].pointer()); + + argCount++; + cs = ", "; + } + //cs = argCount ? "" : voidWord; + cs = argCount ? "" : thisArg.pointer(); + LOGV(argCount) LCV(cs); + wpe("%s) {\n",cs); + } +} + +static void print_token_names(const char *pname) { + LOGSECTION("print_token_names"); + + define_macro("TOKEN_NAMES", "%s_token_names", pname); + wpe("%schar *%s%s_token_names[%d] = {\n \"%s\",\n", + constWord, constWord, pname, ntkns+1, + Token(grammar_token)->token_name->string.pointer()); + + for (Each<Token> token; token.loopNotFinished(); token.getNext()) { + char *string; + Symbol name = token->token_name; + + ics(); + LOGV(token_names_only) LCV(token->fine_structure) LCV(name.isNotNull()); + if (token->fine_structure) { + /* nothing */ + } + else if (name.isNotNull()) { + ass(name->string.pointer()); + } + else if (!token_names_only) { + Keyword key = token->key; + ParseTree tree = token->parse_tree; + LOGV(key.isNotNull()) LCV(tree.isNotNull()); + if (tree.isNotNull()) { + LOGV(tree->expression->type); + } + if (key.isNotNull()) { + LOGV(key); + acs('"'); + append_key(key); + acs('"'); + } + else if (tree.isNotNull() + && tree->expression->type == CharSetExpression::individualChar){ + IndividualChar *expression = (IndividualChar *) (tree->expression); + LOGV(expression->asString().pointer()); + //acs(expression->asciiValue); + ass(expression->asString().pointer()); + } + } + acs(0); + LOGV(string_base); + string_space(2*tis()); + string = string_base; + sss(" \""); + while (*string) { + append_string_char(*string++); + } + ass("\",\n"); + wss(); + rcs(); + } + wpe("\n};\n\n"); +} + + +#define N_MY_MACROS 150 + +char *my_macros_subs[N_MY_MACROS]; + +static void set_my_macro(const char *m, const char *s, ...) { + LOGSECTION("set_my_macro"); + LOGV(m) LCV(s); + int k = add_string_dict(m, my_macros); + va_list ap; + char buf[500]; + int n; + + va_start(ap,s); + n = vsprintf(buf, s, ap); + assert (n < 500); + assert(k < N_MY_MACROS); + if (my_macros_subs[k]) { + DEALLOCATE(my_macros_subs[k]); + } + my_macros_subs[k] = mystrdup(buf); + va_end(ap); +} + +static void rename_macro(const char *sword, const char *sval) { + LOGSECTION("rename_macro"); + LOGV(sword) LCV(sval); + char *word; + char *val; + int index; + + const char *s = sword; + ics(); + while (*s && (isalpha(*s) || *s == '_')) { + acs(*s++); + } + word = build_string(); + + ics(); + s = sval; + while (*s && (isalpha(*s) || *s == '_')) { + acs(*s++); + } + val = build_string(); + + index = add_string_dict(word, my_macros); + assert(index < N_MY_MACROS); + if (my_macros_subs[index]) { + DEALLOCATE(my_macros_subs[index]); + } + my_macros_subs[index] = val; + DEALLOCATE(word); +} + +static void define_my_macros(const char *seg) { + AgString text = code_segment(seg); + if (!text.exists()) { + return; + } + char *buf = text.pointer(); + char *s = buf; + char *val; + char *word; + int index; + + while (*s) { + while (*s && *s == ' ') { + s++; + } + if (*s == '\n') { + s++; + continue; + } + + ics(); + while (*s && (isalpha(*s) || *s == '_')) { + acs(*s++); + } + ics(); + while (*s) { + while (*s && *s == ' ') { + s++; + } + if (strncmp(s,"\\\n", 2)) { + break; + } + s += 2; + } + while (*s && *s != '\n') { + if (*s == '\\') { + s++; + } + acs(*s++); + } + if (*s == '\n') { + s++; + } + val = build_string(); + word = build_string(); + index = add_string_dict(word, my_macros); + assert(index < N_MY_MACROS); + if (my_macros_subs[index]) { + DEALLOCATE(my_macros_subs[index]); + } + my_macros_subs[index] = val; + DEALLOCATE(word); + } +} + +static int argsCompare(AgArray<RuleElement> x, AgArray<RuleElement> y) { + unsigned kx = 0, ky = 0; + while (kx < x.size() && ky < y.size()) { + while (kx < x.size() && x[kx].cVariable == 0) { + kx++; + } + while (ky < y.size() && y[ky].cVariable == 0) { + ky++; + } + if (kx == x.size() && ky == y.size()) { + return 1; + } + if (kx == x.size() || ky == y.size()) { + return 0; + } + if (x[kx].cVariable != y[ky].cVariable) { + return 0; + } + if (x[kx].token->value_type != y[ky].token->value_type) { + return 0; + } + kx++; + ky++; + } + return 0; +} + +static int aliasReductionProc(Procedure proc) { + LOGSECTION("aliasReductionProc"); + LOGV(proc); + Procedure aliasProc = 1; + while ((int)aliasProc < (int)proc) { + if (aliasProc->cSegment.length() != proc->cSegment.length()) { + return 0; + } + if (aliasProc->cast != proc->cast) { + return 0; + } + if (strncmp((const char *)aliasProc->cSegment.begin, + (const char *) proc->cSegment.begin, + proc->cSegment.length())) { + return 0; + } + if (argsCompare(Rule(aliasProc->form_number)->elementList, + Rule(proc->form_number)->elementList)) { + return aliasProc; + } + aliasProc = (int) aliasProc + 1; + } + return 0; +} + + +void build_parse_engine(void) { + LOGSECTION("build_parse_engine"); + unsigned i; + unsigned j; //,k; + unsigned n; + int kw; + int tn; + const char *cs, *vs; + const char *cp; + const char *type; + really_old_style = old_style && !reentrant_parser; + AgString pname = subs_template(simple_file_name.pointer(), + parser_name.pointer(), '#'); + AgString cbt = subs_template(pname.pointer(), control_block_type, '$'); + AgString structName = subs_template(pname.pointer(), structNameTemplate,'%'); + AgString thisArg(reentrant_parser ? "PCB_DECL" : "void"); + AgString thisArgc(reentrant_parser ? "PCB_DECL, " : ""); + AgString pcbArg = reentrant_parser ? "PCB_POINTER" : ""; + AgString pcbArgc = reentrant_parser ? "PCB_POINTER, " : ""; + AgString vst = subs_template(pname.pointer(), value_stack_type, '$'); + AgString token_type = subs_template(pname.pointer(), typedef_name, '$'); + AgString h_file_name = subs_template(simple_file_name.pointer(), + header_file_name.pointer(), '#'); + AgString itt = subs_template(pname.pointer(), input_type_name, '$'); + AgString enum_name = subs_template(pname.pointer(), + enum_constant_name.pointer(), '$'); + const char *void_string = really_old_style ? "" : "void"; + const char *stack_value; + const char *stack_result; + const char *stack_location; + int bt = backtrack || auto_resynch || error_token; + int *rtkn_list = NULL; + int *rtkn_ndx = 0; + + static unsigned rtkn_count = 0; + + const char *csp; + unsigned buildTime = (unsigned) time(0); + + constWord = "const "; + nearWord = "near "; + LOCUS = ""; + VOIDB = "void "; + voidWord = "void"; + + Cast defaultType(default_token_type); + + if (line_numbers_path.exists()) { + ln_file_name = line_numbers_path; + } + else if (escape_backslashes) { + int length = infile_name.size(); + int k = length; + int n = 0; + while (k--) { + if (infile_name.operator[](k) == '\\') { + n++; + } + } + AgCharStack temp; + char *q = infile_name.pointer(); + while (*q) { + temp.push(*q); + if (*q == '\\') { + temp.push('\\'); + } + q++; + } + ln_file_name = temp.popString(); + } + else { + ln_file_name = infile_name.pointer(); + int length = ln_file_name.size(); + int k = length; + while (k--) { + if (ln_file_name[k] == '\\') { + ln_file_name[k] = '/'; + } + } + } + LOGV(ln_file_name.pointer()); + my_macros = null_str_dict(); + for (i = 0; i < rename_macro_list->nt; i++) { + unsigned old_name, new_name; + xtx(rename_macro_list, i, &old_name, &new_name); + rename_macro((const char *)(input_base+old_name), + (const char *)(input_base+new_name)); + } + + if (error_token) { + auto_resynch = 0; + } + + pe_file_name = subs_template(simple_file_name.pointer(), + parser_file_name.pointer(), '#'); + if (pe_file_name[0] == '.'&& pe_file_name[1]!='.') { + AgString pattern = pe_file_name.pointer(); + pattern[0] = '#'; + pe_file_name = subs_template(work_dir_name.pointer(), + pattern.pointer(), '#'); + } + LOGV(pe_file_name); + if (escape_backslashes) { + //int length = strlen(pe_file_name); + int length = pe_file_name.size(); + int k = length; + int n = 0; + while (k--) { + if (pe_file_name[k] == '\\') { + n++; + } + } + ln_pe_name = AgString(length + n); + LOGV(length) LCV(n); + char *q = ln_pe_name.pointer(); + for (k = n = 0; k < length; k++) { + q[n++] = pe_file_name[k]; + LOGV(k) LCV(n); + if (pe_file_name[k] == '\\') { + q[n++] = '\\'; + } + } + } + else { + ln_pe_name = pe_file_name.pointer(); + int k = ln_pe_name.size(); + while (k--) { + if (ln_pe_name[k] == '\\') { + ln_pe_name[k] = '/'; + } + } + } + LOGV(ln_pe_name); + LOGV(pe_file_name); + LOGV(h_file_name); + const char *openMode = no_cr ? "wb" : "w"; + pe_file = fopen(pe_file_name.pointer(), openMode); + parserWriteError = 0; + pe_line_count = 0; + buildErrorMsg[0] = 0; + if (pe_file == NULL) { + sprintf(buildErrorMsg, "Cannot open %s", pe_file_name.pointer()); + //DEALLOCATE(pe_file_name); + return; + } + h_file = fopen(h_file_name.pointer(),openMode); + headerWriteError = 0; + if (h_file == NULL) { + sprintf(buildErrorMsg, "Cannot open %s", h_file_name.pointer()); + //DEALLOCATE(h_file_name); + fclose(pe_file); + return; + } + + grammar_type = map_token_number[grammar_token].value_type; + if (grammar_type.isNull()) { + grammar_type = default_token_type; + } + sfn = simple_file_name.pointer(); + LOGV(sfn); + sfn.toUpper(); + LOGV(sfn); + headerWriteError = fprintf(h_file, + "#ifndef %s_H_%u\n" + "#define %s_H_%u\n\n", + sfn.pointer(), buildTime, sfn.pointer(), buildTime); + + if (Cast::nWrappers) { + AgString def = code_segment("wrapper def"); + headerWriteError = fprintf(h_file, "%s\n", def.pointer()); + } + + // Make list of terminal tokens + AgBalancedTree<int> typeList; + Each<Token> token; + for (token.restart(); token.loopNotFinished(); token.getNext()) { + if (token->non_terminal_flag) { + continue; + } + if (token->value_type > 1) { + typeList.insert(token->value_type); + } + } + n = typeList.size(); + LOGV(typeList.size()); + if (n <= 1) { + input_token_type = n ? typeList[0] : default_input_type; + itt = Cast(input_token_type).name(); + } + else { + unsigned k; + + headerWriteError = fprintf(h_file, "typedef union {\n"); + for (k = 0; k < n; k++) { + int i = typeList[k]; + if (i == void_token_type) continue; + LOGV(i) LCV(Cast(i)->pointer()); + Cast type = i; + if (type.wrapperRequired()) { + headerWriteError = + fprintf(h_file, " char ag_vt_%d[sizeof(AgObjectWrapper<%s >)];\n", + i, type->pointer()); + } + else { + headerWriteError = + fprintf(h_file, " char ag_vt_%d[sizeof(%s)];\n", + i, type->pointer()); + } + } + LOGV(itt); + headerWriteError = fprintf(h_file, "} %s;\n\n", itt.pointer()); + input_token_type = Cast(itt.pointer()); + } + + typeList.reset(); + LOGV(Cast::count()); + for (token.restart(); token.loopNotFinished(); token.getNext()) { + //int tt = map_token_number[i].value_type; + Cast type = token->value_type; + if ((int) type == void_token_type) { + continue; + } + LOGV(type); + LOGV(type->pointer()); + if ((int) type == 0 || typeList.insert((int) type)) { + continue; + } + if (strcmp(type->pointer(), "double")) { + continue; + } + if (parser_stack_alignment == long_token_type) { + parser_stack_alignment = (int) type; + } + } + n = typeList.size(); + LOGV(typeList.size()); + if (typeList.size() == 0) { + typeList.insert(int_token_type); + } + n = typeList.size(); + if (n == 1) { + vst = Cast(typeList[0]).name(); + stack_value = "VS(%d)"; + stack_result = "VS(0) = "; + stack_location = "(PCB).vs[(PCB).ssx]"; + } + else { + stack_value = "V(%d,(%s *))"; + stack_result = "V(0,(%s *)) = "; + stack_location = "(*(%s *) &(PCB).vs[(PCB).ssx])"; + headerWriteError = fprintf(h_file, "typedef union {\n"); + if (parser_stack_alignment != void_token_type) { + LOGV(parser_stack_alignment); + LOGV(Cast(parser_stack_alignment)->pointer()); + headerWriteError = fprintf(h_file, " %s alignment;\n", + //dict_str(cast_dict, parser_stack_alignment) + Cast(parser_stack_alignment)->pointer()); + } + for (i = 0; i < n; i++) { + //int j = list_base[i]; + int j = typeList[i]; + if (j == void_token_type) { + continue; + } + LOGV(j) LCV(Cast(j)->pointer()); + Cast type = j; + if (type.wrapperRequired()) { + headerWriteError = + fprintf(h_file, " char ag_vt_%d[sizeof(AgObjectWrapper<%s >)];\n", + j, type->pointer()); + } + else { + headerWriteError = + fprintf(h_file, " char ag_vt_%d[sizeof(%s)];\n", + j, type->pointer()); + } + } + headerWriteError = fprintf(h_file, "} %s;\n\n", vst.pointer()); + } + + LOGS("Ready to write prologue"); + writePrologue(); + LOGS("Prologue written"); + wpe("\n"); + + LOGV(copyrightMessage); + wpe(code_segment(copyrightMessage).pointer(), + VERSIONSTRING, build_date.pointer()); + + set_my_macro("STATIC", "static "); + set_my_macro("QUAL", "%s", ""); + if (!near_functions) { + nearWord = ""; + } + cp = near_functions ? "near " : ""; + set_my_macro("NEAR", cp); + cp = far_tables ? "far" : near_functions ? "near" : ""; + if (far_tables) { + LOCUS = "far "; + } + set_my_macro("LOCUS", LOCUS); + cp = really_old_style ? "" : "void"; + if (really_old_style) { + voidWord = VOIDB = ""; + } + set_my_macro("VOID", cp); + set_my_macro("THISARG", thisArg.pointer()); + set_my_macro("THISARGC", thisArgc.pointer()); + set_my_macro("PCBARG", pcbArg.pointer()); + set_my_macro("PCBARGC", pcbArgc.pointer()); + if (really_old_style || !const_data) { + constWord = ""; + } + set_my_macro("CONST", constWord); + + set_my_macro("MISSING", "%s", missing_diagnostic); + set_my_macro("UNEXPECTED", "%s", unexpected_diagnostic); + + wpe("\n#ifndef %s_H_%u\n" + "#include \"%s\"\n" + "#endif\n\n" + "#ifndef %s_H_%u\n" + "#error Mismatched header file\n" + "#endif\n\n", + sfn.pointer(), buildTime, h_file_name.pointer(), + sfn.pointer(), buildTime); + if (diagnose_errors) { + wpe("#include <ctype.h>\n"); + } + write_code_segment("header"); + if (reentrant_parser) { + wpe("#ifndef PCB_TYPE\n#define PCB_TYPE %s\n#endif\n\n", cbt.pointer()); + wpe("\n#define PCB (*pcb_pointer)\n"); + set_my_macro("PCB_TYPE_CAST", "(PCB_TYPE *)"); + wpe("#define PCB_DECL PCB_TYPE *pcb_pointer\n"); + wpe("#define PCB_POINTER pcb_pointer\n"); + } + else { + set_my_macro("PCB_TYPE_CAST", "%s", ""); + if (declare_pcb) { + wpe("\n%s %s_pcb;\n#define PCB %s_pcb\n", + cbt.pointer(), pname.pointer(), pname.pointer()); + } + } + rtkn_count = 0; + if (semantic_productions) { + const char *as = really_old_style ? "" : token_type.pointer(); + const char *ds = really_old_style ? "int ag_k;" : ""; + AgString enum_temp = subs_template("##x##", enum_name.pointer(), '%'); + unsigned fn, nsd=0; + define_macro("CHANGE_REDUCTION(x)", + "%s_change_reduction(%s%s)", + pname.pointer(), pcbArgc.pointer(), enum_temp.pointer()); + set_my_macro("AG_CHANGE_REDUCTION", + "%s_change_reduction(%s%s ag_k)%s", + pname.pointer(), thisArgc.pointer(), as,ds); + wpe("int %s_change_reduction(%s%s);\n\n", + pname.pointer(), thisArgc.pointer(), as); + + as = really_old_style ? "ag_tp" : "int *ag_tp"; + ds = really_old_style ? "int *ag_tp" : ""; + if (reduction_choices) { + set_my_macro("AG_CHOICES", + "%s_reduction_choices(%s%s)%s", + pname.pointer(), thisArgc.pointer(), as, ds); + define_macro("REDUCTION_CHOICES(x)", + "%s_reduction_choices(%sx)", + pname.pointer(), pcbArgc.pointer()); + wpe("int %s_reduction_choices(%s%s);\n", + pname.pointer(), thisArgc.pointer(), as); + } + for (fn = 0; fn++ < nforms_base;) { + if (ibnfn[fn] > 1) { + nsd += ibnfn[fn] + 1; + } + } + rtkn_count = nsd; + rtkn_list = local_array(nsd, int); + rtkn_ndx = local_array(nforms_base+1, int); + nsd = 0; + for (fn = 0; fn++ < nforms_base;) { + int n = ibnfn[fn]; + const int *p; + if (n == 1) { + continue; + } + p = ibnfs+ibnfb[fn]; + rtkn_ndx[fn] = nsd; + while (n--) { + rtkn_list[nsd++] = *p++; + } + rtkn_list[nsd++] = 0; + } + } + AgString iname = AgString("init_").concat(pname); + if (reentrant_parser) { + set_my_macro("AG_INIT_PARSE", "%s%s(%s *PCB_POINTER)", + VOIDB, iname.pointer(), cbt.pointer()); + set_my_macro("AG_PARSE", "%s%s(%s *PCB_POINTER)", + VOIDB, pname.pointer(), cbt.pointer()); + } + else { + set_my_macro("AG_INIT_PARSE", + "%s%s(%s)", VOIDB, iname.pointer(), voidWord); + set_my_macro("AG_PARSE", + "%s%s(%s)", VOIDB, pname.pointer(), voidWord); + } + if (auto_init) { + set_my_macro("AG_INITIALIZE", "%s(%s)", iname.pointer(), pcbArg.pointer()); + } + else { + set_my_macro("AG_INITIALIZE", "%s", ""); + } + + actual_stack_size = stack_size + parser_stack_size/2; + LOGV(parser_stack_size); + LOGV(actual_stack_size); + if (parser_stack_size > actual_stack_size) { + actual_stack_size = parser_stack_size; + } + set_my_macro("AG_PARSER_STACK_SIZE", "%d", actual_stack_size); + + if ((int) grammar_type != void_token_type) { + cs = grammar_type->pointer(); + wpe("\n%s %s_value(%s);\n\n", + cs, pname.pointer(), thisArg.pointer()); + } + if (input_values) { + define_macro("INPUT_VALUE(type)", "*(type *) &(PCB).input_value"); + } + if (Cast::nWrappers) { + wpe("static void ag_delete_wrappers(%s);\n", thisArg.pointer()); + wpe("#ifndef DELETE_WRAPPERS\n" + "#define DELETE_WRAPPERS ag_delete_wrappers(%s)\n" + "#endif\n", pcbArg.pointer()); + } + int token_names_printed = 0; + if (token_names || token_names_only) { + print_token_names(pname.pointer()); + token_names_printed = 1; + } + LOGS("First token_names call point"); + wps("\n"); + writeEmbeddedC(); + + if (!case_sensitive) { + if (iso_latin_1) { + write_code_segment("toupper latin"); + } + else { + write_code_segment("toupper"); + } + } + else { + define_macro_default("CONVERT_CASE(c)", "(c)"); + } + define_macro_default("TAB_SPACING", "%d", tab_spacing); + + if ((int) grammar_type != void_token_type) { + cs = grammar_type->pointer(); + char wrapperBuf[200]; + sprintf(wrapperBuf, "AgObjectWrapper< %s >", cs); + char buf[200]; + const char *ws = grammar_type.wrapperRequired() ? wrapperBuf : cs; + //sprintf(buf, stack_location, cs); + sprintf(buf, stack_location, ws); + wpe(code_segment("value proc").pointer(), + cs, pname.pointer(), thisArg.pointer(), + cs, buf); + } + LOGS("begin scanning auto procs"); + Each<Procedure> proc; + for (proc.restart(); proc.loopNotFinished(); proc.getNext()) { + LOGV(proc) LCV(proc->form_number); + if (Rule(proc->form_number)->not_unique_reduction) { + continue; + } + if (allow_macros) { + proc->alias = aliasReductionProc(proc); + } + } + + LOGS("second scan of auto procs"); + + for (proc.restart(); proc.loopNotFinished(); proc.getNext()) { + unsigned j; + char *fb, *nlp, *scp; + int single_line; + int length; + const char *lp, *rp; + int line; + AgString ns; + + if (proc->alias) { + continue; + } + ns = proc_name_string(proc); + LOGV(proc) LCV(ns); + length = proc->cSegment.length(); + + LOGV(proc->value_flag) LCV(allow_macros); + fb = (char *) proc->cSegment.begin; + if (proc->value_flag && allow_macros && Cast::nWrappers == 0) { + Rule rule(proc->form_number); + int bias = rule->op_bias; + LOGV(rule) LCV(bias); + wpe("\n#define %s(%s", + ns.pointer(), reentrant_parser? "PCB_POINTER" : ""); + cs = reentrant_parser ? ", " : ""; + //AgArray<RuleElement> &elementList = Rule(proc->form_number)->elementList; + AgArray<RuleElement> elementList = bias ? rule->hostElementList : rule->elementList; + for (j = 0; j < elementList.size(); j++) { + RuleElement &element = elementList[j]; + if (element.cVariable == 0) { + continue; + } + wpe("%s%s", cs, cVariableList[element.cVariable].pointer()); + cs = ", "; + } + wpe(")"); + if (length) { + wpe(" ("); + while(length--) { + if (*fb == '\n') { + pe_line_count++; + parserWriteError = fputc('\\', pe_file); + } + parserWriteError = fputc(*fb++, pe_file); + } + wpe(")"); + } + wpe("\n"); + continue; + } + LOGV(proc->value_flag); + if (proc->value_flag) { + define_proc(proc, allow_macros && Cast::nWrappers, thisArg, thisArgc); + cs = (const char *) proc->cSegment.begin; + line = proc->cSegment.line; + length = proc->cSegment.length(); + while (*cs == '\n') {line++; cs++; length--;} + if (line_numbers) { + wpe("#line %d \"%s\"\n", line, ln_file_name.pointer()); + } + else { + wpe("/* Line %d, %s */\n", line, ln_file_name.pointer()); + } + if (proc->cast != void_token_type) { + parserWriteError = fprintf(pe_file, " return "); + } + else { + parserWriteError = fprintf(pe_file, " "); + } + while (*cs == ' ') { + cs++; + length--; + } + if (length && fwrite(cs,length,1,pe_file) == 0) { + parserWriteError = EOF; + } + count_pe_line(cs,length); + wpe(";\n"); + if (line_numbers) { + wpe("#line %d \"%s\"\n", pe_line_count+2, ln_pe_name.pointer()); + } + wpe("}\n"); + continue; + } + + nlp = strchr(fb,'\n'); + if (nlp == NULL) { + nlp = fb + length; + } + char saveChar = fb[length]; + fb[length] = 0; + scp = strrchr(fb,';'); + fb[length] = saveChar; + if (scp == NULL) { + scp = fb + length; + } + single_line = allow_macros && (scp - fb <= nlp - fb); + while (*fb == ' ' && length) { + fb++; + length--; + } + if (single_line) { + single_line = (strncmp(fb, "return", 6)==0); + } + if (single_line) { + fb += 6; + length -= 6; + while (*fb == ' ' && length) { + fb++; + length--; + } + if (scp-fb < length) { + length = (int) (scp-fb); + } + single_line = (length > 0); + } + else if (allow_macros && length < (nlp - fb)) { + char *p = fb; + int k = length-6; + while (k >= 0) { + if (strncmp(p, "return", 6)== 0) { + break; + } + p++; + k--; + } + if (k == 0) { + proc->cast = void_token_type; + single_line = 1; + } + } + if (single_line && Cast::nWrappers == 0) { + if (proc->cast == void_token_type) { + lp = "{", rp = "}"; + } + else if (proc->cSegment.length()) { + lp = "(", rp = ")"; + } + else { + lp = rp = ""; + } + proc->macro_flag = 1; + wpe("\n#define %s(%s", + ns.pointer(), reentrant_parser? "PCB_POINTER" : ""); + cs = reentrant_parser ? ", " : ""; + Rule rule(proc->form_number); + int bias = rule->op_bias; + AgArray<RuleElement> elementList = bias ? rule->hostElementList : rule->elementList; + for (j = 0; j < elementList.size(); j++) { + RuleElement &element = elementList[j]; + if (element.cVariable == 0) { + continue; + } + wpe("%s%s", cs, cVariableList[element.cVariable].pointer()); + cs = ", "; + } + wpe(") %s",lp); + if (length && fwrite(fb,length,1,pe_file) == 0) { + parserWriteError = EOF; + } + count_pe_line(fb, length); + wpe("%s\n", rp); + continue; + } + define_proc(proc, single_line && Cast::nWrappers, thisArg, thisArgc); + cs = (const char *) proc->cSegment.begin; + line = proc->cSegment.line; + length = proc->cSegment.length(); + while (*cs == '\n') { + line++; + cs++; + length--; + } + if (line_numbers) { + wpe("#line %d \"%s\"\n", line, ln_file_name.pointer()); + } + else { + wpe("/* Line %d, %s */\n", line, ln_file_name.pointer()); + } + int segLength = proc->cSegment.length(); + if (segLength && fwrite(cs,segLength,1,pe_file) == 0) { + parserWriteError = EOF; + } + count_pe_line(cs, proc->cSegment.length()); + wpe("\n"); + if (line_numbers) { + wpe("#line %d \"%s\"\n", pe_line_count+2, ln_pe_name.pointer()); + } + wpe("}\n"); + } + AgStringDictionary reductionProcedures; + rproc = local_array(nforms_base+1, unsigned); + nrproc = 0; + rproc[0] = 0; + LOGS("Starting to build reduction procedures"); + for (i = 1; i<= nforms_base; i++) { + Rule rule(i); + Procedure proc = rule->proc_name; + rproc[i] = 0; + LOGV(rule) LCV(proc) LCV(proc.isNotNull()); + if (proc.isNotNull()) { + int bias; + if (proc->alias) { + proc = proc->alias; + } + ics(); + const char *closure = "; "; + LOGV(rule->not_unique_reduction) LCV(proc->cast); + if (rule->not_unique_reduction) { + if (reentrant_parser) { + apprintf("ag_default(PCB_POINTER, &ag_rtt[%d]); ", rtkn_ndx[i]); + } + else { + apprintf("ag_default(&ag_rtt[%d]); ", rtkn_ndx[i]); + } + } + Cast newValueType = proc->cast; + unsigned deleteIndex = 0; + if (proc->cast != void_token_type) { + LOGV(rule->elementList.size()); + int ruleLength = rule->elementList.size(); + Cast oldValueType = ruleLength ? rule->elementList[0].token->value_type : 0; + const char *format = stack_result; + char buf[1000]; + if (newValueType.wrapperRequired()) { + deleteIndex = 1; + if (ruleLength && oldValueType.wrapperRequired()) { + //sprintf(buf,"VRO((AgObjectWrapper<%s > *), ", oldValueType->pointer()); + sprintf(buf,"VRO(AG_WRAP_%d *, ", (int) oldValueType); + format = buf; + } + else { + format = "VNO AG_WRAP_%d("; + } + closure = "); "; + //apprintf(format, newValueType->pointer()); + apprintf(format, (int)newValueType); + } + else if (ruleLength && oldValueType.wrapperRequired()) { + char buf[1000]; + sprintf(buf, format, newValueType->pointer()); + //apprintf("%sVDO((AgObjectWrapper<%s > *), ", buf, oldValueType->pointer()); + apprintf("%sVDO(AG_WRAP_%d *, ", buf, (int) oldValueType); + closure = "); "; + deleteIndex = 1; + } + else apprintf(format, newValueType->pointer()); + } + LOGV(proc_name_string(proc)); + ass(proc_name_string(proc).pointer()); + if (reentrant_parser) { + ass("(PCB_POINTER"); + cs = ", "; + } + else { + acs('('); + cs = ""; + } + bias = rule->op_bias; + LOGV(bias); + AgArray<RuleElement> elementList = bias ? rule->hostElementList : rule->elementList; + int nWraps = 0; + for (j = 0; j < elementList.size(); j++) { + RuleElement &element = elementList[j]; + if (element.cVariable == 0) continue; + Cast cn = element.token->value_type; + ass(cs); + const char *format = stack_value; + if (cn.wrapperRequired()) { + //format = "VW(%d,(AgObjectWrapper<%s > *))"; + apprintf("VW(%d, AG_WRAP_%d *)", j-bias, (int) cn); + //if (j) nWraps++; + if (j >= deleteIndex) nWraps++; + } + else { + apprintf(format, j-bias,cn->pointer()); + } + cs = ", "; + } + apprintf(")%s", closure); //;\n "); + LOGV(nWraps) LCV(Cast::nWrappers); + LOGV(rule->op_bias); + int newlineRequired = 1; + if (nWraps && rule->op_bias <= 0) { + + //j = newValueType.wrapperRequired() ? 1 : 0; + //j = 1; + j = deleteIndex; + for (; j < elementList.size(); j++) { + RuleElement &element = elementList[j]; + //if (element.cVariable == 0) continue; + Cast cn = element.token->value_type; + if (cn.wrapperRequired()) { + if (newlineRequired) { + newlineRequired = 0; + ass("\n "); + } + LOGV(j) LCV(cn->pointer()); + //apprintf("VWD(%d,AgObjectWrapper<%s > *); ", j,cn->pointer()); + apprintf("VWD(%d, AG_WRAP_%d *); ", j, (int) cn); + } + } + } + ass("break;\n"); + rproc[i] = reductionProcedures << buildAgString(); + nrproc = i; + } + else { // no reduction + ics(); + int k = 0; + unsigned j = 0; + Cast primaryTokenType = rule->prim_tkn->value_type; + if (rule->elementList.size() + && (int) rule->elementList[0].token->value_type == primaryTokenType){ + j = 1; + } + for (; j < rule->elementList.size(); j++) { + RuleElement &element = rule->elementList[j]; + Cast cn = element.token->value_type; + if (cn.wrapperRequired()) { + //apprintf("VWD(%d,AgObjectWrapper<%s > *); ", j,cn->pointer()); + apprintf("VWD(%d,AG_WRAP_%d *); ", j, (int) cn); + k++; + } + } + if (k) { + ass("break;\n"); + rproc[i] = reductionProcedures << buildAgString(); + nrproc = i; + } + else { + rcs(); + } + } + } + wpe("\n\n"); + + { + //AgString code; + AgString ar_defs; + + if (typedef_name != NULL) { + unsigned pn = 0; + unsigned last_enum = 0; + const char *new_line = ",\n "; + const char *head = "typedef enum {\n"; + headerWriteError = fprintf(h_file, head); + kw = 0; + cs = " "; + for (i = 0; i++ < ntkns;) { + if (map_token_number[i].junky) { + continue; + } + tn = map_token_number[i].token_name; + if (tn == 0) { + continue; + } + last_enum = i; + template_string(Symbol(tn)->string.pointer(), + enum_name.pointer(), '%'); + char *p = string_base; + while (*p) { + if (*p == ' ') { + *p = '_'; + } + p++; + } + if (i != pn + 1 || i== 1) { + apprintf(" = %d", i); + } + pn = i; + if (kw + tis() + 2 >= parserLineLength) { + kw = 0; + cs = new_line; + } + headerWriteError = fputs(cs, h_file); + kw += 2+fps(h_file); + cs = ", "; + } + if (last_enum < 256 && ntkns >= 256) { + template_string("_last", enum_name.pointer(), '%'); + apprintf(" = %d", ntkns); + if (kw + tis() + 2 >= parserLineLength) { + cs = new_line; + } + headerWriteError = fputs(cs,h_file); + fps(h_file); + } + headerWriteError = fprintf(h_file,"\n} %s;\n\n", token_type.pointer()); + + } + //code = code_segment("pcb").pointer(); + AgString pcbHeader = code_segment("pcbHeader"); + LOGV(pcbHeader); + LOGV(token_type) LCV(itt) LCV(actual_stack_size) LCV(vst); + headerWriteError = fprintf(h_file, pcbHeader.pointer(), + structName.pointer(), + token_type.pointer(), + itt.pointer(), + actual_stack_size, vst.pointer(), + actual_stack_size); + + LOGV(context_type.exists()); + if (context_type.exists()) { + LOGV(context_type); + headerWriteError = fprintf(h_file, " %s input_context;\n %s cs[%d];\n", + context_type.pointer(), + context_type.pointer(), + actual_stack_size); + } + + LOGV(bt); + if (bt) { + headerWriteError = fprintf(h_file, " int bts[%u], btsx;\n", + actual_stack_size); + } + + LOGV(auto_resynch); + if (auto_resynch) { + const char *ns = near_functions ? "near * near" : "*"; + if (reentrant_parser) { + headerWriteError = + fprintf(h_file, " int (%s %s*gt_procs)(struct %s *);\n" + " int (%s %s*r_procs)(struct %s *);\n" + " int (%s %s*s_procs)(struct %s *);\n", + ns, constWord, structName.pointer(), + ns, constWord, structName.pointer(), + ns, constWord, structName.pointer()); + } + else { + headerWriteError = + fprintf(h_file, " int (%s %s *gt_procs)(%s);\n" + " int (%s %s*r_procs)(%s);\n" + " int (%s %s*s_procs)(%s);\n", + ns, constWord, void_string, + ns, constWord, void_string, + ns, constWord, void_string); + } + } + + if (pointer_input) { + LOGV(pointer_type); + headerWriteError = + fprintf(h_file, " %s pointer;\n %s la_ptr;\n", + pointer_type.pointer(), pointer_type.pointer()); + } + else if (max_key_length) { + headerWriteError = + fprintf(h_file, " int lab[%d], rx, fx;\n", max_key_length+1); + } + + if (Keyword::count() > 1) { + headerWriteError = fprintf(h_file, + " const unsigned char *key_sp;\n" + " int save_index, key_state;\n"); + } + + if (auto_resynch) { + if (event_driven) { + ar_defs = code_segment("auto resynch event defs"); + } + else { + ar_defs = code_segment("auto resynch defs"); + } + headerWriteError = fprintf(h_file, ar_defs.pointer()); + } + if (diagnose_errors) { + headerWriteError = fprintf(h_file, " char ag_msg[82];\n"); + } + if (semantic_productions) { + headerWriteError = + fprintf(h_file, code_segment("reduce loop vars").pointer()); + } + LOGV(cbt); + if (auto_resynch) { + headerWriteError = fprintf(h_file, " int ag_resynch_active;\n"); + } + writePCBExtensions(); + headerWriteError = + fprintf(h_file, code_segment("pcbTail").pointer(), cbt.pointer()); + + if (declare_pcb && !reentrant_parser) { + headerWriteError = + fprintf(h_file, "\nextern %s %s_pcb;\n",cbt.pointer(),pname.pointer()); + } + } + if (!really_old_style) { + AgString arg = reentrant_parser ? subs_template(cbt.pointer(), "$ *", '$') + : AgString("void"); + //AgString arg = reentrant_parser ? "PCB_TYPE *" : "void"; + headerWriteError = + fprintf(h_file, "void init_%s(%s);\n", pname.pointer(), arg.pointer()); + headerWriteError = + fprintf(h_file, "void %s(%s);\n", pname.pointer(), arg.pointer()); + if ((int) grammar_type != void_token_type) { + cs = grammar_type->pointer(); + headerWriteError = + fprintf(h_file, "\n%s %s_value(%s);\n", + cs, pname.pointer(), arg.pointer()); + } + } + else { + LOGV(pname); + headerWriteError = fprintf(h_file, "init_%s();\n", pname.pointer()); + headerWriteError = fprintf(h_file, "%s();\n", pname.pointer()); + if ((int) grammar_type != void_token_type) { + cs = grammar_type->pointer(); + LOGV(cs); + headerWriteError = + fprintf(h_file, "\n%s %s_value();\n", cs, pname.pointer()); + } + } + headerWriteError = fprintf(h_file, "#endif\n\n"); + LOGV(error_trace); + if (error_trace) { + set_my_macro("AG_TRACE_FILE", "\"%s.etr\"", simple_file_name.pointer()); + set_my_macro("AG_TRACE_ERROR", + reentrant_parser ? "ag_trace_error(PCB_POINTER);" : + "ag_trace_error();"); + write_code_segment("error trace"); + } + else { + set_my_macro("AG_TRACE_ERROR","%s", ""); + } + write_header(pname.pointer()); + set_my_macro("AG_INPUT_TYPE", "%s", itt.pointer()); + set_my_macro("AG_TOKEN_TYPE", "%s", token_type.pointer()); + + set_my_macro("AG_SAVE_CONTEXT", context_type.exists()?"GET_CONTEXT;" : ""); + set_my_macro("AG_VALUE_STACK_TYPE", vst.pointer()); + cs = vs = "(PCB).input_code"; + //if (key_dict->nsx > 1) vs = cs = "*(PCB).lab"; + if (Keyword::count() > 1) { + vs = cs = "*(PCB).lab"; + } + if (pointer_input) { + vs = cs = "*(PCB).pointer"; + } + ssprintf(stack_location, Cast(input_token_type)->pointer()); + //csp = build_string(); + AgString leftSide = buildAgString(); + if (input_values) { + if (!pointer_input) { + vs = "(PCB).input_value"; + } + set_my_macro("AG_INPUT_VALUE", vs); + set_my_macro("AG_GET_VALUE", "%s = %s;", leftSide.pointer(), vs); + } + else { + set_my_macro("AG_GET_VALUE", "%s = %s;", leftSide.pointer(), vs); + } + if (pointer_input) { + set_my_macro("AG_INPUT_CODE", "INPUT_CODE((%s))", cs); + } + else { + set_my_macro("AG_INPUT_CODE", "(%s)", cs); + } + + define_my_macros("declare macros"); + set_my_macro("AG_NULL", "(PCB).vs[(PCB).ssx] = ag_null_value;"); + write_code_segment("declarations"); + const char *nullInitializer; + if (typeList.size() == 1 && typeList[0] == int_token_type) { + nullInitializer = "0"; + } + else { + nullInitializer = "{ 0 }"; + } + LOGV(nullInitializer); + wpe("#ifndef NULL_VALUE_INITIALIZER\n" + "#define NULL_VALUE_INITIALIZER = %s\n" + "#endif\n\n", nullInitializer); + LOGV(Cast::nWrappers); + if (Cast::nWrappers) { + wpe("\nstatic %schar %sag_wdf[] = {\n ", constWord, LOCUS); + kw = 2; + cs = ""; + for (kits = 0; kits < nits; kits++) { + Token token = map_state_number[kits].char_token; + Cast valueType = token->value_type; + if (kw + 4 > parserLineLength) {kw = 2; cs = ",\n ";} + //int flag = valueType.wrapperRequired(); + int flag = valueType.wrapperRequired() ? (int) valueType : 0; + kw += wpe("%s%d", cs, flag); + cs = ", "; + } + wpe("\n};\n\n"); + write_code_segment("wrap decls"); + set_my_macro("MY_DELETE_WRAPPERS", "DELETE_WRAPPERS;"); + for (Each<Cast> cast; cast.loopNotFinished(); cast.getNext()) { + if (!cast.wrapperRequired()) { + continue; + } + wpe("#undef AG_WRAP_%d\n" + "#define AG_WRAP_%d AgObjectWrapper<%s >\n", + (int) cast, (int) cast, cast->name.pointer()); + } + const char *derailer = auto_resynch ? + " if ((PCB).ag_resynch_active) return;\n" + " (PCB).ag_resynch_active = 1;\n" + : ""; + + wpe("\nstatic void ag_delete_wrappers(%s) {\n" + "%s" + " int sn = (PCB).sn;\n" + " int sx = (PCB).ssx;\n" + " while (sx--) {\n" + " switch (ag_wdf[sn]) {\n", + thisArg.pointer(), derailer); + for (Each<Cast> c; c.loopNotFinished(); c.getNext()) { + if (!c.wrapperRequired()) continue; +/* + wpe(" case %d: {\n" + " AgObjectWrapper<%s > *wrapper = (AgObjectWrapper<%s > *) (&(PCB).vs[sx]);\n" + " delete wrapper;\n" + " break;\n" + " }\n", (int) c, c.name().pointer(), c.name().pointer()); +*/ + wpe(" case %d: ag_delete_object((AG_WRAP_%d *) &(PCB).vs[sx]); break;\n", + (int) c, (int) c); + } + wpe(" default: break;\n" + " }\n" + " sn = (PCB).ss[sx];\n" + " }\n}\n\n"); +#if 0 /* BAD */ + if (error_token != 0) { + set_my_macro("DELETE_OBJECT", "ag_delete_object(%s);", pcbArg.pointer()); + wpe("void ag_delete_object(%s) {\n" + " int sn = PCB.sn;\n" + " (PCB).sn = (PCB).ss[--(PCB).ssx];\n" + " if (ag_wdf[sn]) delete (AgWrapper *) (&(PCB).vs[(PCB).ssx]);\n" + "}\n\n" + , thisArg.pointer()); + } +#endif + if (error_token != 0) { + set_my_macro("DELETE_OBJECT", "ag_delete_object(%s);", pcbArg.pointer()); + wpe("void ag_delete_object(%s) {\n" + " int sn = PCB.sn;\n" + " (PCB).sn = (PCB).ss[--(PCB).ssx];\n" + " switch (ag_wdf[sn]) {\n", thisArg.pointer()); + for (Each<Cast> c; c.loopNotFinished(); c.getNext()) { + if (!c.wrapperRequired()) { + continue; + } +/* + wpe(" case %d: delete (AgObjectWrapper<%s > *) (&(PCB).vs[(PCB).ssx]); break;\n", + (int) c, (c.name().pointer())); +*/ + wpe(" case %d: {\n" + " AG_WRAP_%d *wrapper = (AG_WRAP_%d *) (&(PCB).vs[(PCB).ssx]);\n" + " delete wrapper;\n" + " break;\n" + " }\n", + (int) c, (int) c, (int) c); + } + wpe(" default: break;\n" + " }\n}\n\n"); + } + } + else { + set_my_macro("MY_DELETE_WRAPPERS", "%s", ""); + set_my_macro("DELETE_OBJECT","(PCB).sn = (PCB).ss[--(PCB).ssx];"); + } + wpe("static %s %sag_null_value NULL_VALUE_INITIALIZER;\n", + vst.pointer(), constWord); + set_my_macro("AG_INPUT", stack_location, Cast(input_token_type)->pointer()); + + type = Procedure::count() + 1 <= 255 ? "char" : + Procedure::count() + 1 <= 65535 ? "short" : "int"; + wpe("\nstatic %sunsigned %s %sag_rpx[] = {\n ",constWord, type, LOCUS); + kw = 4; + cs = ""; + for (i = 0; i <= nrproc; i++) { + if (kw + 4 > parserLineLength) { + kw = 0; + cs = ",\n "; + } + n = rproc[i]; + kw += wpe("%s%3d", cs, n); + cs = ","; + } + wps("\n};\n"); + + //if (key_dict->nsx > 1) write_key_tables(); + if (Keyword::count() > 1) { + write_key_tables(); + } + + if (max_char_number >= min_char_number) { + + if (min_char_number) { + ssprintf(" + %d", -min_char_number); + } + else { + ics(); + } + acs(0); + int charType = 0; + if (test_range && pointer_input) { + int n = strlen(type); + char *type = pointer_type.pointer(); + char ch = '*'; + while (type[n-1] == ch) { + type[n-1] = 0; + n--; + ch = ' '; + } + if (n > 5) { + type += n - 5; + } + if (*type == ' ' || *type == '\t') { + type++; + } + charType = strcmp(type, "char") == 0; + } + if (test_range && + (!pointer_input || charType)) { + wpe("#define AG_TCV(x) (((int)(x) >= %d && (int)(x) <= %d) ? ag_tcv[(x)%s] : 0)\n", + min_char_number, max_char_number, string_base); + } + else { + wpe("\n#define AG_TCV(x) ag_tcv[(x)%s]\n",string_base); + } + rcs(); + type = ntkns <= 255 ? "char" : ntkns <= 65535 ? "short" : "int"; + wpe("\nstatic %sunsigned %s %sag_tcv[] = {\n ", constWord, type, LOCUS); + kw = 4; + cs = ""; + for (i = 0; i < n_chars; i++) { + tn = map_char_number[i].token_number; + if (kw + 4 > parserLineLength) { + kw = 0; + cs = ",\n "; + } + kw += wpe("%s%3d", cs, tn); + cs = ","; + } + wps("\n};\n\n"); + } + else if (test_range) { + wpe("#define AG_TCV(x) (((x) > 0 && (x) <= %d) ? (x) : 0)\n", ntkns); + } + else { + wpe("\n#define AG_TCV(x) (x)\n"); + } + cs = really_old_style ? "function macro defs old style" : + "function macro defs"; + define_my_macros(cs); + gen_input_code(); + + + if (bt) { + if (auto_resynch || error_token) { + set_my_macro("AG_EOF", "%d", eof_token); + } + if (error_token) { + set_my_macro("AG_ERROR", "%d", error_token); + } + csp = "backtrack on"; + cs = "backtrack on macros"; + define_my_macros(context_type.exists() ? "context macros" : + "no context macros"); + define_my_macros(error_token ? "error resynch undo" : "undo macro"); + } + else { + csp = "backtrack off"; + cs = "backtrack off macros"; + } + define_my_macros(cs); + write_code_segment(csp); + + if (rtkn_count) { + wpe("\nstatic %sint %sag_rtt[] = {\n ", constWord, LOCUS); + kw = 4; + cs = ""; + for (i = 0; i < rtkn_count; i++) { + if (kw + 4 > parserLineLength) { + kw = 0; + cs = ",\n "; + } + kw += wpe("%s%3d", cs, rtkn_list[i]); + cs = ","; + } + wps("\n};\n\n"); + } + + write_parse_table_tokens(); + write_parse_table_actions(); + write_parse_table_params(); + + fclose(h_file); + if (headerWriteError == EOF) { + errorList.push(Error("Error writing header file")); + } + LOGS("h_file closed"); + + // Up through 2.0, this was <= 255, ignoring "engine_index+1" 9 lines down. + type = max_engine_index < 255 ? "char" : + max_engine_index < 65535 ? "short" : "int"; + + wpe("\nstatic %sunsigned %s %sag_sbt[] = {\n", constWord, type, LOCUS); + kw = 8; + wps(" 0"); + cs = ","; + + LOGS("Write sbt table"); + for (i = 1; i <= nstates; i++) { + n = map_state_number[i - 1].engine_index + 1; + if (kw + 6 > parserLineLength) { + kw = 0; + cs = ",\n "; + } + kw += wpe("%s%4d", cs, n); + cs = ","; + } + wps("\n};\n\n"); + + wpe("\nstatic %sunsigned %s %sag_sbe[] = {\n",constWord, type, LOCUS); + kw = 8; + wpe(" %4d", map_state_number[0].n_terminals); + cs = ","; + + LOGS("Write sbe table"); + for (i = 1; i < nstates; i++) { + n = map_state_number[i-1].engine_index + 1 + + map_state_number[i].n_terminals; + if (kw + 6 > parserLineLength) { + kw = 0; + cs = ",\n "; + } + kw += wpe("%s%4d", cs, n); + cs = ","; + } + wpe("%s%4d", cs, map_state_number[nstates - 1].engine_index + 1); + wps("\n};\n\n"); + + LOGS("Write ag_fl table"); + wpe("\nstatic %sunsigned char %sag_fl[] = {\n ", constWord, LOCUS); + kw = 4; + cs = ""; + for (i = 0; i <= nforms_base; i++) { + if (kw + 4 > parserLineLength) { + kw = 0; + cs = ",\n "; + } + n = Rule(i)->length(); + kw += wpe("%s%1d", cs, n); + cs = ","; + } + wps("\n};\n"); + + LOGS("Write ag_ptt table"); + type = ntkns <= 255 ? "char" : ntkns <= 65535 ? "short" : "int"; + wpe("\nstatic %sunsigned %s %sag_ptt[] = {\n ", constWord, type, LOCUS); + + kw = 4; + cs = ""; + for (i = 0; i <= nforms_base; i++) { + if (kw + 4 > parserLineLength) { + kw = 0; + cs = ",\n "; + } + n = Rule(i)->prim_tkn; + kw += wpe("%s%3d", cs, n); + cs = ","; + } + wps("\n};\n\n"); + + LOGS("Define macros"); + { + define_my_macros( + auto_resynch ? "auto resynch macros" : + error_token ? "error resynch macros" : + "parse action macros"); + if (auto_resynch) { + set_my_macro("AG_RESYNCH", + reentrant_parser ? "ag_auto_resynch(PCB_POINTER);" : + "ag_auto_resynch();"); + } + define_my_macros( + semantic_productions ? "reduce macros checking" : "reduce macros"); + write_code_segment( + semantic_productions ? "reduce loop checking" : "reduce loop"); + if (semantic_productions && reduction_choices) { + write_code_segment("reduction choices"); + } + } + //wpe("\nstatic %s%sag_ra(%s)\n{\n", VOIDB, nearWord, voidWord); + wpe("\nstatic %s%sag_ra(%s)\n{\n", VOIDB, nearWord, thisArg.pointer()); + LOGS("Write ag_ra table"); + if (reductionProcedures.size() > 1) { + wpe(" switch(ag_rpx[(PCB).ag_ap]) {\n"); + for (i = 1; i < reductionProcedures.size(); i++) { + LOGV(i) LCV(reductionProcedures[i]); + wpe(" case %d: %s", i, reductionProcedures[i].pointer()); + } + wpe(" }\n"); + if (pointer_input) { + wpe(" (PCB).la_ptr = (PCB).pointer;\n"); + } + } + wpe("}\n\n"); + + if (diagnose_errors && !token_names && !token_names_printed) { + print_token_names(pname.pointer()); + } + LOGS("Second token_names call point"); + if (auto_resynch || (diagnose_errors && error_frame)) { + LOGSECTION("ag_ctn option"); + int *ip, *iq = local_array(2*nstates, int); + int maxToken = 0; + + //nf = 0; + ip = iq; + for (i = 0; i < nstates; i++) { + int token = find_ctn(i); + if (token > maxToken) { + maxToken = token; + } + *ip++ = token; + *ip++ = frameIndex; + } + ip = iq; + + type = maxToken <= 255 ? "char" : maxToken <= 65535 ? "short" : "int"; + wpe("\nstatic %sunsigned %s %sag_ctn[] = {\n", constWord, type, LOCUS); + cs = " "; + kw = 2; + for (i = 0; i < nstates; i++) { + int f; + if (kw + 6 > parserLineLength) { + kw = 0; + cs = ",\n "; + } + f = *ip++; + n = *ip++; + kw += wpe("%s%3d,%1d", cs, f, n); + cs = ","; + } + wps("\n};\n\n"); + } + LOGS("ag_ctn loop complete"); + + if (diagnose_errors) { + write_code_segment("diagnose defs"); + const char *codeSeg = character_seen ? "diagnose char" : "diagnose token"; + set_my_macro("AG_DIAGNOSE", + reentrant_parser ? "ag_diagnose(PCB_POINTER);" : + "ag_diagnose();"); + set_my_macro("AG_INIT_ERROR_MESSAGE", "%s", ""); + write_code_segment(codeSeg); + if (error_frame) { + const char *contextCode = "diagnose context"; + //if (lines_and_columns) contextCode = "diagnose context col"; + write_code_segment(contextCode); + } + wps("}\n"); + } + else { + set_my_macro("AG_DIAGNOSE", "%s", ""); + set_my_macro("AG_INIT_ERROR_MESSAGE", + "(PCB).error_message = \"Syntax Error\";"); + } + + cs = (auto_resynch || error_token) && event_driven ? + "ag_action_12_proc" : "ag_action_8_proc"; + + set_my_macro("AG_RECOVER", cs); + + write_code_segment("reduce proc defs"); + if (error_token) { + write_code_segment("reduce proc error defs"); + } + cs = error_token ? "error resynch" : + auto_resynch ? "auto resynch": NULL; + if (cs != NULL) { + set_my_macro("AG_ERROR_STATE", "%d", nstates); + if (auto_resynch) { + write_code_segment("jns proc"); + } + else if (reentrant_parser) { + set_my_macro("AG_RESYNCH", "ag_error_resynch(PCB_POINTER);"); + } + else { + set_my_macro("AG_RESYNCH", "ag_error_resynch();"); + } + sss(cs); + if (event_driven) { + ass(" token sink mode"); + } + write_code_segment(string_base); + rcs(); + } + else { + define_my_macros("no resynch"); + } + + + { + cs = "parse procs"; + if (event_driven) { + cs = "chain parse procs"; + } + write_code_segment(cs); + if (error_token) { + cs = "error token parse procs"; + if (event_driven) { + cs = "chain error token parse procs"; + } + write_code_segment(cs); + } + if (auto_resynch) { + write_code_segment("error parse procs"); + } + + cs = "parse engine"; + if (event_driven) { + cs = "chain parse engine"; + //if (key_dict->nsx > 1) { + // cs = "chain key parse engine"; + //} + if (Keyword::count() > 1) { + cs = "chain key parse engine"; + } + } + write_code_segment(cs); + } + if (cSegmentStack.size() == 0 && main_program + && !pointer_input && !event_driven && !reentrant_parser) { + wpe( + "\nint main(%s) {\n" + " %s();\n" + " return 0;\n" + "}\n", voidWord, pname.pointer()); + } + fclose(pe_file); + if (parserWriteError == EOF) { + errorList.push(Error("Error writing parser file")); + } + for (i = 1; i < my_macros->nsx; i++) { + DEALLOCATE(my_macros_subs[i]); + my_macros_subs[i] = NULL; + } + my_macros = delete_string_dict(my_macros); + syntax_state = engine_built; +} + +