/** * $OpenXM: OpenXM/src/OpenMath/OM2OXM.java,v 1.18 2000/02/28 14:10:28 takayama Exp $ * * このクラスでは以下の BNF で表される構文解析を実装している * expr -> stag [expr | immediate]* etag * immediate -> INTEGER * | SYMBOL * stag -> '<' SYMBOL '>' * etag -> '<' '/' SYMBOL '>' * 終端記号: INTEGER, SYMBOL, '<', '/', '>' * 非終端記号: expr, stag, etag, immediate * 開始記号: expr * * 以下の関数を使用: * public void send(OutputStream os); - buffer にある OX message を送信する. * public int parse(); - 構文解析を開始する. * private int parse_expr(); - parser の expr 部分 * private Attribute parse_stag(); - parser の stag 部分 * private void parse_etag(Attribute tag,int argnum); - parser の etag 部分 * private int parse_immediate(); - parser の immediate 部分 * private void parse_error(String mesg); - parser の error を表示して終了する * public static void main(String[] args); - main 関数. * * 以下の変数を使用: * Attribute Attribute; - 字句解析器を呼び出し, その属性値を保存しておく * int token; - 現在読み込んでいる token を保存しておくのに使用. * CellStack stack; - セマンティックスのチェックに使う内部スタック. * ByteArrayOutputStream buffer; - oxasir に送信するまえにデータを溜めておく */ import java.io.*; import java.net.*; import java.util.Vector; import JP.ac.kobe_u.math.tam.OpenXM.*; final class OM2OXM implements Runnable{ private PushbackInputStream is; private String attribute; private int token = TT_NULL; private boolean lexPushbackFlag = false; private OpenXM asir; // for debug protected boolean debug = false; // for debug message // Token Type for lexical analyzer final static int TT_NULL = 0; final static int TT_String = -1; final static int TT_StartTag = -2; final static int TT_EndTag = -3; final static int TT_SingleTag = -4; public void run(){ // for debug //サーバ側から送信された文字列を受信します。 try{ while(true){ CMO tmp; switch(asir.receiveOXtag()){ case OpenXM.OX_COMMAND: asir.receiveSM(); break; case OpenXM.OX_DATA: tmp = asir.receiveCMO(); System.out.println("=> "+ CMO2OM(tmp)); break; } } }catch(IOException e){} } public static String CMO2OM(CMO cmo){ return ""+ CMO2OM_sub(cmo) +""; } private static String CMO2OM_sub(CMO cmo) throws NumberFormatException{ String ret = ""; switch(cmo.getDISCRIMINATOR()){ case CMO.CMO_NULL: return "0"; case CMO.CMO_INT32: return ""+ ((CMO_INT32)cmo).intValue() +""; // case CMO.CMO_DATUM: case CMO.CMO_STRING: return ""+ ((CMO_STRING)cmo).getString() +""; case CMO.CMO_LIST: ret += ""; { CMO ob[] = ((CMO_LIST)cmo).getElements(); for(int i=0;i"; ret += CMO2OM_sub(((CMO_MONOMIAL32)cmo).getCoefficient()); for(int i=0;i<((CMO_MONOMIAL32)cmo).getDegree().length;i++){ ret += ""+ ((CMO_MONOMIAL32)cmo).getDegree()[i] +""; } ret += ""; return ret; case CMO.CMO_ZZ: return ""+ ((CMO_ZZ)cmo).BigIntValue() +""; case CMO.CMO_QQ: return ""+ CMO2OM_sub(((CMO_QQ)cmo).getBunshi())+ CMO2OM_sub(((CMO_QQ)cmo).getBunbo())+ ""; case CMO.CMO_ZERO: return " 0 "; // case CMO.CMO_DMS: case CMO.CMO_DMS_GENERIC: ret += ""; ret += "2"; return ret; case CMO.CMO_RECURSIVE_POLYNOMIAL: return CMO2OM_CoefficientOfRecursivePOLYNOMIAL(((CMO_RECURSIVE_POLYNOMIAL)cmo).getPolynomial(),((CMO_RECURSIVE_POLYNOMIAL)cmo).getVariables()); case CMO.CMO_DISTRIBUTED_POLYNOMIAL: ret += ""; ret += CMO2OM_sub(((CMO_DISTRIBUTED_POLYNOMIAL)cmo).getRing()); ret += ""; for(int i=0;i<((CMO_DISTRIBUTED_POLYNOMIAL)cmo).getMonomials().length; i++){ ret += CMO2OM_sub(((CMO_DISTRIBUTED_POLYNOMIAL)cmo).getMonomials()[i]); } ret += ""; return ret; //case CMO.CMO_POLYNOMIAL_IN_ONE_VARIABLE: case CMO.CMO_BIGFLOAT: ret += ""; ret += CMO2OM_sub(((CMO_BIGFLOAT)cmo).getSyosubu()); ret += ""; ret += "2"; ret += CMO2OM_sub(((CMO_BIGFLOAT)cmo).getShisubu()); ret += ""; return ret; case CMO.CMO_INDETERMINATE: return ""; case CMO.CMO_TREE: ret += ""; for(int i=0;i<((CMO_TREE)cmo).getLeaves().getElements().length;i++){ ret += CMO2OM_sub(((CMO_TREE)cmo).getLeaves().getElements()[i]); } ret += ""; return ret; default: //return ""+ cmo.toCMOexpression() +""; } throw new NumberFormatException("unknown convert way:"+ cmo.toCMOexpression()); } private static String CMO2OM_CoefficientOfRecursivePOLYNOMIAL(CMO cmo,CMO_LIST variables){ CMO_POLYNOMIAL_IN_ONE_VARIABLE poly; String ret = "",variable; if(!(cmo instanceof CMO_POLYNOMIAL_IN_ONE_VARIABLE)){ return CMO2OM_sub(cmo); } poly = (CMO_POLYNOMIAL_IN_ONE_VARIABLE)cmo; variable = CMO2OM_sub(variables.getElements()[poly.getVariable()]); for(int i=0;i"+ ""+ variable +""+ poly.getDegrees()[i] +""+ CMO2OM_CoefficientOfRecursivePOLYNOMIAL(poly.getCoefficients()[i], variables) +""; if(i==0){ ret = mono; }else{ ret = ""+ ret + mono +""; } } return ret; } private boolean isSpace(int ch){ // use from lex return (ch==' ' || ch=='\t' || ch=='\n' || ch=='\r'); } private int skipSpace() throws IOException{ // use from lex int ch; do{ ch = is.read(); }while(isSpace(ch)); is.unread(ch); return ch; } private void pushbackLex(){ if(lexPushbackFlag){ System.err.println("lex pushback error!"); } lexPushbackFlag = true; } private int readNextToken() throws IOException{ // lexical analyzer String buf = ""; int ch; if(lexPushbackFlag){ lexPushbackFlag = false; return token; } token = TT_NULL; attribute = ""; skipSpace(); ch = is.read(); if(ch == '<'){ // for tag ch = skipSpace(); if(ch == '/'){ is.read(); token = TT_EndTag; skipSpace(); }else{ token = TT_StartTag; } while((ch = is.read()) != '>' && ch != '/' && ch != -1){ if(isSpace(ch)){ if((ch = skipSpace()) != '>' && ch != '/'){ buf += " "; } continue; } buf += Character.toUpperCase((char)ch); if(ch == '"'){ do{ ch = is.read(); buf += (char)ch; }while(ch != '"' && ch != -1); } } if(ch == '>'){ // for StartTag and EndTag attribute = buf; return token; }else if(ch == '/'){ skipSpace(); if((ch = is.read()) == '>'){ // for SingleTag attribute = buf; return token = TT_SingleTag; } } return token = TT_NULL; }else if(ch != -1){ is.unread(ch); while((ch = is.read()) != '<' && ch != -1){ debug("debug: "+ch); if(isSpace(ch)){ String spaces = String.valueOf((char)ch); while(isSpace(ch = is.read())){ spaces += (char)ch; } if(ch != '<' && ch != -1){ buf += spaces; } is.unread(ch); }else{ buf += (char)ch; } } is.unread(ch); attribute = buf; return token = TT_String; } return token = TT_NULL; } private boolean exceptTokenTypeInParse(int type) throws IOException{ // use from parse if(readNextToken() != type){ parse_error("We expect type :'"+ type +"', but we got type :'"+ token +"'("+ attribute +")."); } //debug(":"+token+":"+attribute+":"+type); return true; } public CMO parse(InputStream stream) throws IOException{ // start -> '' object '' CMO ret; is = new PushbackInputStream(stream); exceptTokenTypeInParse(TT_StartTag); if(!attribute.equals("OMOBJ")){ parse_error("We expect ''."); } ret = parse_object(); exceptTokenTypeInParse(TT_EndTag); if(!attribute.equals("OMOBJ")){ parse_error("We expect ''."); } return ret; } private CMO parse_object() throws IOException{ // object -> variable // | '' S? integer S? '' // | '' S? utf7 S? '' // | '' S? symbol S? objects S? '' CMO ret; if(readNextToken() != TT_StartTag && token != TT_SingleTag){ parse_error("We expect ' or '' or ''."); } if(attribute.startsWith("OMV")){ pushbackLex(); ret = parse_variable(); }else if(attribute.equals("OMI")){ pushbackLex(); ret = parse_OMI(); }else if(attribute.equals("OMSTR")){ pushbackLex(); ret = parse_OMSTR(); }else if(attribute.equals("OMA")){ String name,cdname; int argnum = 0; name = parse_symbol(); if(name.equals("DMP")){ ret = parse_symb_DMP(); debug("poly: "+ret); }else{ CMO[] leaves = parse_objects(); if(name.equals("list")){ ret = new CMO_LIST(leaves); }else if(name.equals("over") && leaves.length==2 && leaves[0] instanceof CMO_ZZ && leaves[1] instanceof CMO_ZZ){ ret = new CMO_QQ((CMO_ZZ)leaves[0],(CMO_ZZ)leaves[1]); }else{ ret = new CMO_TREE(name,"basic",new CMO_LIST(leaves)); } } exceptTokenTypeInParse(TT_EndTag); if(!attribute.equals("OMA")){ parse_error("We expect ''."); } }else{ parse_error("We expect ' or '' or ''."); ret = null; } return ret; } private CMO_ZZ parse_OMI() throws IOException{ CMO_ZZ ret; exceptTokenTypeInParse(TT_StartTag); if(!attribute.equals("OMI")){ parse_error("We expect ''."); } ret = (CMO_ZZ)parse_integer(); exceptTokenTypeInParse(TT_EndTag); if(!attribute.equals("OMI")){ parse_error("We expect ''."); } return ret; } private CMO_STRING parse_OMSTR() throws IOException{ CMO_STRING ret; exceptTokenTypeInParse(TT_StartTag); if(!attribute.equals("OMSTR")){ parse_error("We expect ''."); } if(readNextToken() == TT_String){ //ret = (CMO_STRING)parse_utf7(); ret = new CMO_STRING(attribute); }else{ ret = new CMO_STRING(""); pushbackLex(); } exceptTokenTypeInParse(TT_EndTag); if(!attribute.equals("OMSTR")){ parse_error("We expect ''."); } return ret; } private CMO parse_symb_DMP() throws IOException{ parse_object(); return new CMO_DISTRIBUTED_POLYNOMIAL(new CMO_DMS_GENERIC(), parse_symb_SDMP()); } private CMO_MONOMIAL32[] parse_symb_SDMP() throws IOException{ Vector mono = new Vector(); CMO_MONOMIAL32[] ret; exceptTokenTypeInParse(TT_StartTag); if(!attribute.equals("OMA")){ parse_error("We expect ''."); } if(!parse_symbol().equals("SDMP")){ parse_error("We expect ''"); } while(readNextToken() != TT_EndTag){ pushbackLex(); mono.addElement(parse_symb_Monom()); } if(!attribute.equals("OMA")){ parse_error("We expect ''."); } ret = new CMO_MONOMIAL32[mono.size()]; mono.copyInto((Object[])ret); return ret; } private CMO_MONOMIAL32 parse_symb_Monom() throws IOException{ Vector degree = new Vector(); CMO coefficient; int[] array; exceptTokenTypeInParse(TT_StartTag); if(!attribute.equals("OMA")){ parse_error("We expect ''."); } if(!parse_symbol().equals("Monom")){ parse_error("We expect ''"); } coefficient = parse_object(); if(!(coefficient instanceof CMO_ZZ || coefficient instanceof CMO_QQ || coefficient instanceof CMO_INT32 || coefficient instanceof CMO_ZERO)){ parse_error("the coefficient of Monomials must be integer or rational."); } while(readNextToken() != TT_EndTag){ pushbackLex(); degree.addElement(parse_OMI()); } if(!attribute.equals("OMA")){ parse_error("We expect ''."); } array = new int[degree.size()]; for(int i=0;i', but '"+ para.sval +"'."); } if(para.nextToken() != StreamTokenizer.TT_WORD){ parse_error("We expect 'name' or 'cd'."); } if(para.sval.equals("name")){ if(para.nextToken() != '='){ parse_error("We expect '='."); } if(para.nextToken() != '"'){ parse_error("We expect '\"'."); } ret = parse_symbname(para.sval); if(para.nextToken() != StreamTokenizer.TT_WORD || !para.sval.equals("cd")){ parse_error("We expect 'cd'."); } if(para.nextToken() != '='){ parse_error("We expect '='."); } if(para.nextToken() != '"'){ parse_error("We expect '\"'."); } parse_cdname(para.sval); }else if(para.sval.equals("cd")){ if(para.nextToken() != '='){ parse_error("We expect '='."); } if(para.nextToken() != '"'){ parse_error("We expect '\"'."); } parse_cdname(para.sval); if(para.nextToken() != StreamTokenizer.TT_WORD || !para.sval.equals("name")){ parse_error("We expect 'cd'."); } if(para.nextToken() != '='){ parse_error("We expect '='."); } if(para.nextToken() != '"'){ parse_error("We expect '\"'."); } ret = parse_symbname(para.sval); }else{ parse_error("We expect 'name' or 'cd'."); } if(para.nextToken() != StreamTokenizer.TT_EOF){ parse_error("We expect '/>'."); } return ret; } private CMO parse_integer() throws IOException{ //Attribute integer = new Attribute(value); String str; int i=0; exceptTokenTypeInParse(TT_String); str = attribute; if(str.charAt(i)=='-'){ i++; } if(str.length()>=i+2 && str.charAt(i)=='x'){ // for HEX String strhex = str.substring(0,i) + str.substring(i+1); for(i++;i=i+1){ // for DEC for(;i'."); } if(para.nextToken() != StreamTokenizer.TT_WORD || !para.sval.equals("name")){ parse_error("We expect 'name', but obtain '"+ para.sval +"'."); } if(para.nextToken() != '='){ parse_error("We expect '='."); } if(para.nextToken() != '"'){ parse_error("We expect '\"'."); } ret = new CMO_INDETERMINATE(parse_varname(para.sval)); if(para.nextToken() != StreamTokenizer.TT_EOF){ parse_error("We expect '/>'."); } return ret; } private String parse_varname(String str){ String words = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" + "0123456789+='(),-./:?!#$%*;@[]^_`{|}"; for(int i=0;i