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

hu.bme.mit.theta.common.parser.SExpr Maven / Gradle / Ivy

There is a newer version: 6.5.2
Show newest version
/*
 *  Copyright 2024 Budapest University of Technology and Economics
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package hu.bme.mit.theta.common.parser;

import com.google.common.collect.ImmutableList;

import java.io.Reader;
import java.io.StringReader;
import java.util.Iterator;
import java.util.List;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.common.collect.Streams.stream;
import static java.util.stream.Collectors.joining;

public abstract class SExpr {

    private SExpr() {
    }

    public static SAtom atom(final String atom) {
        return new SAtom(atom);
    }

    public static SList list(final Iterable sexprs) {
        return new SList(sexprs);
    }

    public static SList list(final SExpr... sexprs) {
        return list(ImmutableList.copyOf(sexprs));
    }

    public static SExpr build(final Object object) {
        checkNotNull(object);
        if (object instanceof String) {
            final String string = (String) object;
            return atom(string);
        } else if (object instanceof Iterable) {
            final Iterable iterable = (Iterable) object;
            final List sexprs = stream(iterable).map(SExpr::build)
                    .collect(toImmutableList());
            return list(sexprs);
        } else {
            throw new IllegalArgumentException(
                    "Only String and Iterable types are supported, found: " + object.getClass()
                            .getSimpleName());
        }
    }

    public static SExpr parse(final String string) {
        checkNotNull(string);
        final Reader reader = new StringReader(string);
        final LispLexer lexer = new LispLexer(reader);
        final LispParser parser = new LispParser(lexer);
        return parser.sexpr();
    }

    public boolean isAtom() {
        return false;
    }

    public boolean isList() {
        return false;
    }

    public SAtom asAtom() {
        throw new ClassCastException();
    }

    public SList asList() {
        throw new ClassCastException();
    }

    public static final class SAtom extends SExpr {

        private static final int HASH_SEED = 3943;
        private volatile int hashCode = 0;

        private final String atom;

        private SAtom(final String atom) {
            checkNotNull(atom);
            checkArgument(atom.length() > 0);
            this.atom = atom;
        }

        public String getAtom() {
            return atom;
        }

        @Override
        public boolean isAtom() {
            return true;
        }

        @Override
        public SAtom asAtom() {
            return this;
        }

        @Override
        public int hashCode() {
            int result = hashCode;
            if (result == 0) {
                result = HASH_SEED;
                result = 31 * result + atom.hashCode();
                hashCode = result;
            }
            return result;
        }

        @Override
        public boolean equals(final Object obj) {
            if (this == obj) {
                return true;
            } else if (obj != null && this.getClass() == obj.getClass()) {
                final SAtom that = (SAtom) obj;
                return this.atom.equals(that.atom);
            } else {
                return false;
            }
        }

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

    public static final class SList extends SExpr implements Iterable {

        private static final String LPAREN = "(";
        private static final String RPAREN = ")";
        private static final String SPACE = " ";

        private static final int HASH_SEED = 6563;
        private volatile int hashCode = 0;

        private final List list;

        private SList(final Iterable sexprs) {
            checkNotNull(sexprs);
            this.list = ImmutableList.copyOf(sexprs);
        }

        public List getList() {
            return list;
        }

        @Override
        public boolean isList() {
            return true;
        }

        @Override
        public SList asList() {
            return this;
        }

        @Override
        public Iterator iterator() {
            return list.iterator();
        }

        @Override
        public int hashCode() {
            int result = hashCode;
            if (result == 0) {
                result = HASH_SEED;
                result = 31 * result + list.hashCode();
                hashCode = result;
            }
            return result;
        }

        @Override
        public boolean equals(final Object obj) {
            if (this == obj) {
                return true;
            } else if (obj != null && this.getClass() == obj.getClass()) {
                final SList that = (SList) obj;
                return this.list.equals(that.list);
            } else {
                return false;
            }
        }

        @Override
        public String toString() {
            return list.stream().map(Object::toString).collect(joining(SPACE, LPAREN, RPAREN));
        }
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy