Package org.antlr.tool

Source Code of org.antlr.tool.RandomPhrase

/*
* [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.
*/
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.
   */
  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 */
  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);
    }
  }
}
TOP

Related Classes of org.antlr.tool.RandomPhrase

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.