Package org.erlide.engine.internal.services.parsing

Source Code of org.erlide.engine.internal.services.parsing.ErlParser

/*******************************************************************************
* Copyright (c) 2004 Vlad Dumitrescu and others. All rights reserved. This program and
* the accompanying materials are made available under the terms of the Eclipse Public
* License v1.0 which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors: Vlad Dumitrescu
*******************************************************************************/
package org.erlide.engine.internal.services.parsing;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;

import org.erlide.engine.ErlangEngine;
import org.erlide.engine.internal.model.erlang.ErlAttribute;
import org.erlide.engine.internal.model.erlang.ErlComment;
import org.erlide.engine.internal.model.erlang.ErlExport;
import org.erlide.engine.internal.model.erlang.ErlFunction;
import org.erlide.engine.internal.model.erlang.ErlFunctionClause;
import org.erlide.engine.internal.model.erlang.ErlImport;
import org.erlide.engine.internal.model.erlang.ErlMacroDef;
import org.erlide.engine.internal.model.erlang.ErlMember;
import org.erlide.engine.internal.model.erlang.ErlRecordDef;
import org.erlide.engine.internal.model.erlang.ErlRecordField;
import org.erlide.engine.internal.model.erlang.ErlTypespec;
import org.erlide.engine.internal.model.erlang.SourceRefElement;
import org.erlide.engine.model.ErlModelException;
import org.erlide.engine.model.erlang.IErlAttribute;
import org.erlide.engine.model.erlang.IErlComment;
import org.erlide.engine.model.erlang.IErlFunction;
import org.erlide.engine.model.erlang.IErlImport;
import org.erlide.engine.model.erlang.IErlMember;
import org.erlide.engine.model.erlang.IErlModule;
import org.erlide.engine.model.erlang.IErlRecordDef;
import org.erlide.engine.model.erlang.IErlTypespec;
import org.erlide.engine.model.erlang.ISourceReference;
import org.erlide.engine.model.root.IErlElement;
import org.erlide.engine.services.parsing.ParserService;
import org.erlide.engine.services.parsing.RuntimeHelper;
import org.erlide.runtime.api.IOtpRpc;
import org.erlide.util.ErlLogger;
import org.erlide.util.Util;

import com.ericsson.otp.erlang.OtpErlangAtom;
import com.ericsson.otp.erlang.OtpErlangList;
import com.ericsson.otp.erlang.OtpErlangLong;
import com.ericsson.otp.erlang.OtpErlangObject;
import com.ericsson.otp.erlang.OtpErlangRangeException;
import com.ericsson.otp.erlang.OtpErlangString;
import com.ericsson.otp.erlang.OtpErlangTuple;
import com.google.common.collect.Lists;

/**
* @author jakob
*
*/
public final class ErlParser implements ParserService {

    private static final class SourceOffsetComparator implements
            Comparator<ISourceReference> {
        @Override
        public int compare(final ISourceReference o1, final ISourceReference o2) {
            final int offset1 = o1.getSourceRange().getOffset();
            final int offset2 = o2.getSourceRange().getOffset();
            return offset1 - offset2;
        }
    }

    private static final int FUNCTION_COMMENT_THRESHOLD = 3;
    private static final int MODULE_HEADER_COMMENT_THRESHOLD = 1;
    private static final boolean TRACE = false;

    private final RuntimeHelper helper;
    private final IOtpRpc backend;

    public ErlParser(final IOtpRpc backend) {
        this.backend = backend;
        helper = new RuntimeHelper(backend);
    }

    @Override
    public boolean parse(final IErlModule module, final String scannerName,
            final boolean initialParse, final String path, final String initialText,
            final boolean updateSearchServer) {
        if (module == null) {
            return false;
        }
        OtpErlangList forms = null;
        OtpErlangList comments = null;
        OtpErlangTuple res = null;
        if (initialParse) {
            final String stateDir = ErlangEngine.getInstance().getStateDir();
            final String pathNotNull = path == null ? "" : path;
            res = ErlideNoparse.initialParse(backend, scannerName, pathNotNull,
                    initialText, stateDir, true, updateSearchServer);
        } else {
            res = ErlideNoparse.reparse(backend, scannerName, updateSearchServer);
        }
        if (Util.isOk(res)) {
            final OtpErlangTuple t = (OtpErlangTuple) res.elementAt(1);
            forms = (OtpErlangList) t.elementAt(1);
            comments = (OtpErlangList) t.elementAt(2);
        } else {
            ErlLogger.error("error when parsing %s: %s", path, res);
        }
        if (forms == null) {
            module.setChildren(null);
        } else {
            final List<IErlElement> children = createForms(module, forms);
            module.setChildren(children);
        }
        if (comments == null) {
            module.setComments(null);
        } else {
            final List<IErlComment> moduleComments = createComments(module, comments);
            module.setComments(moduleComments);
        }
        attachFunctionComments(module);
        String cached = "reparsed";
        if (res != null && res.arity() > 2) {
            final OtpErlangObject res2 = res.elementAt(2);
            if (res2 instanceof OtpErlangAtom) {
                final OtpErlangAtom atom = (OtpErlangAtom) res2;
                cached = atom.atomValue();
            }
        }
        if (TRACE) {
            ErlLogger.debug("Parsed %d forms and %d comments (%s)",
                    forms != null ? forms.arity() : 0,
                    comments != null ? comments.arity() : 0, cached);
        }
        return forms != null && comments != null;
    }

    @Override
    public OtpErlangObject parse(final String module, final String text) {
        final String stateDir = ErlangEngine.getInstance().getStateDir();
        return ErlideNoparse.initialParse(backend, module, module, text, stateDir, false,
                false);
    }

    private List<IErlComment> createComments(final IErlModule module,
            final OtpErlangList comments) {
        final List<IErlComment> moduleComments = Lists.newArrayListWithCapacity(comments
                .arity());
        for (final OtpErlangObject comment : comments) {
            final IErlComment c = createComment(module, (OtpErlangTuple) comment);
            if (c != null) {
                moduleComments.add(c);
            }
        }
        return moduleComments;
    }

    private List<IErlElement> createForms(final IErlModule module,
            final OtpErlangList forms) {
        final List<IErlElement> children = Lists.newArrayListWithCapacity(forms.arity());
        for (final OtpErlangObject form : forms) {
            final IErlMember elem = create(module, (OtpErlangTuple) form);
            if (elem != null) {
                children.add(elem);
            }
        }
        return children;
    }

    /**
     * attach local function documentation with heuristics: if a comment is
     * within 3 lines before function, or a sequence of comment, -spec, comment,
     * then they should be added to function documentation
     *
     * If any typespec is available for the function (wherever it is located),
     * then it should be attached too.
     *
     * @param module
     */
    private void attachFunctionComments(final IErlModule module) {
        // TODO rewrite in Erlang? would be so much less code...
        try {
            final Collection<IErlComment> comments = module.getComments();
            final List<IErlElement> children = module.getChildren();
            final List<IErlMember> all = Lists.newArrayListWithCapacity(children.size()
                    + comments.size());
            all.addAll(comments);
            for (final IErlElement element : children) {
                if (element instanceof IErlMember) {
                    all.add((IErlMember) element);
                }
            }
            Collections.sort(all, new SourceOffsetComparator());
            for (int i = 1; i < all.size(); i++) {
                checkForComment(all, i);
            }
        } catch (final ErlModelException e) {
            ErlLogger.warn(e);
        }
    }

    private void checkForComment(final List<IErlMember> all, final int i) {
        final IErlMember m = all.get(i);
        if (m instanceof IErlFunction) {
            final IErlFunction function = (IErlFunction) m;
            final LinkedList<IErlComment> comments = Lists.newLinkedList();
            int j = considerPrevious(i, all, comments, function);
            j = considerPrevious(j, all, comments, function);
            j = considerPrevious(j, all, comments, function);
            if (!comments.isEmpty()) {
                function.setComments(comments);
            }
        }
    }

    private int considerPrevious(final int i, final List<IErlMember> all,
            final LinkedList<IErlComment> comments, final IErlFunction function) {
        final int j = i - 1;
        if (j > 0) {
            final IErlMember member = all.get(i);
            final IErlMember prevMember = all.get(j);
            if (prevMember instanceof IErlComment) {
                if (prevMember.getLineEnd() + FUNCTION_COMMENT_THRESHOLD >= member
                        .getLineStart()) {
                    comments.addFirst((IErlComment) prevMember);
                }
            } else if (prevMember instanceof IErlTypespec) {
                final IErlTypespec spec = (IErlTypespec) prevMember;

                if (spec.getName().equals(function.getName())
                        && spec.getArity() == function.getArity()
                        && prevMember.getLineEnd() + FUNCTION_COMMENT_THRESHOLD >= member
                                .getLineStart()) {
                    function.setTypespec(spec);
                }
            } else {
                return -1;
            }
        }
        return j;
    }

    // -record(token, {kind, line, offset, length, value, text,
    // last_line, column}).
    // indexes of the token fields
    final static int KIND = 1;
    final static int LINE = 2;
    final static int OFFSET = 3;
    final static int LENGTH = 4;
    final static int VALUE = 5;
    final static int TEXT = 6;
    final static int LAST_LINE = 7;
    final static int COLUMN = 8;

    /**
     * create an IErlComment from a token record
     *
     * @param IErlModule
     *            module containing comment
     * @param OtpErlangTuple
     *            token record from noparse
     * @return IErlComment
     */
    private IErlComment createComment(final IErlModule module, final OtpErlangTuple c) {
        final OtpErlangLong lineL = (OtpErlangLong) c.elementAt(LINE);
        final OtpErlangObject s = c.elementAt(TEXT);

        int line;
        int lastLine;
        try {
            line = lineL.intValue();
        } catch (final OtpErlangRangeException x) {
            line = 0;
        }
        lastLine = line;
        try {
            if (c.elementAt(LAST_LINE) instanceof OtpErlangLong) {
                final OtpErlangLong lastLineL = (OtpErlangLong) c.elementAt(LAST_LINE);
                lastLine = lastLineL.intValue();
            }
        } catch (final OtpErlangRangeException e1) {
            lastLine = line;
        }
        final ErlComment comment = new ErlComment(module, Util.stringValue(s),
                line <= MODULE_HEADER_COMMENT_THRESHOLD);
        try {
            final int ofs = ((OtpErlangLong) c.elementAt(OFFSET)).intValue();
            final int len = ((OtpErlangLong) c.elementAt(LENGTH)).intValue();
            setPos(comment, line, lastLine, ofs + 1, len);
        } catch (final OtpErlangRangeException e) {
            return null;
        }
        return comment;
    }

    /**
     * create an IErlMember from a tuple from noparse
     *
     * @param el
     *            the tuple, either function or attribute
     * @return
     */
    private IErlMember create(final IErlModule module, final OtpErlangTuple el) {
        final OtpErlangAtom type = (OtpErlangAtom) el.elementAt(0);
        final String typeS = type.atomValue();
        if ("error".equals(typeS)) {
            final OtpErlangTuple er = (OtpErlangTuple) el.elementAt(1);
            final String msg = helper.formatError(er);
            final ErlParserProblem e = ErlParserProblem.newError(module, msg);
            setPos(e, er.elementAt(0));
            return e;
        } else if ("tree".equals(typeS)) {
            final OtpErlangTuple atr = (OtpErlangTuple) el.elementAt(3);
            final OtpErlangObject pos = ((OtpErlangTuple) el.elementAt(2)).elementAt(1);
            final OtpErlangTuple name = (OtpErlangTuple) atr.elementAt(1);
            final OtpErlangAtom n = (OtpErlangAtom) concreteTerm(name);
            final OtpErlangObject val = atr.elementAt(2);
            final OtpErlangObject extra = el.arity() > 4 ? el.elementAt(4) : null;
            return addAttribute(module, pos, n, val, extra, null);
        } else if ("attribute".equals(typeS)) {
            final OtpErlangObject pos = el.elementAt(1);
            final OtpErlangAtom name = (OtpErlangAtom) el.elementAt(2);
            final OtpErlangObject val = el.elementAt(3);
            final OtpErlangObject extra = el.arity() > 4 ? el.elementAt(4) : null;
            final OtpErlangObject arity = el.arity() > 5 ? el.elementAt(5) : null;
            return addAttribute(module, pos, name, val, extra, arity);
        } else if ("function".equals(typeS)) {
            final ErlFunction f = makeErlFunction(module, el);
            final OtpErlangList clauses = (OtpErlangList) el.elementAt(6);
            final List<ErlFunctionClause> cls = Lists.newArrayListWithCapacity(clauses
                    .arity());
            for (int i = 0; i < clauses.arity(); i++) {
                final OtpErlangTuple clause = (OtpErlangTuple) clauses.elementAt(i);
                final ErlFunctionClause cl = makeErlFunctionClause(f, i, clause);
                cls.add(cl);
            }
            f.setChildren(cls);
            return f;
        } else {
            ErlLogger.debug("unknown: " + el);
        }
        return null;
    }

    /**
     * @param module
     *            module
     * @param el
     *            -record(function, {pos, name, arity, args, head, clauses,
     *            name_pos, comment, exported}).
     * @return ErlFunction
     */
    private ErlFunction makeErlFunction(final IErlModule module, final OtpErlangTuple el) {
        final OtpErlangTuple pos = (OtpErlangTuple) el.elementAt(1);
        final OtpErlangAtom name = (OtpErlangAtom) el.elementAt(2);
        final OtpErlangLong arity = (OtpErlangLong) el.elementAt(3);
        final OtpErlangList parameters = (OtpErlangList) el.elementAt(4);
        final OtpErlangObject head = el.elementAt(5);
        final OtpErlangTuple namePos = (OtpErlangTuple) el.elementAt(7);
        ErlFunction f = null;
        final OtpErlangAtom exportedA = (OtpErlangAtom) el.elementAt(8);
        final boolean exported = Boolean.parseBoolean(exportedA.atomValue());
        try {
            f = new ErlFunction(module, name.atomValue(), arity.intValue(),
                    Util.stringValue(head), exported, parameters);
        } catch (final OtpErlangRangeException e) {
            return f;
        }
        setPos(f, pos);
        try {
            setNamePos(f, namePos);
        } catch (final OtpErlangRangeException e) {
            return f;
        }
        return f;
    }

    /**
     * @param f
     *            function
     * @param i
     *            clause number
     * @param clause
     *            -record(clause, {pos, name, args, head, code, name_pos}).
     * @return ErlFunctionClause
     *
     *
     */
    private ErlFunctionClause makeErlFunctionClause(final ErlFunction f, final int i,
            final OtpErlangTuple clause) {
        final OtpErlangTuple cpos = (OtpErlangTuple) clause.elementAt(1);
        final OtpErlangList parameters = (OtpErlangList) clause.elementAt(3);
        final OtpErlangObject head = clause.elementAt(4);
        final OtpErlangTuple cnamePos = (OtpErlangTuple) clause.elementAt(5);
        final ErlFunctionClause cl = new ErlFunctionClause(f, "#" + i,
                Util.stringValue(head), parameters);
        try {
            setNamePos(cl, cnamePos);
        } catch (final OtpErlangRangeException e) {
            ErlLogger.warn(e);
        }
        setPos(cl, cpos);
        return cl;
    }

    private void setNamePos(final ErlMember f, final OtpErlangTuple namePos)
            throws OtpErlangRangeException {
        final OtpErlangTuple tpos1 = (OtpErlangTuple) namePos.elementAt(0);
        final int ofs = ((OtpErlangLong) tpos1.elementAt(1)).intValue();
        final int len = ((OtpErlangLong) namePos.elementAt(1)).intValue();
        f.setNameRange(ofs, len);
    }

    private IErlMember addAttribute(final IErlModule module, final OtpErlangObject pos,
            final OtpErlangAtom name, final OtpErlangObject val,
            final OtpErlangObject extra, final OtpErlangObject arity) {
        final String nameS = name.atomValue();
        if ("module".equals(nameS) && val instanceof OtpErlangAtom) {
            return addModuleAttribute(module, pos, (OtpErlangAtom) val, extra, nameS);
        } else if ("import".equals(nameS)) {
            if (val instanceof OtpErlangTuple) {
                return addImportAttribute(module, pos, val);
            }
        } else if ("export".equals(nameS)) {
            return addExportAttribute(module, pos, val, extra);
        } else if ("record".equals(nameS)) {
            return addRecordDef(module, pos, val, extra);
        } else if ("type".equals(nameS) || "spec".equals(nameS) || "opaque".equals(nameS)) {
            return addTypespec(module, pos, extra);
        } else if ("define".equals(nameS)) {
            return addMacroDef(module, pos, val, extra, nameS);
        }
        return addOtherAttribute(module, pos, val, extra, nameS);
    }

    private IErlMember addExportAttribute(final IErlModule module,
            final OtpErlangObject pos, final OtpErlangObject val,
            final OtpErlangObject extra) {
        final OtpErlangList functionList = (OtpErlangList) val;
        final ErlExport ex = new ErlExport(module, functionList, Util.stringValue(extra));
        setPos(ex, pos);
        return ex;
    }

    private IErlMember addMacroDef(final IErlModule module, final OtpErlangObject pos,
            final OtpErlangObject val, final OtpErlangObject extra, final String nameS) {
        if (val instanceof OtpErlangAtom) {
            final String s = Util.stringValue(extra);
            final ErlMember r = new ErlMacroDef(module,
                    ((OtpErlangAtom) val).atomValue(), s);
            setPos(r, pos);
            // r.setParseTree(val);
            return r;
        } else if (val instanceof OtpErlangList) {
            final OtpErlangList macroList = (OtpErlangList) val;
            if (macroList.elementAt(0) instanceof OtpErlangTuple) {
                final OtpErlangTuple macroNameTuple = (OtpErlangTuple) macroList
                        .elementAt(0);
                OtpErlangObject o = macroNameTuple.elementAt(2);
                if (o instanceof OtpErlangTuple) {
                    o = ((OtpErlangTuple) o).elementAt(2);
                }
                ErlMember r;
                if (o instanceof OtpErlangAtom) {
                    final String macroName = ((OtpErlangAtom) o).atomValue();
                    r = new ErlMacroDef(module, macroName, null);
                } else {
                    // what do we do here? the define isn't correct
                    // Erlang...
                    ErlLogger.warn("Strange macro definition in %s: %s",
                            module.getName(), o.toString());
                    r = new ErlMacroDef(module, o.toString(), null);
                }
                setPos(r, pos);
                // r.setParseTree(val);
                return r;
            }
        }
        return addOtherAttribute(module, pos, val, extra, nameS);
    }

    private IErlAttribute addOtherAttribute(final IErlModule module,
            final OtpErlangObject pos, final OtpErlangObject val,
            final OtpErlangObject extra, final String nameS) {
        // user-defined attribute? or maybe if else endif...
        // OtpErlangObject val1 = concreteTerm(val);
        // if (val instanceof OtpErlangList) {
        // final OtpErlangList list = (OtpErlangList) val;
        // if (list.arity() == 0) {
        // val1 = null;
        // }
        // }

        // final ErlAttribute a = new ErlAttribute(parent, nameS, val1, null);
        OtpErlangObject o = val;
        if (o instanceof OtpErlangAtom) {
            final OtpErlangAtom u = (OtpErlangAtom) o;
            if ("u".equals(u.atomValue())) {
                o = null;
            }
        }
        final ErlAttribute a = new ErlAttribute(module, nameS, o, Util.stringValue(extra));
        setPos(a, pos);
        // a.setParseTree(val);
        return a;
    }

    private IErlRecordDef addRecordDef(final IErlModule module,
            final OtpErlangObject pos, final OtpErlangObject val,
            final OtpErlangObject extra) {
        if (val instanceof OtpErlangTuple) {
            final OtpErlangTuple recordTuple = (OtpErlangTuple) val;
            if (recordTuple.elementAt(0) instanceof OtpErlangAtom) {
                final String s = extra instanceof OtpErlangString ? ((OtpErlangString) extra)
                        .stringValue() : null;
                final OtpErlangList fields = (OtpErlangList) recordTuple.elementAt(1);
                final ErlRecordDef r = new ErlRecordDef(module, null, s);
                setPos(r, pos);
                if (fields != null) {
                    final List<ErlRecordField> children = Lists
                            .newArrayListWithCapacity(fields.arity());
                    for (final OtpErlangObject o : fields) {
                        if (o instanceof OtpErlangTuple) {
                            final OtpErlangTuple fieldTuple = (OtpErlangTuple) o;
                            final OtpErlangAtom fieldNameAtom = (OtpErlangAtom) fieldTuple
                                    .elementAt(0);
                            final String fieldName = fieldNameAtom.atomValue();
                            final ErlRecordField field = new ErlRecordField(r, fieldName);
                            final OtpErlangTuple posTuple = (OtpErlangTuple) fieldTuple
                                    .elementAt(1);
                            if (fieldTuple.arity() > 2) {
                                final OtpErlangObject fieldExtra = fieldTuple
                                        .elementAt(2);
                                field.setExtra(Util.stringValue(fieldExtra));
                            }
                            setPos(field, posTuple);
                            children.add(field);
                        } else {
                            ErlLogger.error("bad record def: %s", o);
                        }
                    }
                    r.setChildren(children);
                } else {
                    r.setChildren(new ArrayList<IErlElement>());
                }
                return r;
            }
        }
        if (val instanceof OtpErlangAtom) {
            final String s = extra instanceof OtpErlangString ? ((OtpErlangString) extra)
                    .stringValue() : null;
            final ErlRecordDef r = new ErlRecordDef(module, null, s);
            setPos(r, pos);
            return r;
        }
        return null;
    }

    private IErlMember addTypespec(final IErlModule module, final OtpErlangObject pos,
            final OtpErlangObject extra) {
        final String s = Util.stringValue(extra);
        final int p = s.indexOf('(');
        final String ref = p < 0 ? s : s.substring(0, p);
        final int arity = getTypeArity(s);
        final String[] refs = ref.split(":");
        String moduleName;
        String typeName;
        if (refs.length == 1) {
            moduleName = module.getName();
            typeName = refs[0];
        } else {
            moduleName = refs[0];
            typeName = refs[1];
        }
        final ErlTypespec a = new ErlTypespec(module, moduleName, typeName, arity, s);
        setPos(a, pos);
        return a;
    }

    private int getTypeArity(final String s) {
        final int p = s.indexOf('(');
        int paras = 1;
        int result = 0;
        for (int i = p + 1; i < s.length(); i++) {
            final char crt = s.charAt(i);
            if (crt == '(') {
                paras += 1;
            }
            if (crt == ')') {
                paras -= 1;
            }
            if (paras == 0) {
                break;
            }
            if (crt == ',' && paras == 1) {
                result += 1;
            }
            if (result == 0 && crt != ')') {
                result += 1;
            }
        }
        return result;
    }

    private IErlImport addImportAttribute(final IErlModule module,
            final OtpErlangObject pos, final OtpErlangObject val) {
        final OtpErlangTuple t = (OtpErlangTuple) val;
        if (t.elementAt(0) instanceof OtpErlangAtom
                && t.elementAt(1) instanceof OtpErlangList) {
            final OtpErlangAtom importModule = (OtpErlangAtom) t.elementAt(0);
            final OtpErlangList functionList = (OtpErlangList) t.elementAt(1);
            final ErlImport imp = new ErlImport(module, importModule.atomValue(),
                    functionList);
            setPos(imp, pos);
            return imp;
        }
        return null;
    }

    private IErlAttribute addModuleAttribute(final IErlModule module,
            final OtpErlangObject pos, final OtpErlangAtom value,
            final OtpErlangObject extra, final String nameS) {
        final String s = Util.stringValue(extra);
        final ErlAttribute r = new ErlAttribute(module, nameS, value, s);
        setPos(r, pos);
        return r;
    }

    private boolean setPos(final SourceRefElement e, final OtpErlangObject pos) {
        if (!(pos instanceof OtpErlangTuple)) {
            if (pos instanceof OtpErlangLong) {
                int ipos = 999999;
                try {
                    ipos = ((OtpErlangLong) pos).intValue();
                } catch (final OtpErlangRangeException e1) {
                }
                setPos(e, 0, 0, ipos, 0);
                return true;
            }
            ErlLogger.debug("!> expecting pos tuple, got " + pos);
            return false;
        }
        try {
            // pos=
            // {{Line, LastLine, Offset}, PosLength} or
            // {{Line, Offset}, PosLength}
            final OtpErlangTuple tpos = (OtpErlangTuple) pos;
            final OtpErlangTuple tpos1 = (OtpErlangTuple) tpos.elementAt(0);
            final OtpErlangLong lenL = (OtpErlangLong) tpos.elementAt(1);
            final OtpErlangLong lineL = (OtpErlangLong) tpos1.elementAt(0);
            final OtpErlangLong lastLineL = (OtpErlangLong) tpos1.elementAt(1);
            final int line = lineL.intValue();
            int lastLine = lastLineL.intValue();
            int ofs;
            if (tpos1.arity() > 2) {
                ofs = ((OtpErlangLong) tpos1.elementAt(2)).intValue();
            } else {
                ofs = lastLine;
                lastLine = line;
            }
            final int len = lenL.intValue();
            setPos(e, line, lastLine, ofs, len);
            return true;
        } catch (final OtpErlangRangeException ex) {
            return false;
        }

    }

    private void setPos(final SourceRefElement e, final int line, final int lastLine,
            final int ofs, final int len) {
        e.setSourceRangeOffset(ofs);
        e.setSourceRangeLength(len);
        e.setLineStart(line);
        e.setLineEnd(lastLine);
    }

    private OtpErlangObject concreteTerm(final OtpErlangObject val) {
        if (val instanceof OtpErlangList) {
            final OtpErlangList ll = (OtpErlangList) val;
            final OtpErlangObject[] res = new OtpErlangObject[ll.arity()];
            for (int i = 0; i < ll.arity(); i++) {
                res[i] = concreteTerm(ll.elementAt(i));
            }
            return new OtpErlangList(res);
        }
        try {
            return helper.concreteSyntax(val);
        } catch (final Exception e) {
            return val;
        }
    }

}
TOP

Related Classes of org.erlide.engine.internal.services.parsing.ErlParser

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.