idea使用antlr_ANTLR4实践笔记

Query.g4:

grammar Query;

// parser

query : expr;

expr : SELECT result FROM repo (WHERE orCondition SEMI)?;

result : resultType (COMMA resultType)*;

resultType : 'class'

| 'method'

| 'package'

| 'dependenceGraph'

| 'controlFlowFraph'

| 'callGraph';

repo : app (COMMA app)*;

app : '[' ID ']';

// TODO 改为与或表达式

orCondition : andCondition (operator=OR andCondition)*

;

andCondition : conditionExpr (operator=AND conditionExpr)*

;

conditionExpr : conditionLeft op=('=' | '!=') conditionRight;

conditionLeft : app DOT type DOT attr;

conditionRight : STRING;

type: 'package'

| 'class'

| 'method';

attr : 'name'

| 'type'

| 'visibility'

| 'isAbstract';

// keyword

SELECT : 'select';

FROM : 'from';

WHERE : 'where';

AND : 'and';

OR : 'or';

NOT : 'not';

COMMA : ',';

SEMI : ';';

DOT : '.';

// lexer

ID : Letter LetterOrDigit*;

STRING

: '\'' ( ~('\''|'\\') | ('\\' .) )* '\''

| '"' ( ~('"'|'\\') | ('\\' .) )* '"'

;

fragment Letter: [a-zA-Z_];

fragment Digit : ('0' .. '9') +;

fragment LetterOrDigit: Letter | Digit;

WS : [ \t\n\r]+ -> skip ;

QueryListenerImp.java:

package modelQuery.parser;

import org.antlr.v4.runtime.tree.ParseTreeProperty;

import java.util.HashSet;

public class QueryListenerImp extends QueryBaseListener {

HashSet resultSet = new HashSet<>();

HashSet appSet = new HashSet<>();

StringBuilder condition = new StringBuilder();

boolean Sign = false;

public ParseTreeProperty values = new ParseTreeProperty<>();

@Override

public void exitExpr(QueryParser.ExprContext ctx) {

if(Sign)

return;

else {

System.out.println("resultSet: " + resultSet);

System.out.println("appSet: " + appSet);

System.out.println("condition: " + values.get(ctx.orCondition()));

// 后面调用XQuery查询xml信息库中内容

}

}

@Override

public void exitResultType(QueryParser.ResultTypeContext ctx) {

resultSet.add(ctx.getText());

System.out.println("exitResultType: " + ctx.getText());

}

@Override

public void exitRepo(QueryParser.RepoContext ctx) {

for(QueryParser.AppContext appCtx : ctx.app()) {

appSet.add(appCtx.getText());

}

}

@Override

public void exitOrCondition(QueryParser.OrConditionContext ctx) {

if(ctx.operator != null){

values.put(ctx, values.get(ctx.andCondition(0)) + " or " + values.get(ctx.andCondition(1)));

} else {

}

values.put(ctx, values.get(ctx.andCondition(0)));

}

@Override

public void exitAndCondition(QueryParser.AndConditionContext ctx) {

if(ctx.operator != null) {

values.put(ctx, values.get(ctx.conditionExpr(0)) + " and " + values.get(ctx.conditionExpr(1)));

} else {

values.put(ctx, values.get(ctx.conditionExpr(0)));

}

}

@Override

public void exitConditionExpr(QueryParser.ConditionExprContext ctx) {

String left = values.get(ctx.conditionLeft());

values.put(ctx, left + ctx.op.getText() + ctx.conditionRight().getText());

}

@Override

public void exitConditionLeft(QueryParser.ConditionLeftContext ctx) {

String app = ctx.app().getText();

if(!appSet.contains(app)) {

System.err.println(ctx.start.getLine() + ":" + ctx.start.getStartIndex() + ", variable " + ctx.app().getText() + " not defined");

Sign = true;

return;

} else {

String type = ctx.type().getText();

String attr = ctx.attr().getText();

values.put(ctx, "$x/" + type + "/@" + attr);

}

}

}

最后可以测试如下语句:

select class,method, package from [aa],[bb]

where [app].method.name = "yyf"

and [app].class.name = "www";

利用IDEA插件可以看到解析的语法树:

test.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值