/*
 * [The "BSD license"]
 *  Copyright (c) 2010 Terence Parr
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *  1. Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *  2. Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *  3. The name of the author may not be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 *  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 *  OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 *  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
package org.antlr.tool;

import org.antlr.Tool;
import org.antlr.analysis.Label;
import org.antlr.analysis.NFAState;
import org.antlr.analysis.RuleClosureTransition;
import org.antlr.analysis.Transition;
import org.antlr.misc.IntervalSet;
import org.antlr.misc.Utils;

import java.io.BufferedReader;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Random;
import java.util.Stack;

Generate a random phrase given a grammar. Usage: java org.antlr.tool.RandomPhrase grammarFile.g startRule [seed] For example: java org.antlr.tool.RandomPhrase simple.g program 342 The seed acts like a unique identifier so you can get the same random phrase back during unit testing, for example. If you do not specify a seed then the current time in milliseconds is used guaranteeing that you'll never see that seed again. NOTE: this does not work well for large grammars...it tends to recurse too much and build really long strings. I need throttle control; later.
/** Generate a random phrase given a grammar. * Usage: * java org.antlr.tool.RandomPhrase grammarFile.g startRule [seed] * * For example: * java org.antlr.tool.RandomPhrase simple.g program 342 * * The seed acts like a unique identifier so you can get the same random * phrase back during unit testing, for example. * * If you do not specify a seed then the current time in milliseconds is used * guaranteeing that you'll never see that seed again. * * NOTE: this does not work well for large grammars...it tends to recurse * too much and build really long strings. I need throttle control; later. */
public class RandomPhrase { public static final boolean debug = false; protected static Random random;
an experimental method to generate random phrases for a given grammar given a start rule. Return a list of token types.
/** an experimental method to generate random phrases for a given * grammar given a start rule. Return a list of token types. */
protected static void randomPhrase(Grammar g, List<Integer> tokenTypes, String startRule) { NFAState state = g.getRuleStartState(startRule); NFAState stopState = g.getRuleStopState(startRule); Stack<NFAState> ruleInvocationStack = new Stack<NFAState>(); while ( true ) { if ( state==stopState && ruleInvocationStack.isEmpty() ) { break; } if ( debug ) System.out.println("state "+state); if ( state.getNumberOfTransitions()==0 ) { if ( debug ) System.out.println("dangling state: "+state); return; } // end of rule node if ( state.isAcceptState() ) { NFAState invokingState = ruleInvocationStack.pop(); if ( debug ) System.out.println("pop invoking state "+invokingState); //System.out.println("leave "+state.enclosingRule.name); RuleClosureTransition invokingTransition = (RuleClosureTransition)invokingState.transition[0]; // move to node after state that invoked this rule state = invokingTransition.followState; continue; } if ( state.getNumberOfTransitions()==1 ) { // no branching, just take this path Transition t0 = state.transition[0]; if ( t0 instanceof RuleClosureTransition ) { ruleInvocationStack.push(state); if ( debug ) System.out.println("push state "+state); //System.out.println("call "+((RuleClosureTransition)t0).rule.name); //System.out.println("stack depth="+ruleInvocationStack.size()); } else if ( t0.label.isSet() || t0.label.isAtom() ) { tokenTypes.add( getTokenType(t0.label) ); } state = (NFAState)t0.target; continue; } int decisionNumber = state.getDecisionNumber(); if ( decisionNumber==0 ) { System.out.println("weird: no decision number but a choice node"); continue; } // decision point, pick ith alternative randomly int n = g.getNumberOfAltsForDecisionNFA(state); int randomAlt = random.nextInt(n) + 1; if ( debug ) System.out.println("randomAlt="+randomAlt); NFAState altStartState = g.getNFAStateForAltOfDecision(state, randomAlt); Transition t = altStartState.transition[0]; state = (NFAState)t.target; } } protected static Integer getTokenType(Label label) { if ( label.isSet() ) { // pick random element of set IntervalSet typeSet = (IntervalSet)label.getSet(); int randomIndex = random.nextInt(typeSet.size()); return typeSet.get(randomIndex); } else { return Utils.integer(label.getAtom()); } //System.out.println(t0.label.toString(g)); }
Used to generate random strings
/** Used to generate random strings */
public static void main(String[] args) { if ( args.length < 2 ) { System.err.println("usage: java org.antlr.tool.RandomPhrase grammarfile startrule"); return; } String grammarFileName = args[0]; String startRule = args[1]; long seed = System.currentTimeMillis(); // use random seed unless spec. if ( args.length==3 ) { String seedStr = args[2]; seed = Long.parseLong(seedStr); } try { random = new Random(seed); CompositeGrammar composite = new CompositeGrammar(); Tool tool = new Tool(); Grammar parser = new Grammar(tool, grammarFileName, composite); composite.setDelegationRoot(parser); FileReader fr = new FileReader(grammarFileName); BufferedReader br = new BufferedReader(fr); parser.parseAndBuildAST(br); br.close(); parser.composite.assignTokenTypes(); parser.composite.defineGrammarSymbols(); parser.composite.createNFAs(); List<? extends Collection<? extends Rule>> leftRecursiveRules = parser.checkAllRulesForLeftRecursion(); if ( leftRecursiveRules.size()>0 ) { return; } if ( parser.getRule(startRule)==null ) { System.out.println("undefined start rule "+startRule); return; } String lexerGrammarText = parser.getLexerGrammar(); Grammar lexer = new Grammar(tool); lexer.importTokenVocabulary(parser); lexer.fileName = grammarFileName; if ( lexerGrammarText!=null ) { lexer.setGrammarContent(lexerGrammarText); } else { System.err.println("no lexer grammar found in "+grammarFileName); } lexer.buildNFA(); leftRecursiveRules = lexer.checkAllRulesForLeftRecursion(); if ( leftRecursiveRules.size()>0 ) { return; } //System.out.println("lexer:\n"+lexer); List<Integer> tokenTypes = new ArrayList<Integer>(100); randomPhrase(parser, tokenTypes, startRule); System.out.println("token types="+tokenTypes); for (int i = 0; i < tokenTypes.size(); i++) { Integer ttypeI = tokenTypes.get(i); int ttype = ttypeI; String ttypeDisplayName = parser.getTokenDisplayName(ttype); if ( Character.isUpperCase(ttypeDisplayName.charAt(0)) ) { List<Integer> charsInToken = new ArrayList<Integer>(10); randomPhrase(lexer, charsInToken, ttypeDisplayName); System.out.print(" "); for (int j = 0; j < charsInToken.size(); j++) { Integer cI = charsInToken.get(j); System.out.print((char)cI.intValue()); } } else { // it's a literal String literal = ttypeDisplayName.substring(1,ttypeDisplayName.length()-1); System.out.print(" "+literal); } } System.out.println(); } catch (Error er) { System.err.println("Error walking "+grammarFileName+" rule "+startRule+" seed "+seed); er.printStackTrace(System.err); } catch (Exception e) { System.err.println("Exception walking "+grammarFileName+" rule "+startRule+" seed "+seed); e.printStackTrace(System.err); } } }