⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 parsesubst.java

📁 java xml开发指南(初学者推荐)Java Xml 编程指南书籍源码
💻 JAVA
字号:
package MyNa.utils;
import java.io.*;
import java.util.*;
import java.sql.SQLException;
/* *****************************************************************
The ParseSubst class introduces minilanguage processing at the
parse-tree level, but in this case we have only a list of lists.
Consider the sample input string inStr=
  "The time <myna:SUBST> has come, |speaker1| said, to |communicateAbout|
  many </myna:SUBST> things, of <myna:SUBST delim="$"> $topicA$ and $topicB$, 
  of $topicC$ and $topicD$</myna:SUBST>; of why the sea is boiling hot, and 
  whether pigs have wings."
If we now say
 ParseSubst pS=new ParseSubst(new StringBuffer(inStr));
we are breaking the inStr up as if it were labelled as follows:
<ROOT>
  <TEXT>The time </TEXT>
  <myna:SUBST>
     <TEXT> has come, </TEXT>
     <DELIM>speaker1</DELIM>
     <TEXT> said, to </TEXT>
     <DELIM>communicateAbout</DELIM>
     <TEXT>  many </TEXT>
  </myna:SUBST>
  <TEXT> things, of </TEXT>
  <myna:SUBST delim="$">
    <TEXT> </TEXT>
    <DELIM>topicA</DELIM>
    <TEXT> and </TEXT>
    <DELIM>topicB</DELIM>
    <TEXT>,   of </TEXT>
    <DELIM>topicC</DELIM>
    <TEXT> and </TEXT>
    <DELIM>topicD</DELIM>
  </myna:SUBST>
  <TEXT>; of why the sea is boiling hot, and 
    whether pigs have wings.</TEXT>

We now see that
  pS.theTree.numChildren()==5
  pS.getText(pS.theTree.child(1).child(0))==" has come, "
and in an Env where speaker1="the Walrus", we see
  pS.getVal(pS.theTree.child(1).child(1))=="the Walrus"

and so on. Actually, theTree is not public, but this should
indicate the structures generated. Note that although
   pS.theTree.child(1).child(0).getText()==" has come, "
would be more intuitive, it isn't true: the tree does not
know how to interpret itself as a text. The ParseSubst object
has additional data, namely the input stringbuffer and the env.

We work with a grammar which is not completely context-free:
  Root ::= T (Subst T)* ;
  Subst ::= SubstTok(tok,d) T (Delim(d) T)* EndTok(tok);
  Delim(d) ::= d T d;


Read this as follows: The input contains initial text, and then
zero or more repetitions of a Subst followed by more text. A
Subst begins with a SubstTok (defining the actual token and delim
to be used), and it ends with a matching endTok (thus <myna:SUBST> will
end with </myna:SUBST> but <myna:SUBSTROW> will end with </myna:SUBSTROW>.
 In between we have initial text, then zero or more repetitions of
a Delim followed by more text. Finally, we see that a Delim begins
and ends with the defined delimiter, and has plain text in between.
  
***************************************************************** */
public class ParseSubst {
  StringBuffer theBuff; String theString; 
  MyNaLex lex=null;
  ParseTree theTree=null; 
  Env theEnv=null; RowSequence theRows=null;
  boolean substFailure;
  StringBuffer outBuff;
  Logger lg;

public String toString(Env env) throws ParseSubstException{
  theEnv=env; 
  outBuff=new StringBuffer();
  toStringBuffer(theTree);
  return outBuff.toString();
}
public String toString(RowSequence rows) throws ParseSubstException{
  theRows=rows;
  if(null==rows)throw new ParseSubstException("empty RowSequence in toString");
  theEnv=theRows.getRow(); 
  outBuff=new StringBuffer();
  toStringBuffer(theTree);
  return outBuff.toString();
}
public String getText(ParseTree T){
  int low=T.getLow(); int high=T.getHigh();
  if(low>=high)return "";
  return theString.substring(low,high);
}
public String getVal(ParseTree T){
  int low=T.getLow(); int high=T.getHigh();
  if(low>=high)return "";
  return theEnv.getStr(theString.substring(low,high));
}

String treeReport(ParseTree T){
  if(T==null)return "<NULLTREE>";
  String tag=T.getTagName();
  String S="<"+tag+">";
  for(int i=0;i<T.numChildren();i++)
    S+=treeReport(T.child(i));
  if("TEXT".equals(tag))S+=getText(T);
  S+="</"+tag+">";
  return S;
}
String treeReport(){return treeReport(theTree);}

public void toStringBuffer(ParseTree T) throws ParseSubstException{
  if(T==null)return;
  int N=T.numChildren(); 
  String tag=T.getTagName();
  if(tag.equals("ROOT"))
    for(int i=0;i<N;i++)
      toStringBuffer(T.child(i));
  else if(tag.equals("TEXT"))
    outText(T);
  else if(tag.startsWith("myna:"))
    substStringBuffer(tag,T);
  else throw new ParseSubstException("expected ROOT or 'myna:', found "+tag);
}

public void newQuery(ParseTree T) throws ParseSubstException{
  Hashtable H=T.getProps(); 
  if(H==null)return; 
  String theOp=(String)H.get("dbOperation");
  if(theOp==null)return;
  theEnv.addHashtable(H);
  DBHandler theDBHandler=(DBHandler)theEnv.get("dbHandler");
  if(theDBHandler==null)
    throw new ParseSubstException("no dbhandler for op "+theOp);
  try{
    theRows=theDBHandler.getQueryRows(theEnv);
  }catch(SQLException ex){
    throw new ParseSubstException("dbHandler for op "+theOp+
             "failed with SQLException "+ex);
  }
}
public void doDef(ParseTree T) throws ParseSubstException{
  Hashtable H=T.getProps(); String name;
  if(H==null || null==(name=(String)H.get("name")))
    throw new ParseSubstException("SUBSTDEF needs a 'name' property");
  StringBuffer valBuff=new StringBuffer();
  outSubVals(T,valBuff);
  theEnv.put(name,valBuff.toString());
  }
  
   
public void substStringBuffer(String tag,ParseTree T) throws ParseSubstException{
  newQuery(T);
  if(tag.equals("myna:SUBST")) outSubVals(T);
  else if(tag.equals("myna:SUBSTROW")){
    if(substFailure || null==theRows || 
       !theRows.next())
      {substFailure=true; return;}
    else {
      theEnv=theRows.getRow();
      outSubVals(T);
      }
    } else if(tag.equals("myna:SUBSTERR")){
      if(substFailure) outSubVals(T);
    } else if(tag.equals("myna:SUBSTROWLIST")){
      if(substFailure || null==theRows)return;
      while(theRows.next()){
        theEnv=theRows.getRow();
        outSubVals(T);
        }
    } else if(tag.equals("myna:SUBSTDEF"))doDef(T);      
    else throw new ParseSubstException("unrecognized tag "+tag);
}

public void outSubVals(ParseTree T){
  int N=T.numChildren();
  for(int i=0;i<N;i++)
    if(T.child(i).getTagName().equals("DELIM"))
      outVal(T.child(i));
    else outText(T.child(i));
}
  
public void outText(ParseTree T){
  int low=T.getLow(); int high=T.getHigh();
  if(low>=high)return;
  outBuff.append(theString.substring(low,high));
}
public void outVal(ParseTree T){
  int low=T.getLow(); int high=T.getHigh();
  if (low>=high)return;
  outBuff.append(theEnv.getStr(theString.substring(low,high)));
}

/* copy the three "out" functions for generating output
text and values, give them a StringBuffer as explicit param;
now they can be used to generate definitions which are not
sent to the output but placed in the Env. */

public void outSubVals(ParseTree T,StringBuffer sB){
  int N=T.numChildren();
  for(int i=0;i<N;i++)
    if(T.child(i).getTagName().equals("DELIM"))
      outVal(T.child(i),sB);
    else outText(T.child(i),sB);
}
public void outText(ParseTree T,StringBuffer sB){
  int low=T.getLow(); int high=T.getHigh();
  if(low>=high)return;
  sB.append(theString.substring(low,high));
}
public void outVal(ParseTree T,StringBuffer sB){
  int low=T.getLow(); int high=T.getHigh();
  if (low>=high)return;
  sB.append(theEnv.getStr(theString.substring(low,high)));
}


public String context(int n,int m){
  if(n>=m)return "[no context:"+n+">="+m+"]";
  if(n>=theString.length()) return 
    "[no context: "+n+">= string length "+theString.length()+"]";
  if(m>=theString.length())return theString.substring(n,theString.length());
  return theString.substring(n,m);
}

public ParseSubst(StringBuffer sB) throws ParseSubstException{
  if(sB==null)throw new ParseSubstException("can't parse null string buffer");
  theBuff=sB;
  theString=sB.toString();
  lex=new MyNaLex(theBuff);
  lg=new Logger();  
  theTree=parseRoot();
//  lg.logIt(treeReport(theTree));
  substFailure=false;
}

  // Root ::= (T | Subst)* ;

public ParseTree parseRoot() throws ParseSubstException{
  ParseTree root=new ParseTree("ROOT",0,theString.length());
  int tokType=lex.getToken();
  while(MyNaLex.endAllToken!=tokType){
    if(tokType==MyNaLex.noToken)
      throw new ParseSubstException("ERROR: Bad token at parseRoot:\n "
                          +lex.context());
    int lo=lex.getTokenStart(); int hi=lex.getTokenEnd();
    if(tokType==MyNaLex.textToken)
      root.addChild(new ParseTree("TEXT",lo,hi));
    else if(tokType==MyNaLex.mynaToken)
      root.addChild(parseSub(lo,hi));
    else throw new ParseSubstException("ERROR: Bad token at beginning:\n "
                              +lex.context());
    tokType=lex.getToken();
    }
  return root;
}

//  Subst ::= SubstTok(tok,d) T (Delim(d) T)* EndTok(tok);


public ParseTree parseSub(int lo, int hi) throws ParseSubstException{
  // the current token is a mynaToken, or we wouldn't be here.
  Hashtable tokProps=lex.getTokenProps();
  String tagName=theString.substring(lo,hi);
  ParseTree pS=new ParseTree(tagName,lo,hi,tokProps);
  int tokType; 
  while(MyNaLex.textToken==(tokType=lex.getToken())){
    pS.addChild(new ParseTree("TEXT",
                lex.getTokenStart(),
                lex.getTokenEnd()));
    if(MyNaLex.textToken!=(tokType=lex.getToken()))break;
      // textToken values are TEXT, DELIM alternately.
    pS.addChild(new ParseTree("DELIM",
                lex.getTokenStart(),
                lex.getTokenEnd()));
   }
  String closeTag=null;
  if(tokType!=MyNaLex.endMynaToken
     || !tagName.equals(closeTag=lex.getTokenString()) ) 
    throw new ParseSubstException("ERROR: <XMP>expecting ["+tagName+
                          "], found ["+closeTag+"]\n"+
                         lex.context()+"</XMP>");
  return pS;
}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -