/* MonkeyTalk - a cross-platform functional testing tool Copyright (C) 2012 Gorilla Logic, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program 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 Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ package com.gorillalogic.monkeytalk.parser; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Scanner; import java.util.regex.Matcher; import java.util.regex.Pattern; import com.gorillalogic.monkeytalk.Command; import com.gorillalogic.monkeytalk.utils.FileUtils; /** * Static helper class to support converting MonkeyTalk command strings into MonkeyTalk * {@link Command} objects. * * @see Command */ public class MonkeyTalkParser { private static final String CRAZY = "\u21D0\u21D1\u21D2\u21D3\u21D5\u21D4\u21DD\u21DC"; private static final Pattern TOKEN = Pattern .compile("[^\\s\"=]+=\"[^\"]*\"|[^\\s\"]+|\"[^\"]*\""); private MonkeyTalkParser() { } /** * Parse a MonkeyTalk command string into a list of tokens, correctly handling quoted strings * and escaped quotes. * * @param command * the MonkeyTalk command string * @return a list of tokens */ public static List<String> parse(String command) { List<String> tokens = new ArrayList<String>(); if (command == null) { return tokens; } // trim off any extra space command = command.trim(); if (command.startsWith(Command.COMMENT_PREFIX)) { // command is a comment, so just return a single token tokens.add(command); } else { // this is a hack: replace all escaped quotes with crazy unicode command = command.replaceAll("\\\\\"", CRAZY); Matcher tokenMatcher = TOKEN.matcher(command); while (tokenMatcher.find()) { String token = tokenMatcher.group(); // revert the hack, and put escaped quotes back into the token token = token.replaceAll(CRAZY, "\\\\\""); tokens.add(token); } } return tokens; } /** * Parse a MonkeyTalk text file, ignoring blanks, and return just a list of MonkeyTalk * {@link Command} objects. * * @param f * the MonkeyTalk input file * @return the list of Commands */ public static List<Command> parseFile(File f) { return parseFile(f, false, true); } /** * Parse a MonkeyTalk text file, with commands, blanks, and comments into a list of MonkeyTalk * {@link Command} objects. * * @param f * the MonkeyTalk input file * @param ignoreComments * if true, don't return any MonkeyTalk comments (aka lines beginning with * <code>#</code>). * @param ignoreBlanks * if true, don't return any blank lines * @return the list of Commands */ public static List<Command> parseFile(File f, boolean ignoreComments, boolean ignoreBlanks) { if (f == null) { return null; } try { String text = FileUtils.readFile(f); return parseText(text, ignoreComments, ignoreBlanks); } catch (FileNotFoundException ex) { return null; } catch (IOException ex) { return new ArrayList<Command>(); } } /** * Parse the MonkeyTalk command text, ignoring blanks, and return just a list of MonkeyTalk * {@link Command} objects. * * @param text * the MonkeyTalk command text * @return the list of Commands */ public static List<Command> parseText(String text) { return parseText(text, false, true); } /** * Parse the MonkeyTalk command text, with commands, blanks, and comments into a list of * MonkeyTalk {@link Command} objects. * * @param text * the MonkeyTalk command text * @param ignoreComments * if true, don't return any MonkeyTalk comment objects (aka if true lines beginning * with <code>#</code> will be ignored). * @param ignoreBlanks * if true, don't return any blank MonkeyTalk {@link Command} objects (aka if true * blank lines will be ignored). * @return the list of Commands */ public static List<Command> parseText(String text, boolean ignoreComments, boolean ignoreBlanks) { List<Command> commands = new ArrayList<Command>(); Scanner scanner = new Scanner(text); while (scanner.hasNextLine()) { String line = scanner.nextLine().trim(); if (ignoreBlanks && line.length() == 0) { continue; } if (ignoreComments && line.startsWith(Command.COMMENT_PREFIX)) { continue; } Command cmd = new Command(line); commands.add(cmd); } return commands; } }