definegrammarsymbols.java

来自「SRI international 发布的OAA框架软件」· Java 代码 · 共 855 行 · 第 1/2 页

JAVA
855
字号
package antlr_oaa;

/* ANTLR Translator Generator
 * Project led by Terence Parr at http://www.jGuru.com
 * Software rights: http://www.antlr.org/RIGHTS.html
 *
 * $Id: DefineGrammarSymbols.java,v 1.1 2002/11/08 17:38:07 agno Exp $
 */

import java.util.Hashtable;
import antlr_oaa.collections.impl.BitSet;

/**DefineGrammarSymbols is a behavior for the ANTLRParser that adds all
 * the token and rule symbols to the grammar symbol table.
 *
 * Token types are assigned to token symbols in this class also.
 * The token type for a token is done in the order seen (lexically).
 */
public class DefineGrammarSymbols implements ANTLRGrammarParseBehavior
{
	// Contains all of the defined parser and lexer Grammar's indexed by name
	protected Hashtable grammars = new Hashtable();
	// Contains all the TokenManagers indexed by name
	protected Hashtable tokenManagers = new Hashtable();
	// Current grammar (parser or lexer)
	protected Grammar grammar;
	// The tool under which this is invoked
	protected Tool tool;
	// The grammar analyzer object
	LLkAnalyzer analyzer;
	// The command-line arguments passed to the tool.
	// This allows each grammar to parse the arguments as it is created
	String[] args;
	// Name for default token manager does not match any valid name
	static final String DEFAULT_TOKENMANAGER_NAME = "*default";
	// Header actions apply to all parsers unless redefined
	// Contains all of the header actions indexed by name
	protected Hashtable headerActions = new Hashtable();
	// Place where preamble is stored until a grammar is defined
	Token thePreambleAction = new CommonToken(Token.INVALID_TYPE, ""); // init to empty token
	// The target language
	String language = "Java";

	protected int numLexers = 0;
	protected int numParsers = 0;
	protected int numTreeParsers = 0;

	public DefineGrammarSymbols(Tool tool_, String[] args_, LLkAnalyzer analyzer_)
	{
		tool = tool_;
		args = args_;
		analyzer = analyzer_;
	}
	public void _refStringLiteral(Token lit, Token label, int autoGenType, boolean lastInRule)
	{
		if (!(grammar instanceof LexerGrammar))
		{
			// String literals are treated like tokens except by the lexer
			String str = lit.getText();
			if ( grammar.tokenManager.getTokenSymbol(str) != null )
			{
				// string symbol is already defined
				return;
			}
			StringLiteralSymbol sl = new StringLiteralSymbol(str);
			int tt = grammar.tokenManager.nextTokenType();
			sl.setTokenType(tt);
			grammar.tokenManager.define(sl);
		}
	}
    /** Reference a token */
	public void _refToken(Token assignId,
								 Token t,
								 Token label,
								 Token args,
								 boolean inverted,
								 int autoGenType,
								 boolean lastInRule)
	{
		String id = t.getText();
		if (!grammar.tokenManager.tokenDefined(id))
		{
			int tt = grammar.tokenManager.nextTokenType();
			TokenSymbol ts = new TokenSymbol(id);
			ts.setTokenType(tt);
			grammar.tokenManager.define(ts);
		}
	}

    /** Abort the processing of a grammar due to syntax errors */
	public void abortGrammar()
	{
		if (grammar != null && grammar.getClassName() != null)
		{
			grammars.remove(grammar.getClassName());
		}
		grammar = null;
	}

	public void beginAlt(boolean doAST_)
	{
	}

	public void beginChildList()
	{
	}

	// Exception handling
	public void beginExceptionGroup() {
	}
	public void beginExceptionSpec(Token label) {
	}
	public void beginSubRule(Token label, int line, boolean not)
	{
	}
	public void beginTree(int line)  throws SemanticException
	{
	}
    /** Define a lexer or parser rule */
	public void defineRuleName(Token r,
										String access,
										boolean ruleAutoGen,
										String docComment)
		throws SemanticException
	{
		String id = r.getText();

		//		if ( Character.isUpperCase(id.charAt(0)) ) {
		if ( r.type == ANTLRTokenTypes.TOKEN_REF )
		{
			// lexer rule
			id = CodeGenerator.lexerRuleName(id);
			// make sure we define it as token identifier also
			if ( !grammar.tokenManager.tokenDefined(r.getText()) )
			{
				int tt = grammar.tokenManager.nextTokenType();
				TokenSymbol ts = new TokenSymbol(r.getText());
				ts.setTokenType(tt);
				grammar.tokenManager.define(ts);
			}
		}

		RuleSymbol rs;
		if ( grammar.isDefined(id) )
		{
			// symbol seen before?
			rs = (RuleSymbol) grammar.getSymbol(id);
			// rule just referenced or has it been defined yet?
			if ( rs.isDefined() )
			{
				tool.error("redefinition of rule "+id, grammar.getFilename(), r.getLine());
			}
		}
		else
		{
			rs = new RuleSymbol(id);
			grammar.define(rs);
		}
		rs.setDefined();
		rs.access = access;
		rs.comment = docComment;
	}

    /** Define a token from tokens {...}.
	 *  Must be label and literal or just label or just a literal.
	 */
	public void defineToken(Token tokname, Token tokliteral)
	{
		String name = null;
		String literal = null;
		if (tokname != null)
		{
			name = tokname.getText();
		}
		if (tokliteral != null)
		{
			literal = tokliteral.getText();
		}
		// System.out.println("defining " + name + " with literal " + literal);
		//
		if (literal != null)
		{
			StringLiteralSymbol sl=(StringLiteralSymbol)grammar.tokenManager.getTokenSymbol(literal);
			if ( sl != null)
			{
				// This literal is known already.
				// If the literal has no label already, but we can provide
				// one here, then no problem, just map the label to the literal
				// and don't change anything else.
				// Otherwise, labels conflict: error.
				if ( name==null || sl.getLabel()!=null )
				{
					tool.warning("Redefinition of literal in tokens {...}: " + literal, grammar.getFilename(), tokliteral.getLine());
					return;
				}
				else if ( name!=null )
				{
					// The literal had no label, but new def does.  Set it.
					sl.setLabel(name);
					// Also, map the label to the literal.
					grammar.tokenManager.mapToTokenSymbol(name, sl);
				}
			}
			// if they provide a name/label and that name/label already
			// exists, just hook this literal onto old token.
			if (name != null)
			{
				TokenSymbol ts = (TokenSymbol) grammar.tokenManager.getTokenSymbol(name);
				if (ts != null)
				{
					// watch out that the label is not more than just a token.
					// If it already has a literal attached, then: conflict.
					if ( ts instanceof StringLiteralSymbol )
					{
						tool.warning("Redefinition of token in tokens {...}: " + name, grammar.getFilename(), tokliteral.getLine());
						return;
					}
					// a simple token symbol such as DECL is defined
					// must convert it to a StringLiteralSymbol with a
					// label by co-opting token type and killing old
					// TokenSymbol.  Kill mapping and entry in vector
					// of token manager.
					// First, claim token type.
					int ttype = ts.getTokenType();
					// now, create string literal with label
					sl = new StringLiteralSymbol(literal);
					sl.setTokenType(ttype);
					sl.setLabel(name);
					// redefine this critter as a string literal
					grammar.tokenManager.define(sl);
					// make sure the label can be used also.
					grammar.tokenManager.mapToTokenSymbol(name, sl);
					return;
				}
				// here, literal was labeled but not by a known token symbol.
			}
			sl = new StringLiteralSymbol(literal);
			int tt = grammar.tokenManager.nextTokenType();
			sl.setTokenType(tt);
			sl.setLabel(name);
			grammar.tokenManager.define(sl);
			if (name != null)
			{
				// make the label point at token symbol too
				grammar.tokenManager.mapToTokenSymbol(name, sl);
			}
		}

		// create a token in the token manager not a literal
		else
		{
			if (grammar.tokenManager.tokenDefined(name))
			{
				tool.warning("Redefinition of token in tokens {...}: " + name, grammar.getFilename(), tokname.getLine());
				return;
			}
			int tt = grammar.tokenManager.nextTokenType();
			TokenSymbol ts = new TokenSymbol(name);
			ts.setTokenType(tt);
			grammar.tokenManager.define(ts);
		}
	}
	public void endAlt()
	{
	}
	public void endChildList()
	{
	}
	public void endExceptionGroup() {
	}
	public void endExceptionSpec() {
	}
	public void endGrammar()
	{
	}
    /** Called after the optional options section, to compensate for
	 * options that may not have been set.
	 * This method is bigger than it needs to be, but is much more
	 * clear if I delineate all the cases.
	 */
	public void endOptions()
	{
		// NO VOCAB OPTIONS
		if ( grammar.exportVocab==null && grammar.importVocab==null )
		{
			grammar.exportVocab = grammar.getClassName();
			// Can we get initial vocab from default shared vocab?
			if (tokenManagers.containsKey(DEFAULT_TOKENMANAGER_NAME))
			{
				// Use the already-defined token manager
				grammar.exportVocab = DEFAULT_TOKENMANAGER_NAME;
				TokenManager tm = (TokenManager) tokenManagers.get(DEFAULT_TOKENMANAGER_NAME);
				// System.out.println("No tokenVocabulary for '" + grammar.getClassName() + "', using default '" + tm.getName() + "'");
				grammar.setTokenManager(tm);
				return;
			}
			// no shared vocab for file, make new one
			// System.out.println("No exportVocab for '" + grammar.getClassName() + "', creating default '" + grammar.exportVocab + "'");
			TokenManager tm = new SimpleTokenManager(grammar.exportVocab, tool);
			grammar.setTokenManager(tm);
			// Add the token manager to the list of token managers
			tokenManagers.put(grammar.exportVocab, tm);
			// no default vocab, so make this the default vocab
			tokenManagers.put(DEFAULT_TOKENMANAGER_NAME, tm);
			return;
		}

		// NO OUTPUT, BUT HAS INPUT VOCAB
		if ( grammar.exportVocab==null && grammar.importVocab!=null )
		{
			grammar.exportVocab = grammar.getClassName();
			// first make sure input!=output
			if ( grammar.importVocab.equals(grammar.exportVocab) )
			{
				tool.warning("Grammar " + grammar.getClassName() +
								 " cannot have importVocab same as default output vocab (grammar name); ignored.");
				// kill importVocab option and try again: use default vocab
				grammar.importVocab = null;
				endOptions();
				return;
			}
			// check to see if the vocab is already in memory
			// (defined by another grammar in the file).  Not normal situation.
			if (tokenManagers.containsKey(grammar.importVocab))
			{
				// make a copy since we'll be generating a new output vocab
				// and we don't want to affect this one.  Set the name to
				// the default output vocab==classname.
				TokenManager tm = (TokenManager) tokenManagers.get(grammar.importVocab);
				// System.out.println("Duping importVocab of " + grammar.importVocab);
				TokenManager dup = (TokenManager)tm.clone();
				dup.setName(grammar.exportVocab);
				// System.out.println("Setting name to " + grammar.exportVocab);
				dup.setReadOnly(false);
				grammar.setTokenManager(dup);
				tokenManagers.put(grammar.exportVocab, dup);
				return;
			}
			// System.out.println("reading in vocab "+grammar.importVocab);
			// Must be a file, go get it.
			ImportVocabTokenManager tm =
				new ImportVocabTokenManager(grammar,
													 grammar.importVocab + CodeGenerator.TokenTypesFileSuffix + CodeGenerator.TokenTypesFileExt,
													 grammar.exportVocab,
													 tool);
			tm.setReadOnly(false); // since renamed, can write out
			// Add this token manager to the list so its tokens will be generated
			tokenManagers.put(grammar.exportVocab, tm);
			// System.out.println("vocab renamed to default output vocab of "+tm.getName());
			// Assign the token manager to this grammar.
			grammar.setTokenManager(tm);

			// set default vocab if none
			if (!tokenManagers.containsKey(DEFAULT_TOKENMANAGER_NAME))
			{
				tokenManagers.put(DEFAULT_TOKENMANAGER_NAME, tm);
			}

			return;
		}

		// OUTPUT VOCAB, BUT NO INPUT VOCAB
		if ( grammar.exportVocab!=null && grammar.importVocab==null )
		{
			// share with previous vocab if it exists
			if (tokenManagers.containsKey(grammar.exportVocab))
			{
				// Use the already-defined token manager
				TokenManager tm = (TokenManager) tokenManagers.get(grammar.exportVocab);
				// System.out.println("Sharing exportVocab of " + grammar.exportVocab);
				grammar.setTokenManager(tm);
				return;
			}
			// create new output vocab
			// System.out.println("Creating exportVocab " + grammar.exportVocab);
			TokenManager tm = new SimpleTokenManager(grammar.exportVocab, tool);
			grammar.setTokenManager(tm);
			// Add the token manager to the list of token managers
			tokenManagers.put(grammar.exportVocab, tm);
			// set default vocab if none
			if (!tokenManagers.containsKey(DEFAULT_TOKENMANAGER_NAME))
			{
				tokenManagers.put(DEFAULT_TOKENMANAGER_NAME, tm);
			}
			return;
		}

		// BOTH INPUT AND OUTPUT VOCAB
		if ( grammar.exportVocab!=null && grammar.importVocab!=null )
		{
			// don't want input==output
			if (grammar.importVocab.equals(grammar.exportVocab))
			{
				tool.error("exportVocab of " + grammar.exportVocab + " same as importVocab; probably not what you want");
			}
			// does the input vocab already exist in memory?
			if (tokenManagers.containsKey(grammar.importVocab))
			{
				// make a copy since we'll be generating a new output vocab
				// and we don't want to affect this one.
				TokenManager tm = (TokenManager) tokenManagers.get(grammar.importVocab);
				// System.out.println("Duping importVocab of " + grammar.importVocab);
				TokenManager dup = (TokenManager)tm.clone();
				dup.setName(grammar.exportVocab);
				// System.out.println("Setting name to " + grammar.exportVocab);
				dup.setReadOnly(false);
				grammar.setTokenManager(dup);
				tokenManagers.put(grammar.exportVocab, dup);
				return;
			}
			// Must be a file, go get it.
			ImportVocabTokenManager tm =
				new ImportVocabTokenManager(grammar,
													 grammar.importVocab + CodeGenerator.TokenTypesFileSuffix + CodeGenerator.TokenTypesFileExt,
													 grammar.exportVocab,
													 tool);
			tm.setReadOnly(false); // write it out as we've changed name
			// Add this token manager to the list so its tokens will be generated
			tokenManagers.put(grammar.exportVocab, tm);
			// Assign the token manager to this grammar.
			grammar.setTokenManager(tm);

			// set default vocab if none
			if (!tokenManagers.containsKey(DEFAULT_TOKENMANAGER_NAME))
			{
				tokenManagers.put(DEFAULT_TOKENMANAGER_NAME, tm);
			}

⌨️ 快捷键说明

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