javacc 定义自己的全文检索语言 综合全面解析

/********************************/
>javacc jjt语法文件解析
/********************************/


/********************************/
>0.语法文件全局性配置项
options
{
  NODE_USES_PARSER = true; //如果使用观察者模式那么每一个节点都会有解析器的引用
  JDK_VERSION = "1.6"; 
  MULTI = true;            //为每一个生产表达式生成节点类
  VISITOR = true;	   //是否使用观察者模式
  NODE_DEFAULT_VOID = false; //每个节点默人生成节点
  STATIC = true;	
  USER_CHAR_STREAM = false; //是否使用定义的字符流
  UNICODE_INPUT = true;
  JAVA_UNICODE_ESCAPE = true;
}
/********************************/




/********************************/
>1.语法文件解析java逻辑单元部分
//notes:这个语法文件经过javacceclipse插件解析后生成一个java文件
//在java逻辑单元中定义的成员变量和成员方法都是可以在语法定义中调用的
PARSER_BEGIN(Parser)
package com._3_1;
import java.util.ArrayList;
import java.util.List;
public class Parser
{
  
  /** 查询单元字段域名称*/
  public static String fname="";

  /** 短语查询跨度关键词*/
  public static String s_divisor="";

  /** 短语查询查询关键词集合*/
  public static List<PhraseTerm > p_List = new ArrayList<PhraseTerm >();

  public static void setDefault_name(String name)
  {
    fname=name;
  }
  
}

PARSER_END(Parser)
/********************************/

/********************************/
>2.整个语法中涉及到的字符定义
//涉及到的字符定义就如在java中定义的变量名字中可以由哪些字符组成
//哪些字符是不可以出现的等...这些东西必须在这里定义


SKIP:
{
  " "
}//忽略空格就如name  = zhangsan
 //那么解析器在解析的时候就会忽略在这两个三个元素之间的空格


//私有字符定义有利于字符定义冲突定义的私有字符只能被别的定义引用
//而不能够在语法解析式中真正的使用到

TOKEN : {
  <#_NUM_CHAR:   ["0"-"9"] >
| <#_ESCAPED_CHAR: "\\" ~[] >

//这个定义就好像java的变量名一样首先定义它不能出现的字符然后就可以了
| <#_TERM_START_CHAR: ( ~[ " ", "\t", "\n", "\r", "\u3000", "+", "-", "!", "(", ")", ":", "^",
                           "[", "]", "\"", "{", "}", "\\","=",",",">","<","'","~","."] 
                       | <_ESCAPED_CHAR> ) >
| <#_TERM_CHAR: ( <_TERM_START_CHAR> | <_ESCAPED_CHAR>) >
| <#_WHITESPACE: ( " " | "\t" | "\n" | "\r" | "\u3000") >
| <#_QUOTED_CHAR: ( ~[ "\"", "\\" ] | <_ESCAPED_CHAR> ) >
}

TOKEN:
{
  < LPAREN:(" ")*"["(" ")*>
| < LBRACE:(" ")*"("(" ")*>
| < LSHIT:(" ")*"{"(" ")*>
| < RPAREN:(" ")*"]"(" ")*>
| < RBRACE:(" ")*")"(" ")*>
| < RSHIT:(" ")*"}"(" ")* >
}

TOKEN:
{
  < AND :
    (
     (" ")*(["A","a"]["n","N"]["d","D"])(" ")* //定义方便就这样使用
    |(" ")*"+"(" ")*
    |(" ")*"&&"(" ")*
    ) >
| < OR :
    (
    (" ")*(["O","o"]["r","R"])(" ")*
    |(" ")* "," (" ")*
    |(" ")* "||" (" ")*
    )>
| < NOT :
    (
	(" ")*(["n","N"]["O","o"]["t","T"])(" ")*
     )>
}

TOKEN:{
  < S_TO:(" ")*"-"(" ")* >
 |< R_TO:(" ")*"~"(" ")* >
}

TOKEN:
{
  < RANGE_TO :
    ((" ")*(["T","t"]["O","o"](" ")*)|(" ")*":"(" ")*
    )>
}

TOKEN:{
    < DTT:(" ")*"."(" ")* >
   |<BT:"^"<TERM>< DTT>(<TERM >)?>
   |<DT:(" ")*":"(" ")* > 
}

TOKEN :
{
  < EQUAL:(" ")* "=" (" ")* >
 |<TERM:<_TERM_START_CHAR> (<_TERM_CHAR>)*>
 |<DOUBLE_QAUOTED:"\"" > 
 |<GRATTER:(" ")*">"(" ")* >
 |<LESS:(" ")*"<"(" ")*>
}
/********************************/

/********************************/
>3.生产表达式解析
String getKeyWords()#void: //#void表示不为此生产表达式生成节点
{
  Token t = null; //getKeyWords方法局部变量声明
  Token tt = new Token();
  String bf="";
  tt.image="";
}
{
 (
   LOOKAHEAD(3) //表示向前看(三个类型)的token进行判断是否满足语法要求
   //一定要把定义多的那个表达式放在前面这样才不会有冲突
   smp_range()
   {
     return ""; //在javacc中("a"|"b"|"c")这种关系为switch关系他会通过字符的类型来判断进入那个条件分支
   }
   |(
     LOOKAHEAD(2)
    t = < TERM> tt=< R_TO>
   |(
     LOOKAHEAD(2)
      t =< TERM> bf=bf()
     |t = < TERM >
     )
  )
 )
  {
    return actual_form(t.toString()+tt.image+bf);
  }
}

ASTstart start():
{
}
{
  expr()
  {
    jjtThis.value="";
    return jjtThis;//jjtThis表示到当前节点的引用
  }
}

void expr():
{
}
{
{
  jjtThis.value="";
}
    < EOF >{return;}
   |l_brace()
   |r_brace()
   |
	 (
	  LOOKAHEAD(2)
	   field_name()
	  |elements()
	 )
}

void elements():
{
}
{
{
  jjtThis.value="";
}
   (
    LOOKAHEAD(3)
    smp_range()
    |(
       LOOKAHEAD(2)
        omit_range()
       |smp_term()
      )
     |range()
     | < DOUBLE_QAUOTED >
     {
       jjtThis.value=fname+":\"";
       phrase_term();
     }
   )
}

void phrase_field_name():
{
  Token t = null;
}
{
 t = < TERM ><EQUAL >
  {
    p_List = new ArrayList< PhraseTerm>();
    fname=t.toString().trim();
    jjtThis.value="";
    expr();
  }
}

void smp_range():
{
  Token t1 = new Token();
  Token t2 = new Token();
  String bf ="";
}
{
  t1 = < TERM> (< RANGE_TO >|< DT>) t2 =< TERM> bf = bf()
  {
    jjtThis.value=fname+":["+t1.toString()+" TO "+t2.toString()+"]"+bf;
    conj_elem();
  }
}

void smp_term():
{
  String t = "";
  String t2 ="";
  Token b = new Token();
  b.image="";
}
{
  {
    jjtThis.value="";
  }
   (
     (
    < AND >
    {
     jjtThis.value=" +";
    }
   |(< NOT>|< S_TO>)
   {
    jjtThis.value=" -";
   }
   |(
	< OR>
    {
     jjtThis.value=" OR ";
    }
    )
  )
  {
    p_List = new ArrayList< PhraseTerm>();
    expr();
  }
 |< RBRACE >
  {
    jjtThis.value=" ) ";
    smp_term();
  }
 |< EOF >
 {
   p_List = new ArrayList< PhraseTerm>();
   return;
 } 
 |< LBRACE >
  {
    jjtThis.value=" ( ";
    smp_term();
  }
 |(
    LOOKAHEAD(2)
    phrase_field_name()
   |(
       LOOKAHEAD(2)
       omit_range()
      |t =getKeyWords()
     )
    ) 
  [
  (
   ((
      LOOKAHEAD(2)
	  phrase_field_name()
	  |t2 = getKeyWords()
     )|b = < RBRACE>|b = <LBRACE >)
   {
	 String g="";
     /********************/
	 if(
	   p_List.size() >0
	   ||
	   t2.toString().matches(
	     "([w,W]{1}[0-9]*)|([w,W]{1}[f,F]{1}[0-9]*)|([n,N]{1}[E,e]{1}[a,A]{1}[R,r]{1})|([s,S]{1}[P,p]{1}[a,A]{1}[C,c]{1}[E,e]{1})")
	  )
	  {
	     /*********/
		 s_divisor=t;
		 int dis = get_s_divisor();
		 
		 if(dis==0 && !t2.equals(""))
		 {
		   s_divisor=t2;
		   dis = get_s_divisor();
		   if(dis==0)
		   {
		     t=t2;
		   }
		 }

		 if(t.toString().matches("([w,W]{1}[0-9]*)|([w,W]{1}[f,F]{1}[0-9]*)|([n,N]{1}[E,e]{1}[a,A]{1}[R,r]{1})|([s,S]{1}[P,p]{1}[a,A]{1}[C,c]{1}[E,e]{1})"))
		 {
		   t=t2;
		 }
		 
         if(s_divisor.matches("([w,W]{1}[0-9]*)|([w,W]{1}[f,F]{1}[0-9]*)|([n,N]{1}[E,e]{1}[a,A]{1}[R,r]{1})|([s,S]{1}[P,p]{1}[a,A]{1}[C,c]{1}[E,e]{1})"))
         {
           PhraseTerm pt2 = new PhraseTerm(t.toString(),dis);
           p_List.add(pt2);
           if(p_List.size() >1)
           {
             g+=fname+":\""+
             actual_form(p_List.get(p_List.indexOf(pt2)-1).getValue())+
             " "+actual_form(pt2.getValue())+"\"~"+pt2.getSlop()+" ";
           }

		   /*******/
			if(p_List.size() >2)
		     {
		       ///
		       for(int i=0;i<p_List.indexOf(pt2)-1;i++)
		       {
	              //\\\\\\
		          int sm=0;
		          //求间隔
				  for(int j=i;j<=p_List.indexOf(pt2);j++)
				  {
				    PhraseTerm ptt = p_List.get(j);
				    sm+=ptt.getSlop();
				    if(j!=0)
				    {
				    if(ptt.getValue().matches("([a-z,A-Z]*|[0-9]*)|([a-z,A-Z]*[0-9]*)|([0-9]*[a-z,A-Z]*)"))
				    {
				      sm+=1;
				    }else
				    {
				      sm+=ptt.getValue().toCharArray().length;
				    }
				   }
				  }

                   int ms=0;
                   if(pt2.getValue().matches("([a-z,A-Z]*|[0-9]*)|([a-z,A-Z]*[0-9]*)|([0-9]*[a-z,A-Z]*)"))
				    {
				      ms+=1;
				    }else
				    {
				      ms+=pt2.getValue().toCharArray().length;
				    }
				 
			      //\\\\\\
			      g+=fname+":\""+
                  actual_form(p_List.get(i).getValue())+
                  " "+actual_form(pt2.getValue())+"\"~"+(sm-ms)+" ";
		       }	      	
			   ///
		     }
		  /*******/	
           
         }else
         {
             PhraseTerm pt2 = new PhraseTerm(t.toString(),0);
             p_List.add(pt2);
             if(p_List.size() >1)
             {
	             g+=fname+":\""+
	             p_List.get(p_List.indexOf(pt2)-1).getValue()+
	             " "+pt2.getValue()+"\"~"+p_List.get(p_List.indexOf(pt2)-1).getSlop()+" ";
             }
         }
	     /*********/
	    jjtThis.value=g+b;
	  }
      /********************/
   }
  )
  {
   if(p_List.size()==0 && null!=t)
   {
     
    jjtThis.value=fname+":"+t.toString()+b+" ";
    if(null!=t2 && !t2.toString().equals(""))
    {
      jjtThis.value=jjtThis.value+fname+":"+t2.toString()+b+" ";
    }
   }
   smp_term();
   return;
  }
  ]
  {
   if(p_List.size()==0 && null!=t && !t.equals(""))
   {
    jjtThis.value=fname+":"+t.toString()+" ";
   }
    p_List = new ArrayList<PhraseTerm>();
    expr();
  })
  
}

void range():
{
  String bf = "";
  Token t1 =null;
  Token t2 = null;
  Token lparen=null;
  Token rparen=null;
}
{
   (lparen = < LPAREN > |lparen=< LSHIT>)
    (
      (
        t1= < TERM>)[< RANGE_TO >|<S_TO>|< R_TO>|< DT>][t2=< TERM>](rparen = < RPAREN > |rparen = < RSHIT>)bf = bf()
      {
        if(null!=t2)
        {
         jjtThis.value=" "+fname+":"+lparen.toString()+t1.toString()
        +" TO "+t2.toString()+rparen.toString()+bf;
        }else
        {
        jjtThis.value=" "+fname+":"+lparen.toString()+t1.toString().split("~")[0].trim()
        +" TO "+t1.toString().split("~")[1].trim()+rparen.toString()+bf;
		}
        conj_elem();
        return;
      }
     )
    	[< RANGE_TO >|< R_TO>|< S_TO>|< DT>] //["a"|"b"]这种用法是很有用的他表示可有可无的意思很灵活
   (
     t2= < TERM>
   )
   (rparen = < RPAREN > |rparen = < RSHIT>)
    bf = bf()
   {
      jjtThis.value=" "+fname+":"+lparen.toString()+t1+" TO "+t2+rparen.toString()+bf;
      conj_elem();
   }
}

void omit_range():
{
  Token v1=new Token();
  Token v2=new Token();
  Token t=null;
  String bf="";
}
{
    (
      v1= < TERM>
    )
  (
   t = < GRATTER>
  |t = < LESS>
  )
   (
      v2=< TERM>
    )
    bf = bf()
  {
    fname=v1.toString();
    String v = v1+t.toString()+v2;
    String name = v.split("[>,<]")[0];
    String vv = v.split("[>,<]")[1];
	String s = "";
	//name>50
    if (v.contains(">")) {
		v = name + ":[" + vv + " TO " + Long.MAX_VALUE + "]";
	 } else if (v.contains("<")) {
		v = name + ":[" + 0 + " TO " + vv + "]";
	 }
	 
    jjtThis.value=v+bf;
    start();
  }
}

String bf():
{
  Token t=new Token();
  t.image="";
}
{
    {
      jjtThis.value="";
    }
  [t = <BT >]
  {
    return t.toString();
  }
}

void phrase_term():
{
  String v="";
  String bf="";
  Token sp = new Token();
  sp.image="";
}
{
  (
   (
   v = getKeyWords()
   )
    {
      jjtThis.value=v+" ";
      phrase_term();
    }
  |< DOUBLE_QAUOTED>
   [(<R_TO >sp = < TERM>)]bf = bf()
  {
    if(null!=sp)
    {
	  jjtThis.value="\"~"+sp.toString()+bf;
	  start();
    }else
    {
      jjtThis.value="\"";
      start();
    }
  }
  )
}

void l_brace():
{
}
{
  < LBRACE >
  {
    jjtThis.value=" ( ";
    expr();
  }
}

void r_brace():
{
}
{
  < RBRACE >
  {
    jjtThis.value=" ) ";
    expr();
  }
}

void conj_elem():
{
}
{
  (
    < AND >
    {
      jjtThis.value=" +";
    }
   |(< NOT>|< S_TO>)
   {
    jjtThis.value=" -";
   }
   |(
    LOOKAHEAD(2)
	(< OR>)+
    {
     jjtThis.value=" OR ";
    }
    |(<OR>)? //这个?号很有用他表示可以出现一次或者不出现都满足这种条件用的很巧妙对整个程序的解难性非常有帮助
    {
     jjtThis.value=" ";
    }
    )
  )
  {
    expr();
  }
}

void field_name():
{
  Token t = null;
}
{
 t = < TERM ><EQUAL >
  {
    fname=t.toString().trim();
    jjtThis.value="";
    expr();
  }
}

String actual_form(String v) #void:
{
}
{
  {
 	if(v.trim().contains("~"))
 	{
 	 v = v.replaceAll("~","");
 	 v+="~0.5";
 	}else if(v.trim().contains("%"))
 	{
 	 v=v.replaceAll("%","");
 	 v+="~0.5";
 	}else if(v.trim().contains("#"))
 	{
 	  v=v.replaceAll("#","");
 	  v+="~0.5";
 	}
 	return v;
}
}

//javacc的语法用到很多语言的语法在其中正则表达式的语法完全可以在java中用
int get_s_divisor()#void :
{
  int divisor=0;
}
{
  {
   String d=s_divisor.trim();
   if(d.equals(""))
   {
     return 0;
   }
   if(d.matches("[n,N][E,e][a,A][r,R]"))
  {
    divisor = 5;
  }else if(d.matches("[S,s][p,P][a,A][c,C][E,e]"))
  {
    divisor = 1;
  }else if(d.matches("[w,W][0-9]*"))
  {
    divisor = Integer.valueOf(d.split("[w,W]")[1]);
  }else if(d.matches("[w,W][f,F][0-9]*"))
  {
    divisor = Integer.valueOf(d.split("[w,W][F,f]")[1]);
  }
  {
 }
  return divisor;
}
}
/********************************/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值