Java词法分析器jflex

本文以表达式识别为例,介绍了如何利用jflex进行词法分析,涉及标识符、and、or操作符及括号的处理。通过%token和%type定义终端和非终端符类型,最终将解析的表达式存储到全局变量中。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

以表达式识别为例,包括标识符、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());
	}
//Makefile
parser: 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)




                
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值