@Test public void testAggregateRule() { Parser<AggregateSlot> sut = TagSpaceTerminalParser.buildParser(TagSpaceRuleParser.AGGREGATE_SLOT_RULE); List<ValueDefinition> valueDefinitions = new LinkedList<>( Arrays.asList( vDef("clear", ""), vDef("encrypt", ""), vDef("clientSide", ""), vDef("doubleEncrypt", ""))); assertEquals( new AggregateSlot("Transfer", "", valueDefinitions), sut.parse("Transfer: some of clear, encrypt, clientSide, doubleEncrypt.")); assertEquals( new AggregateSlot("Transfer", "How we transfer the data", valueDefinitions), sut.parse( "Transfer [How we transfer the data]: some of clear, encrypt, clientSide, doubleEncrypt.")); assertEquals( new AggregateSlot("Transfer", "How we transfer the data", valueDefinitions), sut.parse( "Transfer [How we transfer the data]<* err, what?*>: some of clear, encrypt, clientSide, doubleEncrypt. <--- la la la")); valueDefinitions.add( new ValueDefinition("superEncrypt", "does not really exist but sounds good")); assertEquals( new AggregateSlot("Transfer", "How we transfer the data", valueDefinitions), sut.parse( "Transfer [How we transfer the data]: some of clear, encrypt, clientSide, doubleEncrypt, superEncrypt [does not really exist but sounds good].")); }
@Test public void testValueDefinition() { Parser<ValueDefinition> sut = TagSpaceTerminalParser.buildParser(TagSpaceRuleParser.VALUE_DEFINITION_RULE); assertEquals(new ValueDefinition("clear", ""), sut.parse("clear")); ValueDefinition expected = new ValueDefinition("clear", "a value that is not encrypted at all"); assertEquals(expected, sut.parse("clear [a value that is not encrypted at all]")); assertEquals( expected, sut.parse("clear [a value that is not encrypted at all] <-- This is a line comment")); assertEquals(expected, sut.parse("<*un*>clear [a value that is not encrypted at all]")); }
@Test public void testRule() { Parser<? extends AbstractSlot> sut = TagSpaceTerminalParser.buildParser(TagSpaceRuleParser.RULE); assertEquals(new ToDoSlot("Test", ""), sut.parse("Test: TODO.")); assertEquals( new AtomicSlot("Test", "a test slot", Arrays.asList(vDef("A"), vDef("B", "value b"))), sut.parse("Test [a test slot]: one of A, B[value b].")); assertEquals( new AggregateSlot("Test", "", Arrays.asList(vDef("A"), vDef("B", "value b"))), sut.parse("Test: some of A, B[value b].")); assertEquals( new CompoundSlot("Test", "", Arrays.asList("A", "B", "C")), sut.parse("Test: consists of A, B, C.")); }
@Test public void testCompoundRule() { Parser<CompoundSlot> sut = TagSpaceTerminalParser.buildParser(TagSpaceRuleParser.COMPOUND_SLOT_RULE); List<String> subSlots = Arrays.asList("HIPAA", "FERPA", "PrivacyAct", "JUnit"); assertEquals( new CompoundSlot("Legal", "", subSlots), sut.parse("Legal: consists of HIPAA, FERPA, PrivacyAct, JUnit.")); assertEquals( new CompoundSlot("Legal", "Aspects of the dataset by act", subSlots), sut.parse( "Legal [Aspects of the dataset by act]: consists of HIPAA, FERPA, PrivacyAct, JUnit.")); assertEquals( new CompoundSlot("Legal", "Aspects of the dataset by act", subSlots), sut.parse( "Legal<*please ignore me!*> [Aspects of the dataset by act]: consists of HIPAA, FERPA, PrivacyAct, JUnit. <--- la la la")); }
@Test public void testAtomicRule() { Parser<AtomicSlot> sut = TagSpaceTerminalParser.buildParser(TagSpaceRuleParser.ATOMIC_SLOT_RULE); List<ValueDefinition> valueDefinitions = Arrays.asList( vDef("clear", ""), vDef("encrypt", ""), vDef("clientSide", ""), vDef("doubleEncrypt", "")); assertEquals( new AtomicSlot("Transfer", "", valueDefinitions), sut.parse("Transfer: one of clear, encrypt, clientSide, doubleEncrypt.")); assertEquals( new AtomicSlot("Transfer", "How we transfer the data", valueDefinitions), sut.parse( "Transfer [How we transfer the data]: one of clear, encrypt, clientSide, doubleEncrypt.")); assertEquals( new AtomicSlot("Transfer", "How we transfer the data", valueDefinitions), sut.parse( "Transfer [How we transfer the data]<* err, what?*>: one of clear, encrypt, clientSide, doubleEncrypt. <--- la la la")); }
@Test public void testTodoRule() { Parser<ToDoSlot> sut = TagSpaceTerminalParser.buildParser(TagSpaceRuleParser.TODO_RULE); assertEquals(new ToDoSlot("Procrastination", ""), sut.parse("Procrastination: TODO.")); assertEquals(new ToDoSlot("Procrastination", ""), sut.parse("Procrastination: TODO .")); assertEquals(new ToDoSlot("Procrastination", ""), sut.parse("Procrastination: TODO \n.")); assertEquals( new ToDoSlot("Procrastination", ""), sut.parse("\t \t Procrastination: \n \t \t \tTODO<*!!!*> \n.")); assertEquals( new ToDoSlot("Procrastination", "I'll get to this later"), sut.parse("Procrastination [I'll get to this later]: TODO.")); assertEquals( new ToDoSlot("Procrastination", "I'll get to this later"), sut.parse("Procrastination [I'll get to this later] <--- Yeah, right\n\t: TODO.")); }
/** * Plugin for string related literals, operations, and functions. * * @author Mashaal Memon, Roozbeh Farahbod */ public class StringPlugin extends Plugin implements ParserPlugin, InterpreterPlugin, OperatorProvider, VocabularyExtender { public static final VersionInfo VERSION_INFO = new VersionInfo(0, 4, 1, ""); public static final String STRING_TOKEN = "STRING"; public static final String STRINGCONCAT_OP = "+"; public static final String PLUGIN_NAME = StringPlugin.class.getSimpleName(); // TODO why do we have this as a static field? // public static StringBackgroundElement STRING_BACKGROUND_ELEMENT; private StringBackgroundElement stringBackgroundElement; private Map<String, FunctionElement> funcs = null; private Map<String, BackgroundElement> backgroundElements = null; private Map<String, GrammarRule> parsers = null; private Set<Parser<? extends Object>> lexers = null; // private final Parser<Node>[] stringTermParserArray = new Parser[1]; // private final Parser<Node> stringTermParser = ParserTools.lazy("StringTerm", // stringTermParserArray); Parser.Reference<Node> refStringTermParser = Parser.newReference(); Parser<String> tokenizer_str = null; private final String[] keywords = {}; private final String[] operators = {"+"}; private CompilerPlugin compilerPlugin = new CompilerStringPlugin(this); @Override public CompilerPlugin getCompilerPlugin() { return compilerPlugin; } public String[] getKeywords() { return keywords; } public String[] getOperators() { return operators; } /* (non-Javadoc) * @see org.coreasm.engine.Plugin#interpret(org.coreasm.engine.interpreter.Node) */ public ASTNode interpret(Interpreter interpreter, ASTNode pos) { ASTNode nextPos = pos; String x = pos.getToken(); String gClass = pos.getGrammarClass(); // if number related expression if (gClass.equals(ASTNode.EXPRESSION_CLASS)) { // it is a number constant if (x != null) { // get new string element representing lexeme from string background StringElement se = stringBackgroundElement.getNewValue(x); // result of this node is the string element produced pos.setNode(null, null, se); } } return nextPos; } public Set<Parser<? extends Object>> getLexers() { if (lexers == null) { lexers = new HashSet<Parser<? extends Object>>(); tokenizer_str = Terminals.StringLiteral.DOUBLE_QUOTE_TOKENIZER; lexers.add(tokenizer_str); } return lexers; } /* * @see org.coreasm.engine.plugin.ParserPlugin#getParser(java.lang.String) */ public Parser<Node> getParser(String nonterminal) { if (nonterminal.equals("StringTerm")) return refStringTermParser.lazy(); else return null; } public Map<String, GrammarRule> getParsers() { if (parsers == null) { // org.coreasm.engine.parser.Parser parser = capi.getParser(); parsers = new HashMap<String, GrammarRule>(); Parser<Node> stringParser = Terminals.StringLiteral.PARSER .token() .map( new org.codehaus.jparsec.functors.Map<Token, Node>() { @Override public Node map(Token from) { return new StringNode( StringElement.processEscapeCharacters(from.toString()), new ScannerInfo(from)); } }); refStringTermParser.set(stringParser); parsers.put( "ConstantTerm", new GrammarRule("StringConstantTerm", "STRING", refStringTermParser.lazy(), PLUGIN_NAME)); } return parsers; } /* (non-Javadoc) * @see org.coreasm.engine.Plugin#initialize() */ @Override public void initialize() {} // -------------------------------- // Vocabulary Extender Interface // -------------------------------- /** @see org.coreasm.engine.plugin.VocabularyExtender#getFunctions() */ public Map<String, FunctionElement> getFunctions() { if (funcs == null) { funcs = new HashMap<String, FunctionElement>(); funcs.put(ToStringFunctionElement.TOSTRING_FUNC_NAME, new ToStringFunctionElement()); funcs.put(StringLengthFunctionElement.STRLENGTH_FUNC_NAME, new StringLengthFunctionElement()); funcs.put( StringMatchingFunction.STRING_MATCHES_FUNCTION_NAME, new StringMatchingFunction(capi)); funcs.put( StringSubstringFunction.STRING_SUBSTRING_FUNCTION_NAME, new StringSubstringFunction()); } return funcs; } public Set<String> getRuleNames() { return Collections.emptySet(); } public Map<String, RuleElement> getRules() { return null; } /** @see org.coreasm.engine.plugin.VocabularyExtender#getUniverses() */ public Map<String, UniverseElement> getUniverses() { // no universes return Collections.emptyMap(); } /** @see org.coreasm.engine.plugin.VocabularyExtender#getBackgrounds() */ public Map<String, BackgroundElement> getBackgrounds() { if (backgroundElements == null) { backgroundElements = new HashMap<String, BackgroundElement>(); stringBackgroundElement = new StringBackgroundElement(); backgroundElements.put( StringBackgroundElement.STRING_BACKGROUND_NAME, stringBackgroundElement); } return backgroundElements; } // -------------------------------- // Operator Implementor Interface // -------------------------------- public Collection<OperatorRule> getOperatorRules() { ArrayList<OperatorRule> opRules = new ArrayList<OperatorRule>(); opRules.add(new OperatorRule(STRINGCONCAT_OP, OpType.INFIX_LEFT, 750, PLUGIN_NAME)); return opRules; } public Element interpretOperatorNode(Interpreter interpreter, ASTNode opNode) throws InterpreterException { Element result = null; String x = opNode.getToken(); String gClass = opNode.getGrammarClass(); // if class of operator is binary if (gClass.equals(ASTNode.BINARY_OPERATOR_CLASS)) { // get operand nodes ASTNode alpha = opNode.getFirst(); ASTNode beta = alpha.getNext(); // get operand values Element l = alpha.getValue(); Element r = beta.getValue(); // if both operands are undef, the result is undef if (l.equals(Element.UNDEF) && r.equals(Element.UNDEF)) { capi.warning( PLUGIN_NAME, "Both operands of the '" + x + "' operator were undef.", opNode, interpreter); result = Element.UNDEF; } else // confirm that at least one of the operands is a string elements, otherwise throw an error if ((l instanceof StringElement || r instanceof StringElement)) { if (x.equals(STRINGCONCAT_OP)) result = stringBackgroundElement.getNewValue(l.toString() + r); } // otherwise // throw new InterpreterException("At least one operand must be strings for '"+x+"' // operation."); } return result; } /** This plugin requires "NumberPlugin". */ public Set<String> getDependencyNames() { Set<String> names = new HashSet<String>(super.getDependencyNames()); names.add("NumberPlugin"); return names; } public Set<String> getBackgroundNames() { return backgroundElements.keySet(); } public Set<String> getFunctionNames() { return funcs.keySet(); } public Set<String> getUniverseNames() { return Collections.emptySet(); } public VersionInfo getVersionInfo() { return VERSION_INFO; } /** A pattern to match string litterals. */ // public static final class StringPattern extends Pattern { // // private static final long serialVersionUID = 1L; // // public int match(final CharSequence src, final int len, final int from) { // if(from >= len) // return Pattern.MISMATCH; // if (src.charAt(from) != '"') // return Pattern.MISMATCH; // // for (int i=from+1; i < len; i++) { // char c = src.charAt(i); // if (c == '"' && src.charAt(i-1) != '\\') // return i+1 - from; // } // // return Pattern.MISMATCH; // } // // public String toString(){ // return "string constant"; // } // // } /** Creates string tokens. */ // @SuppressWarnings("serial") // public static class StringTokenizer implements Tokenizer { // // public Object toToken(CharSequence cs, int from, int len) { // TypedToken<StringTokenType> tToken = // new TypedToken<StringTokenType>(cs.subSequence(from, from + len).toString(), // StringTokenType.String); // return tToken; // } // // } /** * Type of string tokens. * * @author trident */ public static enum StringTokenType { String } }