Mercurial > ~dholland > hg > ag > index.cgi
view anagram/agcore/bpe3.cpp @ 14:a02e9434072e
Fix friend declaration for gcc10.
XXX: did not check it against the IBM compiler, might end up needing
XXX: to be conditional.
author | David A. Holland |
---|---|
date | Tue, 31 May 2022 00:59:42 -0400 |
parents | 13d2b8934445 |
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. * * 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; }