All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.paoding.rose.jade.statement.jexl.Jexl3Analysis Maven / Gradle / Ivy

package net.paoding.rose.jade.statement.jexl;


import net.paoding.rose.jade.excetion.JadeException;
import net.paoding.rose.jade.statement.jexl.analysis.Analysis;
import net.paoding.rose.jade.statement.jexl.analysis.impl.ForAnalysis;
import net.paoding.rose.jade.statement.jexl.analysis.impl.IfElseAnalysis;
import net.paoding.rose.jade.statement.jexl.analysis.impl.JoinAnalysis;
import net.paoding.rose.jade.statement.jexl.analysis.impl.TxtAnalysis;
import net.paoding.rose.jade.statement.jexl.analysis.impl.VariableAnalysis;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.regex.Matcher;

/**
 * jexl3 表达式解析
 * @author fusheng.zhang
 * @date 2022-03-03 14:48:35
 */
public class Jexl3Analysis {

    /**
     * 带解析语句 源语
     */
    private final String sourceLanguage;
    /**
     * 编译位置
     */
    private int position;
    /**
     * 组装位置
     */
    private int fromIndex;

    private final Matcher sourceLanguageMatcher;
    /**
     * #else Matcher
     */
    private final Matcher elseMatcher;

    private final List result = new ArrayList<>();

    public Jexl3Analysis(String sourceLanguage) {
        this.sourceLanguage = sourceLanguage;
        this.sourceLanguageMatcher = Jexl3Constant.PATTERN_KEYWORD.matcher(this.sourceLanguage);
        this.elseMatcher = Jexl3Constant.PATTERN_ELSE.matcher(sourceLanguage);
    }


    public List compile() {
        try {
            while (sourceLanguageMatcher.find(position)) {
                position = sourceLanguageMatcher.end();
                String expr = sourceLanguageMatcher.group(1),
                        group = sourceLanguageMatcher.group(2),
                        keyword = sourceLanguageMatcher.group(3);
                boolean isIn = false;
                if (Objects.nonNull(expr)) {
                    if (sourceLanguageMatcher.start() > fromIndex) {
                        TxtAnalysis txtAnalysis = new TxtAnalysis(sourceLanguage.substring(fromIndex, sourceLanguageMatcher.start()));
                        isIn = Jexl3Constant.PATTERN_IN.matcher(txtAnalysis.getTxt()).find();
                        this.result.add(txtAnalysis);
                    }
                    // 创建  :expr | $expr 形式的子句
                    if (expr.charAt(0) == Jexl3Constant.KEYWORD_$_) {
                        this.result.add(new JoinAnalysis().setJoinExp(expr));
                    } else {
                        this.result.add(new VariableAnalysis(expr, isIn));
                    }
                } else if (Objects.nonNull(group)) {
                    this.result.addAll(new Jexl3Analysis(group).compile());
                } else if (Objects.isNull(keyword)) {
                    expr = parentheses();
                    if (Objects.nonNull(expr)) {
                        if (sourceLanguageMatcher.start() > fromIndex) {
                            TxtAnalysis txtAnalysis = new TxtAnalysis(sourceLanguage.substring(fromIndex, sourceLanguageMatcher.start()));
                            isIn = Jexl3Constant.PATTERN_IN.matcher(txtAnalysis.getTxt()).find();
                            this.result.add(txtAnalysis);
                        }
                        this.result.add(new VariableAnalysis(expr, isIn));
                    }
                } else {
                    switch (keyword) {
                        case Jexl3Constant.KEYWORD_IF: ifElse();
                            break;
                        case Jexl3Constant.KEYWORD_FOR: forLoop();
                            break;
                        case Jexl3Constant.KEYWORD_SHARP: case Jexl3Constant.KEYWORD_JOIN: join();
                            break;
                    }
                }
                fromIndex = position;
            }
            // 写入 PREFIX 字符后的内容。
            if (fromIndex < sourceLanguage.length()) {
                this.result.add(new TxtAnalysis(sourceLanguage.substring(fromIndex)));
            }
        } catch (Exception e) {
            throw new JadeException(e.getMessage(), e);
        }
        return this.result;
    }

    private void join() {
        String joinStr = parentheses();
        if (Objects.nonNull(joinStr)) {
            if (sourceLanguageMatcher.start() > fromIndex) {
                this.result.add(new TxtAnalysis(sourceLanguage.substring(fromIndex, sourceLanguageMatcher.start())));
            }
            this.result.add(new JoinAnalysis().setJoinExp(joinStr));
        }
    }

    private void forLoop() {
        // 获取括号内容
        String forCondition = parentheses();
        if (Objects.nonNull(forCondition)) {
            if (sourceLanguageMatcher.start() > fromIndex) {
                this.result.add(new TxtAnalysis(sourceLanguage.substring(fromIndex, sourceLanguageMatcher.start())));
            }
            ForAnalysis forAnalysis = new ForAnalysis();

            // 解析  variant in :expr 表达式
            Matcher matcherIn = Jexl3Constant.PATTERN_IN.matcher(forCondition);
            if (matcherIn.matches()) {
                forAnalysis.setVariable(matcherIn.group(1));
                forCondition = matcherIn.group(2);
            }
            forAnalysis.setForCondition(forCondition);
            // for 执行语句{}
            String forExecute = braces();
            if (Objects.nonNull(forExecute)) {
                List analysisResult = new Jexl3Analysis(forExecute).compile();
                if (analysisResult.isEmpty()) {
                    forAnalysis.setForExecute(forExecute);
                } else {
                    forAnalysis.setForAnalyses(analysisResult);
                }
            }
            this.result.add(forAnalysis);
        }
    }

    private void ifElse() {
        // 获取if条件语句 ()
        String ifCondition = parentheses();
        if (Objects.nonNull(ifCondition)) {
            if (sourceLanguageMatcher.start() > fromIndex) {
                this.result.add(new TxtAnalysis(sourceLanguage.substring(fromIndex, sourceLanguageMatcher.start())));
            }
            // 构建 if 表达式
            IfElseAnalysis ifElseAnalysis = new IfElseAnalysis();
            ifElseAnalysis.setIfCondition(ifCondition);
            // 获取if执行语句 {}
            String ifExecute = braces();
            if (Objects.nonNull(ifExecute)) {
                List analysisResult = new Jexl3Analysis(ifExecute).compile();
                if (analysisResult.isEmpty()) {
                    ifElseAnalysis.setIfExecute(ifExecute);
                } else {
                    ifElseAnalysis.setIfAnalyses(analysisResult);
                }
            }
            // 判断是否存在 else,如果是则步进5
            if (this.startElse()) {
                this.position += 5;
                // 获取 else执行语句{}
                String elseExecute = braces();
                if (Objects.nonNull(elseExecute)) {
                    List analysesResult = new Jexl3Analysis(elseExecute).compile();
                    if (analysesResult.isEmpty()) {
                        ifElseAnalysis.setElseExecute(elseExecute);
                    } else {
                        ifElseAnalysis.setElseAnalyses(analysesResult);
                    }
                } else {
                    this.position -= 5;
                }
            }
            this.result.add(ifElseAnalysis);
        }
    }

    public boolean startElse() {
        return elseMatcher.find(this.position) && elseMatcher.group().equals(Jexl3Constant.KEYWORD_ELSE);
    }

    /**
     * 匹配大括号
     * @return
     */
    private String braces() {
        return findBrace('{', '}');
    }

    /**
     * 匹配小括号
     * @return
     */
    private String parentheses() {
        return findBrace('(', ')');
    }


    /**
     * 查找匹配的左括号, 忽略之前的空白字符。
     * 

* 如果未找到匹配的左括号,函数返回 -1. * @param chLeft - 匹配的左括号 * @param fromIndex - 查找的起始位置 * @return 左括号的位置, 如果未找到匹配的左括号,函数返回 -1. */ private int findLeftBrace(char chLeft, int fromIndex) { // 查找出现的左括号。 for (int index = fromIndex; index < sourceLanguage.length(); index++) { char ch = sourceLanguage.charAt(index); // 如果出现左括号,返回。 如果出现非空白字符,返回 - 1. if (ch == chLeft) { return index; } else if (!Character.isWhitespace(ch)) { return -1; } } // 没有找到匹配的括号。 return -1; } /** * 查找匹配的右括号, 可以用于匹配 '{}', '[]', '()' 括号对。 *

* 如果未找到匹配的右括号,函数返回 -1. * @param chLeft - 匹配的左括号 * @param chRight - 匹配的右括号 * @param fromIndex - 查找的起始位置 * @return 右括号的位置, 如果未找到匹配的右括号,函数返回 -1. */ private int findRightBrace(char chLeft, char chRight, int fromIndex) { // 记录括号层级。 int level = 0; // 查找匹配的右括号。 for (int index = fromIndex; index < sourceLanguage.length(); index++) { char ch = sourceLanguage.charAt(index); // 如果出现左括号,重叠级别增加。如果出现右括号,重叠级别降低。 if (ch == chLeft) { level++; } else if (ch == chRight) { // 找到右括号。 if (level == 0) return index; level--; } } // 没有找到匹配的括号。 return -1; } /** * 从当前位置查找匹配的一对括号, 并返回内容。 *

* 如果有匹配的括号, 返回后的当前位置指向匹配的右括号后一个字符。 * @param chLeft - 匹配的左括号 * @param chRight - 匹配的右括号 * @return 返回括号内容, 如果没有括号匹配, 返回 null. */ private String findBrace(char chLeft, char chRight) { // 从当前位置查找查找匹配的 (...) int left = findLeftBrace(chLeft, position); if (left >= position) { int start = left + 1; int end = findRightBrace(chLeft, chRight, start); if (end >= start) { // 当前位置指向匹配的右括号后一个字符 position = end + 1; // 返回匹配的括号内容 return sourceLanguage.substring(start, end); } } return null; // 没有 (...) 匹配 } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy