/*
* $OpenXM: OpenXM/src/OpenMath/OM2OXM.java,v 1.26 2000/10/11 08:32:13 ohara 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 ORG.openxm.tam.*;
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){
OXmessage message = asir.receive();
if(message.getTag() == OXmessage.OX_DATA){
System.err.println("=> "+ CMO2OM((CMO)message.getBody()));
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.NULL:
return "0";
case CMO.INT32:
return ""+ ((CMO_INT32)cmo).intValue() +"";
// case CMO.DATUM:
case CMO.STRING:
return ""+ ((CMO_STRING)cmo).getString() +"";
case CMO.LIST:
ret += "";
{
CMO ob[] = ((CMO_LIST)cmo).getElements();
for(int i=0;i";
return ret;
case CMO.MONOMIAL32:
ret += "";
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.ZZ:
return ""+ ((CMO_ZZ)cmo).BigIntValue() +"";
case CMO.QQ:
return ""+
CMO2OM_sub(((CMO_QQ)cmo).getBunshi())+
CMO2OM_sub(((CMO_QQ)cmo).getBunbo())+
"";
case CMO.ZERO:
return " 0 ";
// case CMO.DMS:
case CMO.DMS_GENERIC:
ret += "";
ret += "2";
return ret;
case CMO.RECURSIVE_POLYNOMIAL:
return CMO2OM_CoefficientOfRecursivePOLYNOMIAL(((CMO_RECURSIVE_POLYNOMIAL)cmo).getPolynomial(),((CMO_RECURSIVE_POLYNOMIAL)cmo).getVariables());
case 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.POLYNOMIAL_IN_ONE_VARIABLE:
case 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.INDETERMINATE:
return "";
case 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