⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 grammar.java

📁 Grammatica是一个C#和Java的语法分析程序生成器(编译器的编译器)。它可以用LL(k)语法创建可读的和带有注释的源代码。它也支持创建一个运行时语法分析器
💻 JAVA
字号:
/* * Grammar.java * * This work is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published * by the Free Software Foundation; either version 2 of the License, * or (at your option) any later version. * * This work is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA * * As a special exception, the copyright holders of this library give * you permission to link this library with independent modules to * produce an executable, regardless of the license terms of these * independent modules, and to copy and distribute the resulting * executable under terms of your choice, provided that you also meet, * for each linked independent module, the terms and conditions of the * license of that module. An independent module is a module which is * not derived from or based on this library. If you modify this * library, you may extend this exception to your version of the * library, but you are not obligated to do so. If you do not wish to * do so, delete this exception statement from your version. * * Copyright (c) 2003 Per Cederberg. All rights reserved. */package net.percederberg.grammatica;import java.io.File;import java.io.FileNotFoundException;import java.io.FileReader;import java.io.Reader;import java.util.HashMap;import java.util.Vector;import net.percederberg.grammatica.parser.Analyzer;import net.percederberg.grammatica.parser.Parser;import net.percederberg.grammatica.parser.ParserCreationException;import net.percederberg.grammatica.parser.ParserLogException;import net.percederberg.grammatica.parser.ProductionPattern;import net.percederberg.grammatica.parser.RecursiveDescentParser;import net.percederberg.grammatica.parser.TokenPattern;import net.percederberg.grammatica.parser.Tokenizer;/** * A grammar definition object. This object supports parsing a grammar * file and create a lexical analyzer (tokenizer) for the grammar. * * @author   Per Cederberg, <per at percederberg dot net> * @version  1.2 */public class Grammar extends Object {    /**     * The author grammar declaration constant.     */    public static final String AUTHOR_DECLARATION = "AUTHOR";    /**     * The copyright grammar declaration constant.     */    public static final String COPYRIGHT_DECLARATION = "COPYRIGHT";    /**     * The date grammar declaration constant.     */    public static final String DATE_DECLARATION = "DATE";    /**     * The description grammar declaration constant.     */    public static final String DESCRIPTION_DECLARATION = "DESCRIPTION";    /**     * The grammar type grammar declaration constant.     */    public static final String GRAMMAR_TYPE_DECLARATION = "GRAMMARTYPE";    /**     * The license grammar declaration constant.     */    public static final String LICENSE_DECLARATION = "LICENSE";    /**     * The version grammar declaration constant.     */    public static final String VERSION_DECLARATION = "VERSION";    /**     * The grammar file name.     */    private String fileName = "";    /**     * The grammar declarations. This is a hash map with all the name     * value pairs in the header part of the grammar.     */    private HashMap declarations = new HashMap();    /**     * The tokens found in the processing.     */    private Vector tokens = new Vector();    /**     * The token id map. This is a map from the token pattern id to      * the token pattern.     */    private HashMap tokenIds = new HashMap();    /**     * The token name map. This is map from the token pattern name to      * the token pattern.      */    private HashMap tokenNames = new HashMap();    /**     * The token pattern map. This is map from the token pattern      * string to the token pattern object.      */    private HashMap tokenPatterns = new HashMap();        /**     * The productions found in the processing.     */    private Vector productions = new Vector();    /**     * The production id map. This is a map from the production      * pattern id to the production pattern.     */    private HashMap productionIds = new HashMap();    /**     * The production name map. This is map from the production      * pattern name to the production pattern.      */    private HashMap productionNames = new HashMap();    /**     * The map from token or production pattern name to a line range.     */    private HashMap lines = new HashMap();    /**     * Creates a new grammar from the specified file.     *     * @param file     the grammar file to read     *     * @throws FileNotFoundException if the grammar file could not be     *             found     * @throws ParserLogException if the grammar file couldn't be      *             parsed correctly     * @throws GrammarException if the grammar wasn't valid     */    public Grammar(File file) throws FileNotFoundException,         ParserLogException, GrammarException {        GrammarParser       parser;        FirstPassAnalyzer   first = new FirstPassAnalyzer(this);        SecondPassAnalyzer  second = new SecondPassAnalyzer(this);        fileName = file.toString();        try {            parser = new GrammarParser(new FileReader(file), first);            second.analyze(parser.parse());        } catch (ParserCreationException e) {            throw new UnsupportedOperationException(                "internal error in grammar parser: " + e.getMessage());        }        verify();    }    /**     * Checks that the grammar is valid.     *      * @throws GrammarException if the grammar wasn't valid     */    private void verify() throws GrammarException {        String  type;                // Check grammar type        type = (String) declarations.get(GRAMMAR_TYPE_DECLARATION);        if (type == null) {            throw new GrammarException(                fileName,                "grammar header missing " + GRAMMAR_TYPE_DECLARATION +                " declaration");        } else if (!type.equals("LL")) {            throw new GrammarException(                fileName,                "unrecognized " + GRAMMAR_TYPE_DECLARATION + " value: '" +                type + "', currently only 'LL' is supported");        }                // Check tokens and productions        if (productions.size() > 0) {            createParser(createTokenizer(null));        }    }    /**     * Creates a tokenizer from this grammar.     *      * @param in             the input stream to use     *      * @return the newly created tokenizer     *      * @throws GrammarException if the tokenizer couldn't be created      *             or initialized correctly     */    public Tokenizer createTokenizer(Reader in)         throws GrammarException {        Tokenizer  tokenizer;                try {            tokenizer = new Tokenizer(in);            for (int i = 0; i < tokens.size(); i++) {                tokenizer.addPattern((TokenPattern) tokens.get(i));            }        } catch (ParserCreationException e) {            if (e.getName() == null) {                throw new GrammarException(fileName, e.getMessage());            } else {                LineRange range = (LineRange) lines.get(e.getName());                throw new GrammarException(fileName,                                            e.getMessage(),                                           range.getStart(),                                           range.getEnd());            }        }        return tokenizer;    }    /**     * Creates a parser from this grammar.     *      * @param tokenizer      the tokenizer to use     *      * @return the newly created parser     *      * @throws GrammarException if the parser couldn't be created or      *             initialized correctly     */    public Parser createParser(Tokenizer tokenizer)         throws GrammarException {                    return createParser(tokenizer, null);    }    /**     * Creates a parser from this grammar.     *      * @param tokenizer      the tokenizer to use     * @param analyzer       the analyzer to use     *      * @return the newly created parser     *      * @throws GrammarException if the parser couldn't be created or      *             initialized correctly     */    public Parser createParser(Tokenizer tokenizer, Analyzer analyzer)         throws GrammarException {        Parser  parser;                try {            parser = new RecursiveDescentParser(tokenizer, analyzer);            for (int i = 0; i < productions.size(); i++) {                parser.addPattern((ProductionPattern) productions.get(i));            }            parser.prepare();        } catch (ParserCreationException e) {            LineRange range = (LineRange) lines.get(e.getName());            if (range == null) {                throw new GrammarException(fileName, e.getMessage());            } else {                throw new GrammarException(fileName,                                            e.getMessage(),                                           range.getStart(),                                           range.getEnd());            }        }        return parser;    }    /**     * Returns the grammar file name and path.     *      * @return the grammar file name and path     */    public String getFileName() {        return fileName;    }    /**     * Returns the declaration value for the specified name.      *      * @param name           the declaration name     *      * @return the declaration value, or      *         null if not specified in the grammar header     */    public String getDeclaration(String name) {        return (String) declarations.get(name);    }        /**     * Returns the number of token patterns in the grammar.      *      * @return the number of token patterns     */    public int getTokenPatternCount() {        return tokens.size();    }        /**     * Returns a specific token pattern.     *      * @param pos            the pattern position, 0 <= pos < count     *      * @return the token pattern     */    public TokenPattern getTokenPattern(int pos) {        return (TokenPattern) tokens.get(pos);    }    /**     * Returns a token pattern identified by its id.     *      * @param id             the pattern id     *      * @return the token pattern, or null     */    public TokenPattern getTokenPatternById(int id) {        return (TokenPattern) tokenIds.get(new Integer(id));    }    /**     * Returns a token pattern identified by its name.     *      * @param name           the pattern name     *      * @return the token pattern, or null     */    public TokenPattern getTokenPatternByName(String name) {        return (TokenPattern) tokenNames.get(name);    }    /**     * Returns a token pattern identified by its pattern string. This     * method will only return matches for patterns of string type.       *      * @param image          the pattern string     *      * @return the token pattern, or null     */    TokenPattern getTokenPatternByImage(String image) {        return (TokenPattern) tokenPatterns.get(image);    }    /**     * Returns the number of production patterns in the grammar.      *      * @return the number of production patterns     */    public int getProductionPatternCount() {        return productions.size();    }        /**     * Returns a specific production pattern.     *      * @param pos            the pattern position, 0 <= pos < count     *      * @return the production pattern     */    public ProductionPattern getProductionPattern(int pos) {        return (ProductionPattern) productions.get(pos);    }        /**     * Returns a production pattern identified by its id.     *      * @param id             the pattern id     *      * @return the production pattern, or null     */    public ProductionPattern getProductionPatternById(int id) {        return (ProductionPattern) productionIds.get(new Integer(id));    }    /**     * Returns a production pattern identified by its name.     *      * @param name           the pattern name     *      * @return the production pattern, or null     */    public ProductionPattern getProductionPatternByName(String name) {        return (ProductionPattern) productionNames.get(name);    }    /**     * Adds a grammar declaration name-value pair.     *      * @param name           the name part     * @param value          the value part     */    void addDeclaration(String name, String value) {        declarations.put(name, value);    }    /**     * Adds a token pattern to this grammar.     *      * @param token          the token pattern to add     * @param start          the starting line     * @param end            the ending line     */    void addToken(TokenPattern token, int start, int end) {        tokens.add(token);        tokenIds.put(new Integer(token.getId()), token);        tokenNames.put(token.getName(), token);        if (token.getType() == TokenPattern.STRING_TYPE) {            tokenPatterns.put(token.getPattern(), token);        }        lines.put(token.getName(), new LineRange(start, end));    }        /**     * Adds a production pattern to this grammar.     *      * @param production     the production pattern to add     * @param start          the starting line     * @param end            the ending line     */    void addProduction(ProductionPattern production, int start, int end) {        productions.add(production);        productionIds.put(new Integer(production.getId()), production);        productionNames.put(production.getName(), production);        lines.put(production.getName(), new LineRange(start, end));    }        /**     * A line number range.     */    private class LineRange {                /**         * The first line number.         */        private int start;                /**         * The last line number.         */        private int end;        /**         * Creates a new line number range.         *          * @param start      the first line number         * @param end        the last line number         */        public LineRange(int start, int end) {            this.start = start;            this.end = end;        }                /**         * Returns the first line number.         *          * @return the first line number         */        public int getStart() {            return start;        }                /**         * Returns the last line number.         *          * @return the last line number         */        public int getEnd() {            return end;        }    }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -