以表达式识别为例,包括标识符、and、or,括号
例如:condi1=5 and condi6=6 and (condi7=7 or (condi8=8 and condi9=9))
//Expr.java
public abstract class Expr{
abstract void print();
}
//andExpr.java
public class andExpr extends Expr{
public andExpr(Expr l, Expr r){
lexpr = l;
rexpr = r;
}
public void print(){
lexpr.print();
System.out.print( " and ");
rexpr.print();
}
Expr lexpr;
Expr rexpr;
}
//assignExpr.java
public class assignExpr extends Expr{
public assignExpr(String name, Integer val){
id = name;
num= val;
}
public void print(){
System.out.print(id + " = " + num);
}
String id;
Integer num;
}
//orExpr.java
public class orExpr extends Expr{
public orExpr(Expr l, Expr r){
lexpr = l;
rexpr = r;
}
public void print(){
lexpr.print();
System.out.print( " or ");
rexpr.print();
}
Expr lexpr;
Expr rexpr;
}
//quoteExpr.java
public class quoteExpr extends Expr{
public quoteExpr(Expr e){
inner = e;
}
public void print(){
System.out.print( " ( " );
inner.print();
System.out.print( " ) ");
}
Expr inner;
}
//global.java
public class global{
public static Expr root = null;
public static void tomongodb(){
//
root.print();
System.out.println("");
}
}
//gram.jflex 词法分析
%%
%class scanner
%unicode
%line
%column
%byaccj
%{
/* store a reference to the parser object */
private Parser yyparser;
/* constructor taking an additional parser */
public scanner (java.io.Reader r, Parser yyparser) {
this (r);
this.yyparser = yyparser;
}
/* return the current line number. We need this
because yyline is made private and we don't have
a mechanism like extern in C. */
public int getLine() {
return yyline;
}
%}
%%
and {return Parser.AND_T;}
or {return Parser.OR_T;}
\( {return (int) yycharat(0);}
\) {return (int) yycharat(0);}
= {return (int) yycharat(0);}
[a-zA-Z][a-zA-Z0-9]* {
yyparser.yylval = new ParserVal( yytext() );
return Parser.ID;
}
[+-]?[0-9]+ {
yyparser.yylval = new ParserVal( Integer.parseInt(yytext()) );
return Parser.NUM;
}
[ \t\n] { }
//gram.y 语法分析
%{
import java.io.*;
%}
%token <sval> ID
%token <ival> NUM
%type<obj> expression
%type<obj> source_text
%left AND_T OR_T
%start source_text
%%
source_text :
expression { global.root = (Expr)((ParserVal)$1).obj; $$ = $1; }
expression : expression AND_T expression { $$ = new ParserVal(new andExpr( (Expr)((ParserVal)$1).obj, (Expr)((ParserVal)$3).obj )); }
| expression OR_T expression { $$ = new ParserVal(new orExpr( (Expr)((ParserVal)$1).obj, (Expr)((ParserVal)$3).obj )); }
| ID '=' NUM { $$ = new ParserVal(new assignExpr( $1, $3 ));}
| '(' expression ')' { $$ = new ParserVal(new quoteExpr( (Expr)((ParserVal)$2).obj )); }
;
%%
/* reference to the lexer object */
private scanner lexer;
/* interface to the lexer */
private int yylex() {
int retVal = -1;
try {
retVal = lexer.yylex();
} catch (IOException e) {
System.err.println("IO Error:" + e);
}
return retVal;
}
/* error reporting */
/* constructor taking in File Input */
public Parser (Reader r) {
lexer = new scanner (r, this);
}
public static void main (String [] args) throws IOException {
Parser yyparser = new Parser(new InputStreamReader(System.in));
yyparser.yyparse();
global.tomongodb();
}
/* error reporting */
public void yyerror (String error) {
System.err.println("Error : " + error + " at line " + lexer.getLine());
}
//Makefileparser: Parser.java scanner.java
javac *.java
Parser.java: gram.y
byaccj -J gram.y
scanner.java: gram.jflex
jflex gram.jflex
clean:
rm *.class scanner.java Parser.java ParserVal.java
run:
java Parser < in
//in 输入文件内容
condi1=5 and condi6=6 or (condi7=7 and condi8=8)
%token定义终端符类型,%type定义非终端符类型
归结到根source_text时,我们把构造的表达式保存到别处(global)