office-gobmx/hwpfilter/source/hwpeq.cpp
Jens-Heiner Rechtien 30c07021cc INTEGRATION: CWS warnings01 (1.4.4); FILE MERGED
2006/02/10 14:25:13 os 1.4.4.2: #i59838# warnings removed
2005/10/13 09:53:19 os 1.4.4.1: #i53898# warnings removed
2006-06-19 23:54:52 +00:00

774 lines
24 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*************************************************************************
*
* OpenOffice.org - a multi-platform office productivity suite
*
* $RCSfile: hwpeq.cpp,v $
*
* $Revision: 1.5 $
*
* last change: $Author: hr $ $Date: 2006-06-20 00:54:52 $
*
* The Contents of this file are made available subject to
* the terms of GNU Lesser General Public License Version 2.1.
*
*
* GNU Lesser General Public License Version 2.1
* =============================================
* Copyright 2005 by Sun Microsystems, Inc.
* 901 San Antonio Road, Palo Alto, CA 94303, USA
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License version 2.1, as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*
************************************************************************/
//#include "stdafx.h"
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
// DVO: always use standard headers:
#include <istream>
#include <sstream>
using namespace std;
#include "mzstring.h"
#include "hwpeq.h"
#include <sal/types.h>
//#define TEST
//#define DEBUG
/* @Man: hwp¼ö½ÄÀ» LaTeXÀ¸·Î ¹Ù²Ù±â */
#ifdef WIN32
# define ENDL "\r\n"
#else /* !WIN32 */
# define ENDL "\n"
#endif
#define WS " \t\r\n\v\f"
#define EQ_CASE 0x01 // case sensitive cmd
#define EQ_ENV 0x02 // equiv to latex environment
#define EQ_ATOP 0x04 // must revert order
#define IS_WS(ch) (strchr(WS, ch))
#define IS_BINARY(ch) (strchr("+-<=>", ch))
#ifdef WIN32
#define STRICMP stricmp
#else
#define STRICMP strcasecmp
#endif
// sub and sup scipt script status
enum { SCRIPT_NONE, SCRIPT_SUB, SCRIPT_SUP, SCRIPT_ALL};
static int eq_word(MzString& outs, istream *strm, int script = SCRIPT_NONE);
static bool eq_sentence(MzString& outs, istream *strm, const char *end = 0);
struct hwpeq {
const char *key; // hwp math keyword
const char *latex; // corresponding latex keywork
int nargs; // # of argument
unsigned char flag; // case sensitive?
};
static hwpeq eq_tbl[] = {
{ "!=", "\\equiv ", 0, 0 },
{ "#", "\\\\", 0, 0 },
{ "+-", "\\pm ", 0, 0 },
{ "-+", "\\mp ", 0, 0 },
{ "<=", "\\leq ", 0, 0 },
{ "==", "\\equiv ", 0, 0 },
{ ">=", "\\geq ", 0, 0 },
{ "Pr", NULL, 0, 0 },
{ "^", "^", 1, 0 },
{ "_", "_", 1, 0 },
{ "`", "\\;", 0, 0 },
{ "acute", NULL, 1, 0 },
{ "aleph", NULL, 0, 0 },
{ "alpha", NULL, 0, EQ_CASE },
{ "amalg", NULL, 0, 0 },
{ "and", NULL, 0, 0 },
{ "angle", NULL, 0, 0 },
{ "angstrom", NULL, 0, 0 },
{ "approx", NULL, 0, 0 },
{ "arc", NULL, 0, 0 },
{ "arccos", NULL, 0, 0 },
{ "arch", NULL, 0, 0 },
{ "arcsin", NULL, 0, 0 },
{ "arctan", NULL, 0, 0 },
{ "arg", NULL, 0, 0 },
{ "assert", "\\vdash", 0, 0 },
{ "ast", NULL, 0, 0 },
{ "asymp", NULL, 0, 0 },
{ "atop", NULL, 1, EQ_ATOP },
{ "backslash", NULL, 0, 0 },
{ "bar", NULL, 1, 0 },
{ "because", NULL, 0, 0 },
{ "beta", NULL, 0, EQ_CASE },
{ "big", NULL, 0, EQ_CASE },
{ "bigcap", NULL, 0, 0 },
{ "bigcirc", NULL, 0, 0 },
{ "bigcup", NULL, 0, 0 },
{ "bigg", NULL, 0, EQ_CASE },
{ "bigodiv", NULL, 0, 0 },
{ "bigodot", NULL, 0, 0 },
{ "bigominus", NULL, 0, 0 },
{ "bigoplus", NULL, 0, 0 },
{ "bigotimes", NULL, 0, 0 },
{ "bigsqcap", NULL, 0, 0 },
{ "bigsqcup", NULL, 0, 0 },
{ "biguplus", NULL, 0, 0 },
{ "bigvee", NULL, 0, 0 },
{ "bigwedge", NULL, 0, 0 },
{ "binom", NULL, 2, 0 },
{ "bmatrix", NULL, 0, EQ_ENV },
{ "bold", NULL, 0, 0 },
{ "bot", NULL, 0, 0 },
{ "breve", NULL, 1, 0 },
{ "buildrel", NULL, 0, 0 }, // LATER
{ "bullet", NULL, 0, 0 },
{ "cap", NULL, 0, 0 },
{ "cases", NULL, 0, EQ_ENV },
{ "ccol", NULL, 0, 0 }, /* ¼¼·Î·Î °¡¿îµ¥ */
{ "cdot", NULL, 0, 0 },
{ "cdots", NULL, 0, 0 },
{ "check", NULL, 1, 0 },
{ "chi", NULL, 0, EQ_CASE },
{ "choose", NULL, 0, EQ_ATOP },
{ "circ", NULL, 0, 0 },
{ "col", NULL, 0, 0 }, // LATER
{ "cong", NULL, 0, 0 },
{ "coprod", NULL, 0, 0 },
{ "cos", NULL, 0, 0 },
{ "cosec", NULL, 0, 0 },
{ "cosh", NULL, 0, 0 },
{ "cot", NULL, 0, 0 },
{ "coth", NULL, 0, 0 },
{ "cpile", NULL, 0, 0 }, // LATER
{ "csc", NULL, 0, 0 },
{ "cup", NULL, 0, 0 },
{ "dagger", NULL, 0, 0 },
{ "dashv", NULL, 0, 0 },
{ "ddagger", NULL, 0, 0 },
{ "ddot", NULL, 1, 0 },
{ "ddots", NULL, 0, 0 },
{ "def", NULL, 0, 0 },
{ "deg", NULL, 0, 0 },
{ "del", NULL, 0, 0 },
{ "delta", NULL, 0, EQ_CASE },
{ "diamond", NULL, 0, 0 },
{ "dim", NULL, 0, 0 },
{ "div", NULL, 0, 0 },
{ "divide", NULL, 0, 0 },
{ "dline", NULL, 0, 0 },
{ "dmatrix", NULL, 0, EQ_ENV },
{ "dot", NULL, 1, 0 },
{ "doteq", NULL, 0, 0 },
{ "dotsaxis", NULL, 0, 0 },
{ "dotsdiag", NULL, 0, 0 },
{ "dotslow", "\\ldots", 0, 0 },
{ "dotsvert", "\\vdots", 0, 0 },
{ "downarrow", NULL, 0, EQ_CASE },
{ "dsum", "+", 0, 0 },
{ "dyad", NULL, 0, 0 }, // LATER
{ "ell", NULL, 0, 0 },
{ "emptyset", NULL, 0, 0 },
{ "epsilon", NULL, 0, EQ_CASE },
{ "eqalign", NULL, 0, EQ_ENV },
{ "equiv", NULL, 0, 0 },
{ "eta", NULL, 0, EQ_CASE },
{ "exarrow", NULL, 0, 0 },
{ "exist", "\\exists", 0, 0 },
{ "exists", NULL, 0, 0 },
{ "exp", NULL, 0, EQ_CASE },
{ "for", NULL, 0, 0 },
{ "forall", NULL, 0, 0 },
{ "from", "_", 1, 0 },
{ "gamma", NULL, 0, EQ_CASE },
{ "gcd", NULL, 0, 0 },
{ "ge", "\\geq", 0, 0 },
{ "geq", NULL, 0, 0 },
{ "ggg", NULL, 0, 0 },
{ "grad", NULL, 0, 0 },
{ "grave", NULL, 1, 0 },
{ "hat", "\\widehat", 1, 0 },
{ "hbar", NULL, 0, 0 },
{ "hom", NULL, 0, 0 },
{ "hookleft", NULL, 0, 0 },
{ "hookright", NULL, 0, 0 },
{ "identical", NULL, 0, 0 }, // LATER
{ "if", NULL, 0, 0 },
{ "imag", NULL, 0, 0 },
{ "image", NULL, 0, 0 },
{ "imath", NULL, 0, 0 },
{ "in", NULL, 0, 0 },
{ "inf", "\\infty", 0, 0 },
{ "infinity", "\\infty", 0, 0 },
{ "infty", NULL, 0, 0 },
{ "int", NULL, 0, 0 },
{ "integral", "\\int", 0, 0 },
{ "inter", "\\bigcap", 0, 0 },
{ "iota", NULL, 0, EQ_CASE },
{ "iso", NULL, 0, 0 }, // ams
{ "it", NULL, 0, 0 },
{ "jmath", NULL, 0, 0 },
{ "kappa", NULL, 0, EQ_CASE },
{ "ker", NULL, 0, 0 },
{ "lambda", NULL, 0, EQ_CASE },
{ "land", NULL, 0, 0 }, // LATER
{ "langle", NULL, 0, 0 },
{ "larrow", "\\leftarrow", 0, EQ_CASE },
{ "lbrace", NULL, 0, 0 },
{ "lbrack", "[", 0, 0 },
{ "lceil", NULL, 0, 0 },
{ "lcol", NULL, 0, 0 }, // LATER
{ "ldots", NULL, 0, 0 },
{ "le", NULL, 0, 0 },
{ "left", NULL, 0, 0 },
{ "leftarrow", NULL, 0, EQ_CASE },
{ "leq", NULL, 0, 0 },
{ "lfloor", NULL, 0, 0 },
{ "lg", NULL, 0, 0 },
{ "lim", NULL, 0, EQ_CASE },
{ "line", "\\vert", 0, 0 },
{ "liter", "\\ell", 0, 0 },
{ "lll", NULL, 0, 0 }, // ams
{ "ln", NULL, 0, 0 },
{ "log", NULL, 0, 0 },
{ "lor", "\\vee", 0, 0 },
{ "lparen", "(", 0, 0 },
{ "lpile", NULL, 0, 0 }, // LATER
{ "lrarrow", "\\leftrightarrow", 0, EQ_CASE },
{ "lrharpoons", "\\leftrightharpoons",0, 0 },
{ "mapsto", NULL, 0, 0 },
{ "massert", "\\dashv", 0, 0 },
{ "matrix", NULL, 0, EQ_ENV },
{ "max", NULL, 0, 0 },
{ "mho", NULL, 0, 0 }, // ams
{ "min", NULL, 0, 0 },
{ "minusplus", NULL, 0, 0 },
{ "mit", "", 0, 0 }, // font
{ "mod", "\\bmod", 0, 0 },
{ "models", NULL, 0, 0 },
{ "msangle", NULL, 0, 0 }, // LATER
{ "mu", NULL, 0, EQ_CASE },
{ "nabla", NULL, 0, 0 },
{ "ne", NULL, 0, 0 },
{ "nearrow", NULL, 0, 0 },
{ "neg", NULL, 0, 0 },
{ "neq", NULL, 0, 0 },
{ "nequiv", NULL, 0, 0 },
{ "ni", NULL, 0, 0 },
{ "not", NULL, 0, 0 },
{ "notin", NULL, 0, 0 },
{ "nu", NULL, 0, EQ_CASE },
{ "nwarrow", NULL, 0, 0 },
{ "odiv", NULL, 0, 0 },
{ "odot", NULL, 0, 0 },
{ "oint", NULL, 0, 0 },
{ "omega", NULL, 0, EQ_CASE },
{ "omicron", NULL, 0, EQ_CASE },
{ "ominus", NULL, 0, 0 },
{ "oplus", NULL, 0, 0 },
{ "or ", NULL, 0, 0 },
{ "oslash", NULL, 0, 0 },
{ "otimes", NULL, 0, 0 },
{ "over", NULL, 1, EQ_ATOP },
{ "overline", NULL, 1, 0 },
{ "owns", "\\ni", 0, 0 },
{ "parallel", NULL, 0, 0 },
{ "partial", NULL, 0, 0 },
{ "phantom", NULL, 0, 0 },
{ "phi", NULL, 0, EQ_CASE },
{ "pi", NULL, 0, EQ_CASE },
{ "pile", NULL, 0, 0 }, // LATER
{ "plusminus", "\\pm", 0, 0 },
{ "pmatrix", NULL, 0, EQ_ENV },
{ "prec", NULL, 0, 0 },
{ "prep", NULL, 0, 0 },
{ "prime", NULL, 0, 0 },
{ "prod", NULL, 0, 0 },
{ "propto", NULL, 0, 0 },
{ "psi", NULL, 0, EQ_CASE },
{ "rangle", NULL, 0, 0 },
{ "rarrow", "\\rightarrow", 0, EQ_CASE },
{ "rbrace", "]", 0, 0 },
{ "rbrace", NULL, 0, 0 },
{ "rceil", NULL, 0, 0 },
{ "rcol", NULL, 0, 0 }, // LATER
{ "real", "\\Re", 0, 0 },
{ "reimage", NULL, 0, 0 },
{ "rel", NULL, 0, 0 },
{ "rfloor", NULL, 0, 0 },
{ "rho", NULL, 0, EQ_CASE },
{ "right", NULL, 0, 0 },
{ "rightarrow", NULL, 0, EQ_CASE },
{ "rlharpoons", NULL, 0, 0 },
{ "rm", NULL, 0, 0 },
{ "root", "\\sqrt", 1, 0 },
{ "rparen", ")", 0, 0 },
{ "rpile", NULL, 0, 0 }, // LATER
{ "rtangle", NULL, 0, 0 },
{ "sangle", NULL, 0, 0 },
{ "scale", NULL, 0, 0 },
{ "searrow", NULL, 0, 0 },
{ "sec", NULL, 0, 0 },
{ "sigma", NULL, 0, EQ_CASE },
{ "sim", NULL, 0, 0 },
{ "simeq", NULL, 0, 0 },
{ "sin", NULL, 0, 0 },
{ "sinh", NULL, 0, 0 },
{ "slash", NULL, 0, 0 },
{ "smallint", NULL, 0, 0 },
{ "smallinter", NULL, 0, 0 },
{ "smalloint", NULL, 0, 0 },
{ "smallprod", NULL, 0, 0 },
{ "smallsum", NULL, 0, 0 },
{ "smallunion", NULL, 0, 0 },
{ "smcoprod", NULL, 0, 0 },
{ "sqcap", NULL, 0, 0 },
{ "sqcup", NULL, 0, 0 },
{ "sqrt", NULL, 1, 0 },
{ "sqsubset", NULL, 0, 0 },
{ "sqsubseteq", NULL, 0, 0 },
{ "sqsupset", NULL, 0, 0 },
{ "sqsupseteq", NULL, 0, 0 },
{ "star", NULL, 0, 0 },
{ "sub", "_", 0, 0 },
{ "subset", NULL, 0, 0 },
{ "subseteq", NULL, 0, 0 },
{ "succ", NULL, 0, 0 },
{ "sum", NULL, 0, 0 },
{ "sup", "^", 0, 0 },
{ "superset", NULL, 0, 0 },
{ "supset", NULL, 0, 0 },
{ "supseteq", NULL, 0, 0 },
{ "swarrow", NULL, 0, 0 },
{ "tan", NULL, 0, 0 },
{ "tanh", NULL, 0, 0 },
{ "tau", NULL, 0, EQ_CASE },
{ "therefore", NULL, 0, 0 },
{ "theta", NULL, 0, EQ_CASE },
{ "tilde", "\\widetilde", 1, 0 },
{ "times", NULL, 0, 0 },
{ "to", "^", 1, 0 },
{ "top", NULL, 0, 0 },
{ "triangle", NULL, 0, 0 },
{ "triangled", NULL, 0, 0 },
{ "trianglel", NULL, 0, 0 },
{ "triangler", NULL, 0, 0 },
{ "triangleu", NULL, 0, 0 },
{ "udarrow", "\\updownarrow",0, EQ_CASE },
{ "under", "\\underline", 1, 0 },
{ "underline", "\\underline", 1, 0 },
{ "union", "\\bigcup", 0, 0 },
{ "uparrow", NULL, 0, EQ_CASE },
{ "uplus", NULL, 0, 0 },
{ "upsilon", NULL, 0, EQ_CASE },
{ "varepsilon", NULL, 0, 0 },
{ "varphi", NULL, 0, 0 },
{ "varpi", NULL, 0, 0 },
{ "varrho", NULL, 0, 0 },
{ "varsigma", NULL, 0, 0 },
{ "vartheta", NULL, 0, 0 },
{ "varupsilon", NULL, 0, 0 },
{ "vdash", NULL, 0, 0 },
{ "vdots", NULL, 0, 0 },
{ "vec", NULL, 1, 0 },
{ "vee", NULL, 0, 0 },
{ "vert", NULL, 0, 0 },
{ "wedge", NULL, 0, 0 },
{ "wp", NULL, 0, 0 },
{ "xi", NULL, 0, EQ_CASE },
{ "xor", NULL, 0, 0 },
{ "zeta", NULL, 0, EQ_CASE }
};
static hwpeq *lookup_eqn(char *str)
{
static int eqCount = sizeof(eq_tbl) / sizeof(eq_tbl[0]);
int m, k, l = 0, r = eqCount;
hwpeq *result = 0;
while( l < r ) {
m = (l + r) / 2;
k = strcmp(eq_tbl[m].key, str);
if( k == 0 ) {
result = eq_tbl + m;;
break;
}
else if( k < 0 )
l = m + 1;
else
r = m;
}
return result;
}
/* ùÀÚ¸¸ ´ë¹®ÀÚÀ̰ųª ÀüºÎ ´ë¹®ÀÚ¸é ¼Ò¹®ÀÚ·Î ¹Ù²Û´Ù. */
static char *make_keyword( char *keyword, const char *token)
{
assert(keyword);
char *ptr;
int result = true, len = strlen(token);
if( 255 < len )
strncpy(keyword, token, 255);
else
strcpy(keyword, token);
if( (token[0] & 0x80) || islower(token[0]) ||
strlen(token) < 2 )
return keyword;
int capital = isupper(keyword[1]);
for( ptr = keyword + 2; *ptr && result; ptr++ )
if( (*ptr & 0x80) ||
(!capital && isupper(*ptr)) ||
(capital && islower(*ptr)) )
result = false;
if( result ) {
ptr = keyword;
while( *ptr ) {
if( isupper(*ptr) )
*ptr = sal::static_int_cast<char>(tolower(*ptr));
ptr++;
}
}
return keyword;
}
// token reading funtion
struct eq_stack {
MzString white;
MzString token;
istream *strm;
eq_stack() { strm = 0; };
bool state(istream *s) {
if( strm != s) { white = 0; token = 0; }
return token.length() != 0;
}
};
static eq_stack *stk = 0;
void push_token(MzString &white, MzString &token, istream *strm)
{
// one time stack
assert(stk->state(strm) == false);
stk->white = white;
stk->token = token;
stk->strm = strm;
}
/*
ÀÐÀº ÅäÅ«ÀÇ ±æÀ̸¦ ¹ÝȯÇÑ´Ù. */
/* control char, control sequence, binary sequence,
alphabet string, sigle character */
static int next_token(MzString &white, MzString &token, istream *strm)
{
register int ch = 0;
if( stk->state(strm) ) {
white = stk->white;
token = stk->token;
stk->token = 0;
stk->white = 0;
return token.length();
}
token = 0;
white = 0;
if( !strm->good() || (ch = strm->get()) == EOF )
return 0;
// read preceeding ws
if( IS_WS(ch) ) {
do white << (char) ch;
while( IS_WS(ch = strm->get()) );
}
if( ch == '\\' || ch & 0x80 || isalpha(ch) ) {
if( ch == '\\' ) {
token << (char) ch;
ch = strm->get();
}
do {
token << (char) ch;
ch = strm->get();
} while( ch != EOF && (ch & 0x80 || isalpha(ch)) ) ;
strm->putback(sal::static_int_cast<char>(ch));
/* sub, sub, over, atop Ư¼ö ó¸®
±× ÀÌÀ¯´Â next_state()¿¡ ¿µÇâÀ» ¹ÌÄ¡±â ¶§¹®ÀÌ´Ù.
*/
if( !STRICMP("sub", token) || !STRICMP("from", token) ||
!STRICMP("sup", token) || !STRICMP("to", token) ||
!STRICMP("over", token) || !STRICMP("atop", token) ||
!STRICMP("left", token) || !STRICMP("right", token) )
{
char buf[256];
make_keyword(buf, token);
token = buf;
}
if( !token.compare("sub") || !token.compare("from") )
token = "_";
if( !token.compare("sup") || !token.compare("to") )
token = "^";
}
else if( IS_BINARY(ch) ) {
do token << (char) ch;
while( IS_BINARY(ch = strm->get()) );
strm->putback(sal::static_int_cast<char>(ch));
}
else if( isdigit(ch) ) {
do token << (char) ch;
while( isdigit(ch = strm->get()) );
strm->putback(sal::static_int_cast<char>(ch));
}
else
token << (char) ch;
// cout << "WHITE : " << "|" << white.c_str() << "|" << endl ;
// cout << "TOKEN : " << "|" << token.c_str() << "|" << endl ;
return token.length();
}
static int read_white_space(MzString& outs, istream *strm)
{
int ch, result;
if( stk->state(strm) ) {
outs << stk->white;
stk->white = 0;
result = stk->token[0];
}
else {
while( IS_WS(ch = strm->get()) )
outs << (char )ch;
strm->putback(sal::static_int_cast<char>(ch));
result = ch;
}
return result;
}
/* Àμö°¡ ÇÊ¿äÇÏÁö ¾ÊÀº °æ¿ì °¢ Ç׸ñ°£ÀÇ ±¸ºÐÀº space¿Í brace
sqrt {ab}c = sqrt{ab} c
(, }´Â grouping
^, _ ´Â ¾ÕµÚ·Î °áÇÕÇÑ´Ù.
sqrt µî°ú °°ÀÌ Àμö°¡ ÀÖ´Â Çü½Ä Á¤¸®
sqrt a -> sqrt{a}
sqrt {a} -> sqrt{a}
1 ÀÌ»óÀÇ Àμö°¡ ÀÖ´Â °æ¿ì Àμöµé°£ÀÇ ¿ª¹éÀº ¾ø¾Ø´Ù.
\frac a b -> frac{a}{b}
overÀÇ Çü½Ä Á¤¸®
a over b -> {a}over{b}
*/
static int eq_word(MzString& outs, istream *strm, int status)
{
MzString token, white, state;
int ch, result, nargs;
char keyword[256];
hwpeq *eq;
#ifdef DEBUG
static int slevel = 0;
slevel++;
#endif
next_token(white, token, strm);
if (token.length() <= 0)
return 0;
result = token[0];
if( token.compare("{") == 0 ) {
state << white << token;
eq_sentence(state, strm, "}");
}
else if( token.compare("left") == 0 ) {
state << white << token;
next_token(white, token, strm);
state << white << token;
eq_sentence(state, strm, "right");
next_token(white, token, strm);
state << white << token;
}
else {
/* Á¤»óÀûÀÎ token */
int script_status = SCRIPT_NONE;
while( 1 ) {
state << white << token;
make_keyword(keyword, token);
if( token[0] == '^' )
script_status |= SCRIPT_SUP;
else if( token[0] == '_' )
script_status |= SCRIPT_SUB;
else
script_status = SCRIPT_NONE;
if( 0 != (eq = lookup_eqn(keyword)) ) {
nargs = eq->nargs;
while( nargs-- ) {
ch = read_white_space(state, strm);
if( ch != '{' ) state << '{';
eq_word(state, strm, script_status);
if( ch != '{' ) state << '}';
}
}
if( !next_token(white, token, strm) )
break;
// end loop and restart with this
if( (token[0] == '^' && status && !(status & SCRIPT_SUP)) ||
(token[0] == '_' && status && !(status & SCRIPT_SUB)) ||
strcmp("over", token) == 0 || strcmp("atop", token) == 0 ||
strchr("{}#&`", token[0]) ||
(!strchr("^_", token[0]) && white.length()) ) {
push_token(white, token, strm);
break;
}
}
}
outs << state;
#ifdef DEBUG
//if( slevel == 1 )
// cout << "LEVEL[" << slevel << "]" << state << "\n";
slevel--;
#endif
return result;
}
static bool eq_sentence(MzString& outs, istream *strm, const char *end)
{
MzString state;
MzString white, token;
bool multiline = false;
read_white_space(outs, strm);
while( eq_word(state, strm) ) {
if( !next_token(white, token, strm) ||
(end && strcmp(token.c_str(), end) == 0) )
{
state << white << token;
break;
}
push_token(white, token, strm);
if( !token.compare("atop") || !token.compare("over") )
outs << '{' << state << '}';
else {
if( !token.compare("#") )
multiline = true;
outs << state;
}
state = 0;
read_white_space(outs, strm);
}
outs << state;
return multiline;
}
static char eq2ltxconv(MzString& sstr, istream *strm, const char *sentinel)
{
MzString white, token;
char key[20];
int ch, result;
hwpeq *eq = 0;
while( 0 != (result = next_token(white, token, strm)) ) {
if( sentinel && (result == 1) && strchr(sentinel, token[0]) )
break;
make_keyword(key, token);
if( (eq = lookup_eqn(key)) != 0 ) {
if( eq->latex )
strcpy(key, eq->latex);
else {
key[0] = '\\';
strcpy(key + 1, eq->key);
}
if( (eq->flag & EQ_CASE) && isupper(token[0]) )
key[1] = sal::static_int_cast<char>(toupper(key[1]));
token = key;
}
if( token[0] == '{' ) { // grouping
sstr << white << token;
eq2ltxconv(sstr, strm, "}");
sstr << '}';
}
else if( eq && (eq->flag & EQ_ENV) ) {
next_token(white, token, strm);
if( token[0] != '{' ) return 0;
sstr << "\\begin" << "{" << eq->key << "}" << ENDL ;
eq2ltxconv(sstr, strm, "}");
if( sstr[sstr.length() - 1] != '\n' )
sstr << ENDL ;
sstr << "\\end" << "{" << eq->key << "}" << ENDL ;
}
else if( eq && (eq->flag & EQ_ATOP) ) {
if( sstr.length() == 0 )
sstr << '{';
else {
int pos = sstr.rfind('}');
if( 0 < pos)
sstr.replace(pos, ' ');
}
sstr << token;
while( (ch = strm->get()) != EOF && IS_WS(ch) )
sstr << (char)ch;
if( ch != '{' )
sstr << "{}";
else {
eq2ltxconv(sstr, strm, "}");
sstr << '}';
}
}
else
sstr << white << token;
}
return token[0];
}
void eq2latex(MzString& outs, char *s)
{
assert(s);
if( stk == 0 )
stk = new eq_stack;
MzString tstr;
istringstream tstrm(s);
bool eqnarray = eq_sentence(tstr, &tstrm);
#ifdef TEST
cout << "Step1: " << endl << tstr.c_str() << endl;
#endif
istringstream strm(tstr.c_str());
if( eqnarray )
outs << "\\begin{array}{rllll}" << ENDL;
eq2ltxconv(outs, &strm, 0);
outs << ENDL;
if( eqnarray )
outs << "\\end{array}" << ENDL;
delete stk;
stk = 0;
}