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

javax0.jamal.prog.analyzer.Lexer Maven / Gradle / Ivy

There is a newer version: 2.8.1
Show newest version
package javax0.jamal.prog.analyzer;

import javax0.jamal.api.BadSyntax;
import javax0.jamal.api.Input;
import javax0.jamal.api.Macro;
import javax0.jamal.tools.InputHandler;
import javax0.jamal.tools.param.StringFetcher;

import java.util.ArrayList;
import java.util.Set;

public class Lexer {

    final static private Set RESERVED = Set.of(
            //snipline KEYWORDS
            "if", "else", "elseif", "then", "endif", "while", "wend", "for", "next", "do", "until", "and", "or", "not", "to", "step", "end"
    );
    final static private String[] OPERANDS = {
            "==", "!=", "<=", ">=", "<<", "!", "=", "+", "-", "*", "/", "%", "(", ")", "<", ">", ",", "."
    };

    public Lex.List analyze(Input in) throws BadSyntax {
        final var list = new ArrayList();
        while (!in.isEmpty()) {
            if (Character.isWhitespace(in.charAt(0)) && in.charAt(0) != '\n') {
                InputHandler.skip(in, 1);
                continue;
            }
            if (in.charAt(0) == '\'') {
                InputHandler.skip(in, 1);
                skipComment(in, list);
                continue;
            }
            if (in.charAt(0) == '\n') {
                final var lex = new Lex(Lex.Type.RESERVED, "\n");
                list.add(lex);
                InputHandler.skip(in, 1);
                continue;
            }
            if (Macro.validId1stChar(in.charAt(0))) {
                final var id = InputHandler.fetchId(in);
                if (id.equals("rem")) {
                    skipComment(in, list);
                    continue;
                }
                if (RESERVED.contains(id)) {
                    final var lex = new Lex(Lex.Type.RESERVED, id);
                    list.add(lex);
                } else {
                    final var lex = new Lex(Lex.Type.IDENTIFIER, id);
                    list.add(lex);
                }
                continue;
            }
            if (in.charAt(0) == '"') {
                final var str = StringFetcher.getString(in);
                final var lex = new Lex(Lex.Type.STRING, str);
                list.add(lex);
                continue;
            }
            if (Character.isDigit(in.charAt(0))) {
                final var str = InputHandler.fetchNumber(in);
                final var lex = new Lex(Lex.Type.STRING, str);
                list.add(lex);
                continue;
            }
            int operandIndex = InputHandler.startsWith(in, OPERANDS);
            if (operandIndex >= 0) {
                final var lex = new Lex(Lex.Type.RESERVED, OPERANDS[operandIndex]);
                list.add(lex);
                InputHandler.skip(in, OPERANDS[operandIndex].length());
                continue;
            }
            throw new BadSyntax("Unexpected character '" + in.charAt(0) + "' in the input");
        }
        return new Lex.List(list);
    }

    /**
     * Skip the comment until the end of line. The end of line is not skipped.
     *
     * @param in   the input
     * @param list the lexical list, where an '\n' is added.
     */
    private static void skipComment(final Input in, final ArrayList list) {
        while (!in.isEmpty() && in.charAt(0) != '\n') {
            InputHandler.skip(in, 1);
        }
        if (!in.isEmpty()) {
            final var lex = new Lex(Lex.Type.RESERVED, "\n");
            list.add(lex);
            InputHandler.skip(in, 1);
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy