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

com.barrybecker4.simulation.lsystem.model.expression.LExpressionParser Maven / Gradle / Ivy

// Copyright by Barry G. Becker, 2013. Licensed under MIT License: http://www.opensource.org/licenses/MIT
package com.barrybecker4.simulation.lsystem.model.expression;

import com.barrybecker4.common.expression.ExpressionParser;
import com.barrybecker4.common.expression.Tokens;
import com.barrybecker4.common.expression.TreeNode;

import java.util.ArrayList;
import java.util.List;

/**
 * Parses the text form of an L-system expression into a tree representation.
 * @author Barry Becker
 */
public class LExpressionParser extends ExpressionParser {

    /** Constructor */
    public LExpressionParser() {
        super(new LOperatorsDefinition());
    }

    /**
     * Recursive method to find all the tree nodes for the terms a the current level.
     * For example, given this expression
     * FF(F(-F)(++F)
     * the items in []'s represent the array of nodes returned.
     * [FF][F(-F)][++F]
     * The parts that were in ()'s become their own subtrees via recursive calls.
     *
     * @param exp the expression to get the nodes at the current level for
     * @return array of nodes representing terms that the current level.
     * @throws Error if there is a syntax error causing the expression to be invalid
     */
    @Override
    protected List getNodesAtLevel(String exp) {

        int pos = 0;
        List nodes = new ArrayList();
        String token = "";
        char ch = exp.charAt(pos);

        while (pos < exp.length() && !token.equals("" + Tokens.RIGHT_PAREN.getSymbol())) {
            if (ch == ' ') {
                // spaces are ignored
            }
            else if (ch == Tokens.LEFT_PAREN.getSymbol()) {

                if (token.length() > 0)  {
                    nodes.add(new TreeNode(token, opDef));
                    token = "";
                }

                int closingParenPos = findClosingParen(exp, pos + 1);
                // this method will make the recursive call
                processSubExpression(exp, pos + 1, token, closingParenPos, nodes);
                pos = closingParenPos;
            }
            else if (LTokens.isTerminal(ch)) {
                token += ch;
            }
            else {
                throw new IllegalStateException("Unexpected character " + ch +" in expression: " + exp);
            }
            pos++;
            if (pos < exp.length()) {
                ch = exp.charAt(pos);
            }
        }
        // add the final node
        if (token.length() > 0) {
            pushNodesForToken(token, nodes);
        }

        return nodes;
    }

    /**
     * Parse a parenthesized sub expression recursively.
     * @return current token. May have been reset to "".
     */
    @Override
    protected String processSubExpression(
        String exp, int pos, String token, int closingParenPos, List nodes) {

        // recursive call for sub expression
        TreeNode subTree = parse(exp.substring(pos, closingParenPos));
        subTree.hasParens = true;
        nodes.add(subTree);
        return token;
    }

    /**
     * Converts a list of nodes to a single node by reducing them to
     * subtrees in order of operator precedence.
     */
    @Override
    protected TreeNode makeTreeFromNodes(List nodes) {

        TreeNode node = new TreeNode("", opDef);
        node.children.addAll(nodes);

        nodes.clear();
        nodes.add(node);

        return nodes.get(0);
    }

    @Override
    protected void pushNodesForToken(String token, List nodes) {
        if (token == null) return;
        nodes.add(new TreeNode(token, opDef));
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy