suneido.compiler.AstNode.java Source code

Java tutorial

Introduction

Here is the source code for suneido.compiler.AstNode.java

Source

/* Copyright 2010 (c) Suneido Software Corp. All rights reserved.
 * Licensed under GPLv2.
 */

package suneido.compiler;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Objects;

import com.google.common.base.Strings;

import suneido.runtime.Ops;

public class AstNode {
    public final Token token;
    public final Object value;
    public final List<AstNode> children;
    public int lineNumber;

    public static final int UNKNOWN_LINE_NUMBER = -1;
    public static final List<AstNode> emptyList = Collections.emptyList();
    public static final AstNode nullNode = new AstNode(null, null, UNKNOWN_LINE_NUMBER, emptyList);

    public AstNode(Token token, Object value, int lineNumber, List<AstNode> children) {
        this.token = token;
        this.value = value;
        this.children = children;
        this.lineNumber = lineNumber;
    }

    public AstNode(Token token, String value, List<AstNode> children) {
        this(token, value, getLineNumber(children), children);
    }

    public AstNode(Token token, String value, int lineNumber, AstNode... children) {
        this(token, value, lineNumber, Arrays.asList(children));
    }

    public AstNode(Token token, String value, AstNode... children) {
        this(token, value, Arrays.asList(children));
    }

    public AstNode(Token token, int lineNumber, AstNode... children) {
        this(token, null, lineNumber, Arrays.asList(children));
    }

    public AstNode(Token token, AstNode... children) {
        this(token, null, Arrays.asList(children));
    }

    public AstNode(Token token, List<AstNode> children) {
        this(token, null, children);
    }

    public AstNode(Token token, String value, int lineNumber) {
        this(token, value, lineNumber, emptyList);
    }

    public AstNode(Token token, String value) {
        this(token, value, UNKNOWN_LINE_NUMBER, emptyList);
    }

    public AstNode(Token token, int lineNumber) {
        this(token, null, lineNumber, emptyList);
    }

    public AstNode(Token token) {
        this(token, null, UNKNOWN_LINE_NUMBER, emptyList);
    }

    private static AstNode[] common = { value(Token.VALUE, true), value(Token.VALUE, false), value(Token.VALUE, 0),
            value(Token.VALUE, Integer.MAX_VALUE), value(Token.VALUE, ""), value(Token.VALUE, "block") };

    public static AstNode value(Object val) {
        for (var node : common)
            if (val == node.value)
                return node;
        return value(Token.VALUE, val);
    }

    public static AstNode value(Token token, Object val) {
        return new AstNode(token, val, UNKNOWN_LINE_NUMBER, emptyList);
    }

    public AstNode first() {
        return children.get(0);
    }

    public AstNode second() {
        return children.get(1);
    }

    public AstNode third() {
        return children.get(2);
    }

    public AstNode fourth() {
        return children.get(3);
    }

    private static int getLineNumber(List<AstNode> nodes) {
        int k = nodes.size();
        while (0 < k) {
            AstNode node = nodes.get(--k);
            if (null != node && UNKNOWN_LINE_NUMBER < node.lineNumber) {
                return node.lineNumber;
            }
        }
        return UNKNOWN_LINE_NUMBER;
    }

    public boolean equals(AstNode other) {
        if (other == null)
            return false;
        else if (other == this)
            return true;
        else {
            return token == other.token && Objects.equals(value, other.value)
                    && Objects.equals(children, other.children);
        }
    }

    @Override
    public boolean equals(Object other) {
        return other instanceof AstNode && equals((AstNode) other);
    }

    @Override
    public String toString() {
        return toString(0);
    }

    private String toString(int indent) {
        boolean multiline = multiline();
        String sep = multiline ? "\n" : " ";
        int childIndent = multiline ? indent + 3 : 0;

        StringBuilder sb = new StringBuilder();
        sb.append(Strings.repeat(" ", indent));
        sb.append('(').append(token);
        if (value != null)
            sb.append('=').append(token == Token.VALUE ? Ops.display(value) : value);
        if (children != null)
            for (AstNode x : children)
                sb.append(sep)
                        .append(x == null ? Strings.repeat(" ", childIndent) + "null" : x.toString(childIndent));
        sb.append(')');
        return sb.toString();
    }

    boolean multiline() {
        final int MAX = 70;
        int total = 0;
        for (AstNode x : children) {
            String s = (x == null) ? "null" : x.toString();
            if (s.contains("\n"))
                return true;
            int n = s.length();
            total += n;
            if (n > MAX || total > MAX)
                return true;
        }
        return false;
    }

    public abstract static class Visitor {
        /** return false to skip processing children */
        boolean topDown(AstNode ast) {
            return true;
        }

        void bottomUp(AstNode ast) {
        }
    }

    public void depthFirst(Visitor visitor) {
        if (!visitor.topDown(this))
            return;
        for (AstNode child : children)
            if (child != null)
                child.depthFirst(visitor);
        visitor.bottomUp(this);
    }

    public String strval() {
        return (String) value;
    }

    //   public static void main(String[] args) {
    //      System.out.println(new AstNode(Token.ADD,
    //            new AstNode(Token.IDENTIFIER, "x"),
    //            new AstNode(Token.NUMBER, "123")));
    //   }

}