om2ir.red 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472
  1. omfuncs!*:=
  2. '((oma . (omaIR))
  3. (oms . (omsIR))
  4. (omi . (omiIR))
  5. (omv . (omvIR))
  6. (omf . (omfIR))
  7. (omstr . (omstrIR))
  8. (ombind . (ombindIR))
  9. (omattr . (omattrIR)));
  10. symbolic procedure om2ir();
  11. begin scalar res;
  12. % Initialisation of important variables used by the lexer.
  13. res:=nil;
  14. FLUID '(safe_atts char ch atts count temp space temp2);
  15. space:=int2id(32);
  16. count:=0;
  17. ch:=readch();
  18. temp2:=nil;
  19. % Begining of lexing and parsing
  20. lex();
  21. if char='(o m o b j) then <<
  22. lex();
  23. res:=omobj();
  24. >>
  25. else errorML("<omobj>",2);
  26. lex();
  27. if char='(!/ o m o b j) then
  28. terpri()
  29. else errorML("</omobj>",19);
  30. return res;
  31. end;
  32. symbolic procedure omobj();
  33. begin scalar aa, res;
  34. % We check what the OpenMath tag is and call the appropriate function. The relationship
  35. % between OpenMath tag and function to be called is in table omfuncs!*.
  36. if (aa:=assoc(compress!* char, omfuncs!*)) then return apply(cadr aa, nil);
  37. end;
  38. % The following function recursively reads in objects as defined in
  39. % the OpenMath grammar in the OpenMath standard.
  40. symbolic procedure omobjs();
  41. begin scalar obj, objs;
  42. if char neq '(!/ o m a) then <<
  43. obj:=omobj();
  44. lex();
  45. objs:=omobjs();
  46. if obj eq nil then
  47. return append(obj, objs)
  48. else
  49. return cons(obj, objs);
  50. >>;
  51. end;
  52. % Checks if the current token is equivalent to the given tag.
  53. symbolic procedure checkTag(tag);
  54. begin;
  55. if char neq tag then errorML("Problem", "problem");
  56. end;
  57. % This function returns the symbol read within an <OMS> tag.
  58. % It will also check in the mmleq!* table what the equivalent
  59. % MathML symbol is. If there isnt any it encodes the symbol
  60. % for use in a <semantic> tag.
  61. symbolic procedure omsIR();
  62. begin scalar cd, name, sem, aa, bb, cd, attr, symb, validcd;
  63. attr:=nil;
  64. % We read in from the input the name and CD contained
  65. % in the OMS tag.
  66. name:= intern find(atts, 'name);
  67. cd:= intern find(atts, 'cd);
  68. % We check if the symbol has a MathML equivalent
  69. % in the mmleq!* table.
  70. % But when dealing with a vector, REDUCE works differently
  71. % hence we have to deal with vectors independently.
  72. if explode name = '(v e c t o r) then aa:='(vectorml linalg1)
  73. else aa:=member (intern name, mmleq!*);
  74. % If nothing was found, we check to see if we are
  75. % dealing with a special case.
  76. % If so, we retrieve from the table special_cases!*
  77. % the equivalent MathML symbol and the correct
  78. % attribute to add.
  79. if aa=nil then <<
  80. if (aa:=assoc(name, special_cases!*)) then <<
  81. attr:=car reverse aa;
  82. if attr neq nil then attr:=list attr;
  83. aa:=cadr reverse aa . reverse cddr reverse cdr aa
  84. >>
  85. else
  86. % Here we call special case functions
  87. % because the tranlation needs some care.
  88. if (bb:=assoc(name, special_cases2!*)) neq nil then <<
  89. return apply(cadr bb, cddr bb)
  90. >>;
  91. >>;
  92. % We now check if aa is still nothing, or if the CD
  93. % given in the input does not match one of the CDs
  94. % contained in aa which map to MathML. If so, we
  95. % envelope the input into a semantic tag.
  96. if aa neq nil then validcd:= assoc(car aa, valid_om!*);
  97. if validcd neq nil then validcd:=cadr validcd;
  98. %debug("validcd: ",validcd);
  99. if aa eq nil OR cd=validcd eq nil then <<
  100. sem:=encodeIR(name);
  101. return sem;
  102. >>;
  103. % If we are dealing with a vector, we change it to IR rep which
  104. % is vectorml
  105. return list(car aa, attr);
  106. end;
  107. % The following function encodes an unknown symbol into a
  108. % valid representation for use within <semantic> tags.
  109. symbolic procedure encodeIR(name);
  110. begin scalar sem;
  111. sem:=append(char, cons('! , atts));
  112. sem:=delall('!$, sem);
  113. return cons('semantic, list cons(name, list sem));
  114. end;
  115. lisp operator om2mml;
  116. symbolic procedure omiIR();
  117. begin scalar int;
  118. lex();
  119. int := compress char;
  120. lex();
  121. return int;
  122. end;
  123. symbolic procedure omvIR();
  124. begin scalar name;
  125. name:=find(atts, 'name);
  126. if find(atts, 'hex) neq nil then errorML("wrong att", 2);
  127. if find(atts, 'dec) neq nil then errorML("wrong att", 2);
  128. return name;
  129. end;
  130. symbolic procedure variablesIR();
  131. begin scalar var, vars;
  132. if char neq '(!/ o m b v a r) then <<
  133. var:=omvIR();
  134. lex();
  135. vars:=variablesIR();
  136. if var eq nil then
  137. return append(var, vars)
  138. else
  139. return cons(var, vars);
  140. >>;
  141. end;
  142. symbolic procedure omfIR();
  143. begin scalar float;
  144. float:=find(atts, 'dec);
  145. if find(atts, 'name) neq nil then errorML("wrong att", 2);
  146. return float;
  147. end;
  148. symbolic procedure omstrIR();
  149. begin scalar str;
  150. lex();
  151. str := compress char;
  152. lex();
  153. return cons('string, list str);
  154. end;
  155. symbolic procedure omaIR();
  156. begin scalar obj, elems;
  157. lex();
  158. obj:=omobj();
  159. % If we are dealing with a matrix the following code
  160. % is not executed because the MatrixIR function
  161. % does the input reading and checks when it has
  162. % reached the closing </OMA> tag.
  163. if car obj neq 'matrix then <<
  164. lex();
  165. elems:=omobjs();
  166. checkTag('(!/ o m a));
  167. >>;
  168. return append(obj, elems);
  169. end;
  170. symbolic procedure ombindIR();
  171. begin scalar symb, vars, obj;
  172. lex();
  173. symb:=omobj();
  174. lex();
  175. vars:=toBvarIR variablesIR();
  176. lex();
  177. obj:=omobj();
  178. lex();
  179. checkTag('(!/ o m b i n d));
  180. return append(symb , append(vars, list obj));
  181. end;
  182. symbolic procedure omattrIR();
  183. begin scalar omatp, var;
  184. lex();
  185. omatp:=omatpIR();
  186. lex();
  187. var:=omobj();
  188. lex();
  189. checkTag('(!/ o m a t t r));
  190. if PAIRP omatp then if cadar omatp = 'csymbol then return (var . list nil);
  191. if NUMBERP var then return list('cn, omatp, var);
  192. return list('ci, omatp, var);
  193. end;
  194. symbolic procedure omatpIR();
  195. begin scalar symb ,obj;
  196. lex();
  197. symb:=car omsIR();
  198. lex();
  199. obj:=car omobj();
  200. lex();
  201. checkTag('(!/ o m a t p));
  202. return list (symb . list obj);
  203. end;
  204. % The following function transforms a list of variables
  205. % into a list of bvar constructs. ie: (x y)->((bvar x 1)(bvar y 1))
  206. symbolic procedure toBvarIR(bv);
  207. begin;
  208. if bv neq nil then return cons(cons('bvar, list(car bv, 1)), toBvarIR(cdr bv));
  209. end;
  210. % From here onwards, functions necessary to deal with
  211. % OpenMath special operators are defined. This is where
  212. % matrix, int, sum, prod, diff etc... are treated.
  213. symbolic procedure matrixIR();
  214. begin scalar res;
  215. lex();
  216. res:=omobjs();
  217. if caadr cadr res = 'matrixcolumn then res := 'matrixcolumn . list matrixelems(res)
  218. else res := 'matrixrow . list matrixelems(res);
  219. return 'matrix . nil . res;
  220. end;
  221. symbolic procedure matrixelems(elem);
  222. if elem neq nil then cons(cddr car elem, matrixelems cdr elem);
  223. symbolic procedure sum_prodIR();
  224. begin scalar var, fun, int, name;
  225. name:=intern find(atts, 'name);
  226. lex();
  227. int:=omobj();
  228. int:='lowupperlimit . (cdr int);
  229. lex();
  230. fun:=omobj();
  231. var:=lambdaVar fun;
  232. fun:=lambdaFun fun;
  233. return append(list(name , nil) , append(var , int . list fun));
  234. return name . nil . var . int . list fun;
  235. end;
  236. symbolic procedure integralIR();
  237. begin scalar int, fun, var, tag;
  238. tag:=intern find(atts, 'name);
  239. var:=list '(bvar x 1);
  240. int:=nil;
  241. % if dealing with defint, determine the interval
  242. % and store inside variable int
  243. if tag = 'defint then <<
  244. lex();
  245. int:=omobj();
  246. >>;
  247. lex();
  248. fun:=omobj();
  249. if PAIRP fun then if car fun = 'lambda then <<
  250. var:=lambdaVar fun;
  251. fun:=lambdaFun fun;
  252. >>;
  253. return append(list(tag , nil) , append(var , list fun));
  254. end;
  255. symbolic procedure partialdiffIR();
  256. begin scalar lis, fun, var, tag, vars;
  257. tag:=intern find(atts, 'name);
  258. lex();
  259. lis:=omobj();
  260. if car lis='list then lis:=cddr lis
  261. else errorML("",3);
  262. lex();
  263. fun:=omobj();
  264. if PAIRP fun then
  265. if car fun = 'lambda then <<
  266. var:=lambdaVar fun;
  267. fun:=lambdaFun fun;
  268. vars:= pdiffvars(lis, var);
  269. >>;
  270. return append(list('partialdiff , nil) , append(vars , list fun));
  271. end;
  272. symbolic procedure pdiffvars(ind, v);
  273. begin;
  274. return if ind neq nil then nth(v, car ind) . pdiffvars(cdr ind, v);
  275. end;
  276. symbolic procedure selectIR();
  277. begin scalar name, cd, a,b, c, tag;
  278. name:=intern find(atts, 'name);
  279. cd:=intern find(atts, 'cd);
  280. tag:=list 'selector;
  281. if member(cd, '(linalg3)) eq nil then tag:=encodeIR(name);
  282. lex();
  283. a:=omobj();
  284. if name='matrix_selector then <<
  285. lex();
  286. b:=omobj();
  287. >>;
  288. lex();
  289. c:=omobj();
  290. if name='matrix_selector then <<
  291. return append(tag, nil . c . a . list b);
  292. >>;
  293. return append(tag, nil . c . list a);
  294. end;
  295. symbolic procedure limitIR();
  296. begin scalar val, type, cd, fun, var, res, tag;
  297. cd:=intern find(atts, 'cd);
  298. tag:=list 'limit;
  299. if member(cd, '(limit1)) eq nil then tag:=encodeIR('limit);
  300. lex();
  301. val:=omobj();
  302. lex();
  303. type:=omobj();
  304. lex();
  305. fun:=omobj();
  306. % Extract the necessary information from the OpenMath read in just above.
  307. type:=caadr type;
  308. if member(type, '(below above both_sides null)) eq nil then errorML("wrong method of approach", 2);
  309. if type='null then type:='both_sides;
  310. var:= lambdaVar fun;
  311. fun:= lambdaFun fun;
  312. % Transform that information into intermediate representation.
  313. res:= append(tag, (nil . var ));
  314. if type neq 'both_sides then
  315. res:= append(res , list ('condition . list ('tendsto . list ('type . list type) . cadr car var . list val)))
  316. else
  317. res:= append(res , list ('condition . list ('tendsto . nil . cadr car var . list val)));
  318. res:= append(res, list fun);
  319. return res;
  320. end;
  321. symbolic procedure numIR();
  322. begin scalar base, a1, a2, tag;
  323. tag:=intern find(atts, 'name);
  324. lex();
  325. a1:=omobj();
  326. lex();
  327. a2:=omobj();
  328. if tag = 'complex_cartesian then <<
  329. if IDP a1 OR IDP a2 then return 'plus . nil . a1 . list ('times . nil . a2 . list '!&imaginaryi!;)
  330. >>;
  331. if tag = 'complex_polar then <<
  332. if IDP a1 OR IDP a2 then return 'times . nil . a1 . list ('exp . nil . list ('times . nil . a2 . list '!&imaginaryi!;))
  333. >>;
  334. if tag = 'rational then <<
  335. if IDP a1 OR IDP a2 then return 'divide . nil . a1 . list a2;
  336. >>;
  337. return tag . nil . a1. list a2;
  338. end;
  339. % The following function deals with OpenMath symbols
  340. % not taking any arguments such as false, true, zero, etc...
  341. symbolic procedure unaryIR(validcd, tag);
  342. begin scalar name, cd;
  343. name:=intern find(atts, 'name);
  344. cd:=intern find(atts, 'cd);
  345. if cd neq validcd then return encodeIR name;
  346. return tag;
  347. end;
  348. % Returns the first main variable of a lambda expression
  349. symbolic procedure lambdaVar(l);
  350. begin;
  351. return cdr reverse cddr l;
  352. end;
  353. symbolic procedure lambdaVar2(l);
  354. begin;
  355. return cadr caddr l;
  356. end;
  357. % Returns the function of a lambda expression
  358. symbolic procedure lambdaFun(l);
  359. begin;
  360. return car reverse l;
  361. end;
  362. % This function is the one the user types to
  363. % translate OpenMath to MathML.
  364. symbolic procedure om2mml();
  365. begin scalar ir;
  366. ir:=om2ir();
  367. terpri!* t;
  368. princ "Intermediate representation:";
  369. terpri!* t;
  370. princ ir;
  371. terpri!* t;
  372. ir2mml ir;
  373. end;
  374. end;