All Downloads are FREE. Search and download functionalities are using the official Maven repository.

nl.rrd.wool.model.command.WoolExpressionCommand Maven / Gradle / Ivy

Go to download

WOOL is a simple, powerful dialogue framework for creating virtual agent conversations.

The newest version!
/*
 * Copyright 2019 Roessingh Research and Development.
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a 
 * copy of this software and associated documentation files (the "Software"), 
 * to deal in the Software without restriction, including without limitation 
 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 
 * and/or sell copies of the Software, and to permit persons to whom the 
 * Software is furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
 * DEALINGS IN THE SOFTWARE.
 */

package nl.rrd.wool.model.command;

import java.io.IOException;
import java.io.StringReader;

import nl.rrd.wool.exception.LineNumberParseException;
import nl.rrd.wool.expressions.Expression;
import nl.rrd.wool.expressions.ExpressionParser;
import nl.rrd.wool.expressions.Token;
import nl.rrd.wool.expressions.Tokenizer;
import nl.rrd.wool.io.LineColumnNumberReader;
import nl.rrd.wool.parser.WoolBodyToken;
import nl.rrd.wool.utils.CurrentIterator;

public abstract class WoolExpressionCommand extends WoolCommand {

	/**
	 * Reads the content of a command as a code string. When this method
	 * returns, the iterator will be positioned after the command end token.
	 * 
	 * @param cmdStartToken the command start token
	 * @param tokens the token iterator positioned after the command start token
	 * @return the content
	 * @throws LineNumberParseException if a parsing error occurs
	 */
	protected static ReadContentResult readCommandContent(
			WoolBodyToken cmdStartToken, CurrentIterator tokens)
			throws LineNumberParseException {
		ReadContentResult result = new ReadContentResult();
		result.lineNum = tokens.getCurrent().getLineNum();
		result.colNum = tokens.getCurrent().getColNum();
		StringBuilder text = new StringBuilder();
		boolean foundEnd = false;
		while (!foundEnd && tokens.getCurrent() != null) {
			WoolBodyToken token = tokens.getCurrent();
			if (token.getType() == WoolBodyToken.Type.COMMAND_END) {
				foundEnd = true;
			} else {
				text.append(tokens.getCurrent().getText());
			}
			tokens.moveNext();
		}
		if (!foundEnd) {
			throw new LineNumberParseException("Command not terminated",
					cmdStartToken.getLineNum(), cmdStartToken.getColNum());
		}
		result.content = text.toString();
		return result;
	}
	
	protected static class ReadContentResult {
		public String content;
		public int lineNum;
		public int colNum;
	}
	
	/**
	 * Parses the specified command content. This method checks whether the
	 * command name is the specified name, and there is no expression.
	 * 
	 * @param cmdStartToken the command start token
	 * @param content the command content
	 * @param name the command name
	 * @return the parsed content
	 * @throws LineNumberParseException if a parsing error occurs
	 */
	protected static ParseContentResult parseCommandContentName(
			WoolBodyToken cmdStartToken, ReadContentResult content, String name)
			throws LineNumberParseException {
		ParseContentResult result = parseCommandContent(cmdStartToken, content);
		if (!result.name.equals(name)) {
			throw new LineNumberParseException(String.format(
					"Expected command \"%s\", found: %s", name, result.name),
					cmdStartToken.getLineNum(), cmdStartToken.getColNum());
		}
		if (result.expression != null) {
			throw new LineNumberParseException(String.format(
					"Unexpected content after command name \"%s\"", name),
					cmdStartToken.getLineNum(), cmdStartToken.getColNum());
		}
		return result;
	}

	/**
	 * Parses the specified command content. This method checks whether the
	 * command name is the specified name, and there is an expression.
	 * 
	 * @param cmdStartToken the command start token
	 * @param content the command content
	 * @param name the command name
	 * @return the parsed content
	 * @throws LineNumberParseException if a parsing error occurs
	 */
	protected static ParseContentResult parseCommandContentExpression(
			WoolBodyToken cmdStartToken, ReadContentResult content, String name)
			throws LineNumberParseException {
		ParseContentResult result = parseCommandContent(cmdStartToken, content);
		if (!result.name.equals(name)) {
			throw new LineNumberParseException(String.format(
					"Expected command \"%s\", found: %s", name, result.name),
					cmdStartToken.getLineNum(), cmdStartToken.getColNum());
		}
		if (result.expression == null) {
			throw new LineNumberParseException(String.format(
					"Expression not found in command \"%s\"", name),
					cmdStartToken.getLineNum(), cmdStartToken.getColNum());
		}
		return result;
	}
	
	/**
	 * Parses the specified command content. It tries to read a command name and
	 * an expression. If there is no expression, then the expression in the
	 * result will be null.
	 * 
	 * @param cmdStartToken the command start token
	 * @param content the command content
	 * @return the parsed content
	 * @throws LineNumberParseException if a parsing error occurs
	 */
	protected static ParseContentResult parseCommandContent(
			WoolBodyToken cmdStartToken, ReadContentResult content)
			throws LineNumberParseException {
		int lineOff = content.lineNum;
		int colOff = content.colNum;
		LineColumnNumberReader reader = new LineColumnNumberReader(
				new StringReader(content.content));
		Tokenizer tokenizer = new Tokenizer(reader);
		ExpressionParser parser = new ExpressionParser(tokenizer);
		try {
			try {
				parser.getConfig().setAllowDollarVariables(true);
				parser.getConfig().setAllowPlainVariables(false);
				return parseCommandContent(cmdStartToken, content, tokenizer,
						parser, lineOff, colOff);
			} finally {
				parser.close();
			}
		} catch (IOException ex) {
			throw new RuntimeException(ex.getMessage(), ex);
		}
	}

	private static ParseContentResult parseCommandContent(
			WoolBodyToken cmdStartToken, ReadContentResult content,
			Tokenizer tokenizer, ExpressionParser parser, int lineOff,
			int colOff) throws LineNumberParseException, IOException {
		ParseContentResult result = new ParseContentResult();
		Token nameToken;
		try {
			nameToken = tokenizer.readToken();
		} catch (LineNumberParseException ex) {
			throw createParseException("Invalid command name: " +
					ex.getError(), ex, lineOff, colOff);
		}
		if (nameToken == null) {
			throw new LineNumberParseException("Found empty command",
					cmdStartToken.getLineNum(), cmdStartToken.getColNum());
		}
		if (nameToken.getType() != Token.Type.NAME) {
			throw createParseException("Expected command name, found token: " +
					nameToken.getType(), nameToken.getLineNum(),
					nameToken.getColNum(), lineOff, colOff);
		}
		result.name = nameToken.getValue().toString();
		try {
			result.expression = parser.readExpression();
		} catch (LineNumberParseException ex) {
			throw createParseException("Invalid expression in command: " +
					ex.getError(), ex, lineOff, colOff);
		}
		int postExprLine = tokenizer.getLineNum();
		int postExprCol = tokenizer.getColNum();
		Token nextToken;
		try {
			nextToken = tokenizer.readToken();
		} catch (LineNumberParseException ex) {
			throw createParseException(
					"Unexpected content after expression in command",
					postExprLine, postExprCol, lineOff, colOff);
		}
		if (nextToken != null) {
			throw createParseException(
					"Unexpected content after expression in command",
					postExprLine, postExprCol, lineOff, colOff);
		}
		return result;
	}

	private static LineNumberParseException createParseException(String message,
			LineNumberParseException ex, int lineOff, int colOff)
			throws LineNumberParseException {
		return createParseException(message, ex.getLineNum(), ex.getColNum(),
				lineOff, colOff);
	}

	private static LineNumberParseException createParseException(String message,
			int lineNum, int colNum, int lineOff, int colOff)
			throws LineNumberParseException {
		int exLineNum = lineOff - 1 + lineNum;
		int exColNum = colNum;
		if (exLineNum == lineOff)
			exColNum += colOff - 1;
		return new LineNumberParseException(message, exLineNum, exColNum);
	}

	protected static class ParseContentResult {
		public String name;
		public Expression expression;
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy