|
|
1.1 root 1: /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1984. */
2: /* $Header: b2tes.c,v 1.2 84/07/05 15:01:46 timo Exp $ */
3:
4: /* B test testing */
5: #include "b.h"
6: #include "b1obj.h"
7: #include "b2key.h"
8: #include "b2env.h"
9: #include "b2syn.h"
10: #include "b2sem.h"
11:
12: #define Tnil ((string) 0)
13:
14: Forward outcome ttest(), stest(), comparison(), quant();
15:
16: Visible outcome test(q) txptr q; {
17: return ttest(q, Tnil);
18: }
19:
20: Hidden outcome ttest(q, ti) txptr q; string ti; {
21: txptr fa, ta, fo, to;
22: bool a= find(AND, q, &fa, &ta), o= find(OR, q, &fo, &to);
23: Skipsp(tx);
24: if (ti != Tnil && (a || o))
25: pprerr("use ( and ) to make AND and/or OR unambiguous after ", ti);
26: if (a && o) parerr("AND and OR intermixed, use ( and )", "");
27: if (atkw(NOT)) return !ttest(q, "NOT");
28: else if (atkw(SOME)) return quant(q, No, No, "SOME");
29: else if (atkw(EACH)) return quant(q, Yes, Yes, "EACH");
30: else if (atkw(NO)) return quant(q, Yes, No, "NO");
31: else if (a) {
32: testa: if (!stest(fa)) return No;
33: tx= ta; if (find(AND, q, &fa, &ta)) goto testa;
34: return ttest(q, Tnil);
35: } else if (o) {
36: testo: if (stest(fo)) return Yes;
37: tx= to; if (find(AND, q, &fo, &to)) goto testo;
38: return ttest(q, Tnil);
39: }
40: return stest(q);
41: }
42:
43: Hidden outcome stest(q) txptr q; {
44: bool o, lt, eq, gt; txptr tx0; value v;
45: Skipsp(tx); tx0= tx;
46: nothing(q, "test");
47: if (Char(tx) == '(') {
48: txptr tx1= ++tx, f, t;
49: req(")", q, &f, &t);
50: tx= t; Skipsp(tx);
51: if (tx < q) {tx= tx0; goto exex;}
52: tx= tx1; o= test(f); tx= t;
53: return o;
54: }
55: if (Letter(Char(tx))) {
56: value t= tag(); prd p;
57: Skipsp(tx);
58: if (tx == q) /* test consists of tag */ {
59: value *aa= lookup(t);
60: if (aa != Pnil && Is_refinement(*aa)) {
61: release(t);
62: ref_et(*aa, Rep);
63: o= resout; resout= Und;
64: return o;
65: } else if (is_zerprd(t, &p)) {
66: release(t);
67: upto(q, "zeroadic test");
68: return proposition(Vnil, p, Vnil);
69: } else
70: pprerr(
71: "tag is neither refined-test nor zeroadic-predicate", "");
72: }
73: if (is_monprd(t, &p)) {
74: release(t);
75: t= obasexpr(q);
76: upto(q, "monadic test");
77: o= proposition(Vnil, p, t); release(t);
78: return o;
79: }
80: release(t); tx= tx0;
81: }
82: exex: v= obasexpr(q); Skipsp(tx);
83: if (relop(<, &eq, >)) {
84: value w;
85: nextv: w= obasexpr(q);
86: if (!comparison(v, w, lt, eq, gt)) {
87: release(v); release(w);
88: return No;
89: }
90: release(v); v= w;
91: Skipsp(tx);
92: if (relop(<, &eq, >)) goto nextv;
93: release(v);
94: upto(q, "comparison");
95: return Yes;
96: }
97: if (Letter(Char(tx))) {
98: value t= tag(); prd p;
99: if (!is_dyaprd(t, &p))
100: pprerr("tag following expression is not a predicate", "");
101: release(t); t= obasexpr(q);
102: upto(q, "dyadic test");
103: o= proposition(v, p, t);
104: release(v); release(t);
105: return o;
106: }
107: parerr("something unexpected following expression in test", "");
108: return (bool) Dummy;
109: }
110:
111: Visible bool relop(lt, eq, gt) bool *lt, *eq, *gt; {
112: txptr tx0= tx;
113: *lt= *eq= *gt= No;
114: Skipsp(tx);
115: switch (Char(tx++)) {
116: case '<':
117: if (Char(tx) == '<') break;
118: *lt= Yes;
119: if (Char(tx) == '=') {
120: tx++; *eq= Yes;
121: } else if (Char(tx) == '>') {
122: tx++; *gt= Yes;
123: }
124: break;
125: case '=':
126: *eq= Yes; break;
127: case '>':
128: if (Char(tx) == '<' || Char(tx) == '>') break;
129: *gt= Yes;
130: if (Char(tx) == '=') {
131: tx++; *eq= Yes;
132: }
133: break;
134: default:
135: break;
136: }
137: if (*lt || *eq || *gt) return Yes;
138: tx= tx0; return No;
139: }
140:
141: Visible outcome comparison(v, w, lt, eq, gt) value v, w; bool lt, eq, gt; {
142: relation c= compare(v, w);
143: return c < 0 ? lt : c == 0 ? eq : gt;
144: }
145:
146: Hidden outcome quant(q, all, each, qt) txptr q; bool all, each; string qt; {
147: /* it is assumed that xeq == Yes */
148: env e0= curnv; bool in= No, par= No, go_on= Yes; loc l; value v, w;
149: txptr ftx, ttx, utx, vtx;
150: reqkw(HAS, &utx, &vtx);
151: if (vtx > q) parerr("HAS follows colon", "");
152: /* as in: SOME i IN x: SHOW i HAS a */
153: if (find(IN_quant, vtx, &ftx, &ttx)) in= Yes;
154: if (find(PARSING, vtx, &ftx, &ttx)) par= Yes;
155: if (!in && !par) parerr("neither IN nor PARSING found", "");
156: if (in && par) parerr("you're kidding; both IN and PARSING", "");
157: l= targ(ftx);
158: if (!(Is_simploc(l) && !par || Is_compound(l)))
159: pprerr("inappropriate identifier after ", qt);
160: bind(l);
161: tx= ttx; v= expr(utx);
162: if (par) {
163: if (!Is_text(v))
164: error("in i1, ... , in PARSING t, t is not a text");
165: part(Length(l), l, 0, v, 0, utx, vtx, &go_on, each, q, qt);
166: } else {
167: value k, k1, len;
168: if (!Is_tlt(v))
169: error("in SOME/EACH/NO i IN t, t is not a text, list or table");
170: len= size(v);
171: k= copy(one);
172: while (go_on && compare(k, len) <= 0) {
173: tx= utx;
174: w= th_of(k, v);
175: put(w, l); release(w);
176: tx= vtx;
177: go_on= each == (ttest(q, qt) == Succ);
178: k= sum(k1= k, one); release(k1);
179: }
180: release(k); release(len);
181: }
182: release(v); release(l); restore_env(e0);
183: return go_on == all ? Succ : Fail;
184: }
185:
186: Hidden part(n, l, f, v, B, utx, vtx, go_on, each, q, qt)
187: intlet n; loc l, v; intlet f, B;
188: txptr utx, vtx; bool *go_on, each; txptr q; string qt; {
189: intlet r= length(v)-B, k; value w;
190: for (k= n == 1 ? r : 0; *go_on && k <= r; k++) {
191: tx= utx;
192: w= trim(v, B, r-k);
193: put(w, *field(l, f)); release(w);
194: if (n == 1) {
195: tx= vtx;
196: *go_on= each == (ttest(q, qt) == Succ);
197: } else part(n-1, l, f+1, v, B+k, utx, vtx, go_on, each, q, qt);
198: }
199: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.