2
/******************************************************************************
3
* MODULE : math_language.cpp
4
* DESCRIPTION: mathematical languages
5
* COPYRIGHT : (C) 1999 Joris van der Hoeven
6
*******************************************************************************
7
* This software falls under the GNU general public license and comes WITHOUT
8
* ANY WARRANTY WHATSOEVER. See the file $TEXMACS_PATH/LICENSE for more details.
9
* If you don't have this file, write to the Free Software Foundation, Inc.,
10
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
11
******************************************************************************/
13
#include "language.hpp"
14
#include "analyze.hpp"
15
#include "Languages/hyphenate.hpp"
16
#include "Languages/impl_language.hpp"
19
/******************************************************************************
20
* Mathematical languages
21
******************************************************************************/
23
struct math_language_rep: language_rep {
24
hashmap<string,text_property_rep> tpr_class;
25
hashmap<string,text_property_rep> tpr_member;
26
string class_name; // current type name
27
bool class_def; // in class definition phase
29
math_language_rep (string name, string s);
30
string get_string (string s, int& i);
31
void get_class (string s, int& i);
32
void get_members (string s, int& i);
33
void get_type (string s, int& i);
34
void get_precedence (string s, int& i);
35
void get_lpenalty (string s, int& i);
36
void get_rpenalty (string s, int& i);
37
void get_spacing (string s, int& i);
38
void get_limits (string s, int& i);
40
void skip_spaces (string s, int& pos, space fn_spc, space& spc);
41
string next_word (string s, int& pos);
42
text_property advance (string s, int& pos);
43
array<int> get_hyphens (string s);
44
void hyphenate (string s, int after, string& left, string& right);
47
/******************************************************************************
48
* Load a mathematical language
49
******************************************************************************/
52
math_language_rep::get_string (string s, int& i) {
53
while ((i<N(s)) && (s[i]!=' ') && (s[i]!='\t') && (s[i]!='\n')) i++;
54
while ((i<N(s)) && ((s[i]==' ') || (s[i]=='\t') || (s[i]=='='))) i++;
56
while ((i<N(s)) && (s[i]!='\n')) i++;
58
while ((end>start) && ((s[end-1]==' ') || (s[end-1]=='\t'))) end--;
59
// cout << "String= " << s (start, end) << "\n";
60
return s (start, end);
64
math_language_rep::get_class (string s, int& i) {
65
class_name= get_string (s, i);
70
math_language_rep::get_members (string s, int& i) {
71
class_name= get_string (s, i);
73
// cout << "Members " << class_name << "\n";
77
math_language_rep::get_type (string s, int& i) {
79
string r= get_string (s, i);
80
int &ot= tpr_class(class_name).op_type;
81
if (r == "Symbol") ot= OP_SYMBOL;
82
else if (r == "Prefix") ot= OP_PREFIX;
83
else if (r == "Postfix") ot= OP_POSTFIX;
84
else if (r == "Infix") ot= OP_INFIX;
85
else if (r == "Left Associative Infix") ot= OP_LEFT_ASS_INFIX;
86
else if (r == "Right Associative Infix") ot= OP_RIGHT_ASS_INFIX;
87
else if (r == "Associative Infix") ot= OP_ASS_INFIX;
88
else if (r == "Opening Bracket") ot= OP_OPENING_BRACKET;
89
else if (r == "Separator") ot= OP_SEPARATOR;
90
else if (r == "Closing Bracket") ot= OP_CLOSING_BRACKET;
92
cerr << "Attempt to associate type " << r
93
<< " to " << class_name << "\n";
94
fatal_error ("Unknown type", "math_language_rep::get_type");
97
else fatal_error ("Type declaration outside class definition",
98
"math_language_rep::get_type");
102
math_language_rep::get_precedence (string s, int& i) {
103
if (class_def) tpr_class(class_name).priority= as_int (get_string (s, i));
104
else fatal_error ("Precedence declaration outside class definition",
105
"math_language_rep::get_precedence");
109
math_language_rep::get_lpenalty (string s, int& i) {
111
string r= get_string (s, i);
112
if (r == "Panic") tpr_class(class_name).pen_before= HYPH_PANIC;
113
if (r == "Invalid") tpr_class(class_name).pen_before= HYPH_INVALID;
114
else tpr_class(class_name).pen_before= as_int (r);
116
else fatal_error ("Left Penalty declaration outside class definition",
117
"math_language_rep::get_lpenalty");
121
math_language_rep::get_rpenalty (string s, int& i) {
123
string r= get_string (s, i);
124
if (r == "Panic") tpr_class(class_name).pen_after= HYPH_PANIC;
125
if (r == "Invalid") tpr_class(class_name).pen_after= HYPH_INVALID;
126
else tpr_class(class_name).pen_after= as_int (r);
128
else fatal_error ("Right Penalty declaration outside class definition",
129
"math_language_rep::get_rpenalty");
133
math_language_rep::get_spacing (string s, int& i) {
136
string both= get_string (s, i);
137
for (j=0; j<N(both); j++)
139
string l= both (0, j);
140
string r= both (j+1, N(both));
141
while ((N(l)>0) && ((l[N(l)-1] == ' ') || (l[N(l)-1] == '\t')))
143
while ((N(r)>0) && ((r[0]==' ') || (r[0]=='\t'))) r= r(1, N(r));
145
tpr_class(class_name).spc_before= SPC_NONE;
146
else if (l == "Default")
147
tpr_class(class_name).spc_before= SPC_OPERATOR;
149
tpr_class(class_name).spc_before= SPC_BIGOP;
151
cerr << "Attempt to associate space " << l
152
<< " to " << class_name << "\n";
153
fatal_error ("Unknown space", "math_language_rep::get_type");
156
tpr_class(class_name).spc_after= SPC_NONE;
157
else if (r == "Default")
158
tpr_class(class_name).spc_after= SPC_OPERATOR;
160
tpr_class(class_name).spc_after= SPC_BIGOP;
162
cerr << "Attempt to associate space " << r
163
<< " to " << class_name << "\n";
164
fatal_error ("Unknown space", "math_language_rep::get_type");
168
fatal_error ("Missing comma in Spacing declaration",
169
"math_language_rep::get_spacing");
171
else fatal_error ("Spacing declaration outside class definition",
172
"math_language_rep::get_spacing");
176
math_language_rep::get_limits (string s, int& i) {
178
string l= get_string (s, i);
179
if (l == "Display") tpr_class(class_name).limits= LIMITS_DISPLAY;
180
else if (l == "Always") tpr_class(class_name).limits= LIMITS_ALWAYS;
181
else tpr_class(class_name).limits= LIMITS_NONE;
183
else fatal_error ("Limits declaration outside class definition",
184
"math_language_rep::get_limits");
187
math_language_rep::math_language_rep (string name, string s):
188
language_rep (name, math_enc),
189
tpr_class (text_property_rep ()),
190
tpr_member (text_property_rep ()),
191
class_name ("symbol"), class_def (true)
193
language::instances (name)= (pointer) this;
194
tpr_class("symbol").op_type = OP_SYMBOL;
195
tpr_class("symbol").priority= 1000;
198
for (i=0; i<N(s); i++) {
199
while ((i<N(s)) && ((s[i]==' ') || (s[i]=='\t'))) i++;
200
if ((i+5<N(s)) && (s(i,i+5)=="Class")) get_class (s, i);
201
else if ((i+7<N(s)) && (s(i,i+7)=="Members")) get_members (s, i);
202
else if ((i+4<N(s)) && (s(i,i+4)=="Type")) get_type (s, i);
203
else if ((i+10<N(s)) && (s(i,i+10)=="Precedence")) get_precedence (s, i);
204
else if ((i+12<N(s)) && (s(i,i+12)=="Left-Penalty")) get_lpenalty (s, i);
205
else if ((i+7<N(s)) && (s(i,i+7)=="Penalty")) get_rpenalty (s, i);
206
else if ((i+13<N(s)) && (s(i,i+13)=="Right-Penalty")) get_rpenalty (s, i);
207
else if ((i+7<N(s)) && (s(i,i+7)=="Spacing")) get_spacing (s, i);
208
else if ((i+6<N(s)) && (s(i,i+6)=="Limits")) get_limits (s, i);
209
else if ((i+2<N(s)) && (s(i,i+2)=="##")) (void) get_string (s, i);
211
while ((i<N(s)) && (s[i]!='\n')) {
212
while ((i<N(s)) && ((s[i]==' ') || (s[i]=='\t'))) i++;
214
while ((i<N(s)) && (s[i]!=' ') && (s[i]!='\t') && (s[i]!='\n')) i++;
215
string symbol= s (start, i);
217
(class_def || (class_name != "operator-with-limits")))
218
symbol= "<" * symbol * ">";
219
// cout << " Member: " << symbol << "\n";
220
if ((!class_def) && (tpr_class->contains (class_name)))
221
tpr_member (symbol)= tpr_class [class_name];
223
cerr << "Attempt to insert " << symbol
224
<< " to class " << class_name << "\n";
226
fatal_error ("Member declaration inside class definition",
227
"math_language_rep::get_members");
229
fatal_error ("Unknown class",
230
"math_language_rep::get_members");
237
/******************************************************************************
239
******************************************************************************/
242
math_language_rep::next_word (string s, int& pos) {
245
if (pos>=N(s)) return string ("");
247
if ((s[pos]>='0') && (s[pos]<='9')) {
248
while ((pos<N(s)) && is_numeric (s[pos])) pos++;
249
while (s[pos-1]=='.') pos--;
250
return s (start, pos);
253
if (is_alpha (s[pos])) {
254
while ((pos<N(s)) && (is_alpha (s[pos]))) pos++;
255
return s (start, pos);
259
while ((pos<N(s)) && (s[pos]!='>')) pos++;
261
return s (start, pos);
265
return s (start, pos);
269
math_language_rep::advance (string s, int& pos) {
272
((pos>=2) && is_alpha (s[pos-2]) && is_alpha (s[pos-1]));
273
string r= next_word (s, pos);
277
(((pos+2)<N(s)) && is_alpha (s[pos]) && is_alpha (s[pos+1]));
278
if (op_flag1 || op_flag2) return &tp_operator_rep;
279
else return &tp_shortop_rep;
281
return &tpr_member(r);
283
/****************************** variant *******************************
284
string r= next_word (s, pos);
285
if (r == " ") return &tp_operator_rep;
286
else return &tpr_member(r);
287
**********************************************************************/
290
/******************************************************************************
292
******************************************************************************/
295
math_language_rep::get_hyphens (string s) {
297
fatal_error ("hyphenation of empty string",
298
"math_language_rep::get_hyphens");
301
bool flag= is_numeric (s);
302
array<int> penalty (n);
303
for (i=0; i<n; i++) penalty[i]= (flag? HYPH_PANIC: HYPH_INVALID);
304
if (n>0) penalty[0]= penalty[n-1]= HYPH_INVALID;
305
if (n>2) penalty[1]= penalty[n-2]= HYPH_INVALID;
306
if (n>4) penalty[2]= penalty[n-3]= HYPH_INVALID;
311
math_language_rep::hyphenate (string s, int after, string& left, string& right)
313
left = s (0, after+1) * string ("\\");
314
right= s (after+1, N(s));
317
/******************************************************************************
319
******************************************************************************/
322
math_language (string name) {
323
if (language::instances -> contains (name)) return language (name);
324
string s, fname= name * ".syx";
325
if (DEBUG_AUTO) cout << "TeXmacs] Loading " << fname << "\n";
326
load_string (url ("$TEXMACS_SYNTAX_PATH", fname), s, true);
327
return new math_language_rep (name, s);