Definition:

Define a specific grammar, for a specific kind of language parsing processing, such as, operational expressions, SQL and Android XML file parsing languages with fixed syntax.

implementation

Developer is less used in the model in the actual development, also can saying is less need to customize the parser, but he has a lot of application in the development of the scene, understand the parser model can more easily to understand architectural source, understand and parsing process more convenient and extension of existing functions, such as arithmetic is added in the law of addition and subtraction.

Its general implementation mode is as follows:


1.First create a specific grammar (abstract expression) interface:public abstract class Expression { 
    public boolean interpret(String context); 
}

2.Create an implementation class for the expression interface (terminal expressions) :public class TerminalExpression extend Expression {
    private String data;
    public TerminalExpression(String data){
        this.data = data;
    }
    @Override 
    public Object interpret(String context) {
        // Logical processing
        return null; }}// Non-terminal expressions
public class NonterminalExpression extends Expression { 
    public NonterminalExpression(Expression ... expressions) {}@Override Object interpreter(Context ctx) { 
        return null; }}// More implementation classes can be created to handle different keywords in a particular syntax
Copy the code

For example

Here is an example of an operational expression:

public abstract class Expression {
    int interpret(String info);
}

// Variable resolver
public class VariableExpression extend Expression {
    private String key;
    VariableExpression(String key) {
        this.key = key;
    }
    @Override
    public int interpreter(HashMap<String, Integer> var) { 
        return var.get(key); }}// Operator parser
public abstract class OperatorExpression extend Expression {
    private Expression varLeft;// Operator left variable
    private Expression varRight;// Operator right variable
    OperatorExpression(Expression varLeft, Expression varRight) {
        this.varLeft = varLeft;
        this.varRight = varRight; }}// Add operator parser
public class AndExpression extend OperatorExpression {
    AndExpression(Expression varLeft, Expression varRight) {
        super(varLeft, varRight)
    }
    
    @Override
    public int interpreter(HashMap<String, Integer> var) { 
        return super.varLeft.interpreter(var) + super.varRight.interpreter(var); }}// Subtraction operator parser
// Add operator parser
public class SubExpression extend OperatorExpression {
    SubExpression(Expression varLeft, Expression varRight) {
        super(varLeft, varRight)
    }
    @Override
    public int interpreter(HashMap<String, Integer> var) { 
        return super.varLeft.interpreter(var) - super.varRight.interpreter(var); }}public class Client {

    public static void main(String[] args) throws IOException {
        / / expression
        String expStr = "a+b-c";
        
        // Put the values of a, B, and c in the operatorMap
        HashMap<String, Integer> varMap;// Variable data
        
        // Parse the expression
        Expression expression = parse(expStr);
        
        // The result of the operation
        int result = expression.interpreter(varMap);
    }
    
    
    // Define the method that parses the expression (the core method of the parser, or the real parser)
    private static Expression parser(String expStr) {
        
        Stack<Expression> stack = new Stack<>(); 
        char[] charArray = expStr.toCharArray(); 
        Expression left = null; 
        Expression right = null; 
        for (int i = 0; i < charArray.length; i++) { 
        switch (charArray[i]) { 
            case '+': left = stack.pop(); 
                      right = new VariableExpression(String.valueOf(charArray[++i])); 
                      stack.push(new AddExpression(left, right)); 
                      break; 
            case The '-': 
                      left = stack.pop(); 
                      right = new VariableExpression(String.valueOf(charArray[++i])); 
                      stack.push(new SubExpression(left, right)); 
                      break; 
            default: 
                      stack.push(new VariableExpression(String.valueOf(charArray[i]))); 
                      break; }}returnexpression = stack.pop(); }}Copy the code

The specific grammar defined here is an algorithm (A + b-C), according to which the user enters the corresponding values of A, B, and C. When the user enters the algorithm, the algorithm needs to be parsed, which will parse the operation symbol, mark its left and right operation values, and store them in the data structure of the stack. The result is then computed step by step through a recursion-like call to the Interpreter () method.

Conclusion:

Will want to parse text expression made a analysis, generally can be divided into terminator and non-terminal, is similar to the example of the operator (terminator) and value (non-terminal), and they are all realized the symbolic expression interfaces, and interface by rewriting logic processing method, and the incoming symbol expression a collection of objects, Fetching an expression object from the collection in a method, the object continues to call the logical processing method, making a recursive call until the symbolic expression object terminates. Its core idea is recursive call, recursive step by step each symbol expression object parsing, the execution of the corresponding logical processing.

Application Scenarios:

Some recurring problems can be expressed in a simple language that can represent sentences in a language that needs to be interpreted as an abstract syntax tree

The advantages and disadvantages:

As can be seen, the parsing of a particular text in this way can be easily extended. For example, to modify the algorithm, only the corresponding operator class needs to change the logic processing; To add an operator, you simply create an operator class and parse the operator in the parser. Its disadvantage is that it is easy to increase the code complexity, and the efficiency is obviously not high in the recursive call process.