// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. /** * @author bratseth */ options { CACHE_TOKENS = true; DEBUG_PARSER = false; ERROR_REPORTING = true; STATIC = false; UNICODE_INPUT = true; } PARSER_BEGIN(SemanticsParser) package com.yahoo.prelude.semantics.parser; import com.yahoo.javacc.UnicodeUtilities; import com.yahoo.prelude.semantics.*; import com.yahoo.prelude.semantics.rule.*; import com.yahoo.prelude.query.TermType; public class SemanticsParser { } PARSER_END(SemanticsParser) SKIP : { " " | "\f" | "\r" | "\t" } SPECIAL_TOKEN : { } TOKEN : { (["l","L"])? | (["l","L"])? | (["l","L"])?> | <#DECIMAL: ["1"-"9"] (["0"-"9"])*> | <#HEX: "0" ["x","X"] (["0"-"9","a"-"f","A"-"F"])+> | <#OCTAL: "0" (["0"-"7"])*> } TOKEN : { | | | | | | | | | | | | "> | ="> | | | | | | "> | | | "> | | | | | | | | } /** Parses a search definition and returns the resulting object */ RuleBase semanticRules(RuleBase rules,RuleImporter importer) : { } { ( LOOKAHEAD(2) | directive(rules,importer) | LOOKAHEAD(4) namedCondition(rules) | productionRule(rules) ) * { return rules; } } // ---------------------------------- Directive --------------------------------------- RuleBase directive(RuleBase rules,RuleImporter importer) : { String name; } { ( includeDirective(rules,importer) | defaultDirective(rules) | automataDirective(rules,importer) | stemmingDirective(rules) ) { return rules; } } void includeDirective(RuleBase rules,RuleImporter importer) : { String name; } { name=stringOrLiteral() ()? { try { importer.include(name,rules); } catch (java.io.IOException e) { ParseException ep=new ParseException("Could not read included rule base '" + name + "'"); ep.initCause(e); throw ep; } } } void automataDirective(RuleBase rules,RuleImporter importer) : { String name; } { name=stringOrLiteral() ()? { importer.setAutomata(rules,name); } } void defaultDirective(RuleBase rules) : { } { ()? { rules.setDefault(true); } } void stemmingDirective(RuleBase rules) : { String booleanString; } { booleanString=stringOrLiteral() ()? { rules.setStemming(Boolean.parseBoolean(booleanString)); } } // ---------------------------------- Production rules -------------------------------- void productionRule(RuleBase rules) : { ProductionRule rule; Condition condition; ProductionList production=null; } { condition=topLevelCondition() rule=productionRuleType() ( production=productionList() )? { rule.setCondition(condition); if (production!=null) rule.setProduction(production); rules.addRule(rule); } } ProductionRule productionRuleType() : { } { ( { return new ReplacingProductionRule(); } ) | ( { return new AddingProductionRule(); } ) } ProductionList productionList() : { ProductionList productionList=new ProductionList(); Production production; int weight=100; } { ( production=production() ( weight=number())? { production.setWeight(weight); productionList.addProduction(production); weight=100; } ()* ) + { return productionList; } } Production production() : { Production production; } { ( LOOKAHEAD(2) production=namespaceProduction() | production=termProduction() ) { return production; } } TermProduction termProduction() : { TermProduction termProduction; TermType termType; String label=null; } { termType=termType() ( LOOKAHEAD(2) label=label() )? ( termProduction=nonphraseTermProduction() | termProduction=phraseProduction() ) { termProduction.setLabel(label); termProduction.setTermType(termType); return termProduction; } } TermProduction nonphraseTermProduction() : { TermProduction termProduction; } { ( termProduction=referenceTermProduction() | termProduction=literalTermProduction() ) { return termProduction; } } LiteralPhraseProduction phraseProduction() : { LiteralPhraseProduction phraseProduction=new LiteralPhraseProduction(); String term=null; } { ( term=identifier() { phraseProduction.addTerm(term); } )+ { return phraseProduction; } } NamespaceProduction namespaceProduction() : { String namespace; String key; String value=null; } { namespace=identifier() key=stringOrLiteral() value=identifierOrLiteral() { return new NamespaceProduction(namespace,key,value); } } ReferenceTermProduction referenceTermProduction() : { String reference; } { reference=referenceIdentifier() { return new ReferenceTermProduction(reference); } } LiteralTermProduction literalTermProduction() : { String literal; } { literal=identifier() { return new LiteralTermProduction(literal); } } TermType termType() : { } { { return TermType.OR; } | { return TermType.RANK; } | { return TermType.AND; } | { return TermType.NOT; } | { return TermType.EQUIV; } | { return TermType.DEFAULT; } } String referenceIdentifier() : { String reference; } { ( reference=identifier() { return reference; } ) | ( { return "..."; } ) } // ---------------------------------- Conditions ------------------------------------- void namedCondition(RuleBase rules) : { String conditionName; Condition condition; } { conditionName=identifier() condition=topLevelCondition() { rules.addCondition(new NamedCondition(conditionName,condition)); } } Condition topLevelCondition() : { Condition condition; boolean startAnchor=false; boolean endAnchor=false; } { ( { startAnchor=true; } )? ( LOOKAHEAD(3) condition=choiceCondition() | LOOKAHEAD(3) condition=sequenceCondition() ) ( LOOKAHEAD(2) { endAnchor=true; } )? { condition.setAnchor(Condition.Anchor.create(startAnchor,endAnchor)); return condition; } } Condition condition() : { Condition condition; } { ( ( LOOKAHEAD(3) condition=choiceCondition() | condition=terminalCondition() ) { return condition; } ) } Condition terminalOrSequenceCondition() : { Condition condition; } { ( LOOKAHEAD(3) condition=sequenceCondition() | condition=terminalCondition() ) { return condition; } } Condition terminalCondition() : { Condition condition; } { ( condition=notCondition() | condition=terminalOrComparisonCondition() ) { return condition; } } Condition terminalOrComparisonCondition() : { Condition condition,rightCondition; String comparison; } { condition=reallyTerminalCondition() ( comparison=comparison() ( LOOKAHEAD(2) rightCondition=nestedCondition() | rightCondition=reallyTerminalCondition() ) // ( comparison=comparison() rightCondition=condition() { condition=new ComparisonCondition(condition,comparison,rightCondition); } ) ? { return condition; } } Condition reallyTerminalCondition() : { String label=null; String context=null; String nameSpace=null; Condition condition=null; } { // This body looks like this to distinguish these two cases // namespace.condition // condition . (end anchor) ( LOOKAHEAD(8) ( ( LOOKAHEAD(2) context=context() )? ( nameSpace=nameSpace() ) ( LOOKAHEAD(2) label=label() )? condition=terminalConditionBody() ) | ( ( LOOKAHEAD(2) context=context() )? ( LOOKAHEAD(2) label=label() )? condition=terminalConditionBody() ) ) { if (context!=null) condition.setContextName(context); condition.setLabel(label); condition.setNameSpace(nameSpace); return condition; } } Condition terminalConditionBody() : { Condition condition=null; } { ( LOOKAHEAD(2) condition=conditionReference() | condition=termCondition() | condition=nestedCondition() | condition=nonReferableEllipsisCondition() | condition=referableEllipsisCondition() | condition=superCondition() | condition=literalCondition() | condition=compositeItemCondition()) { return condition; } } Condition notCondition() : { Condition condition; } { condition=terminalOrComparisonCondition() { return new NotCondition(condition); } } ConditionReference conditionReference() : { String conditionName; } { conditionName=identifier() { return new ConditionReference(conditionName); } } EllipsisCondition nonReferableEllipsisCondition() : { } { { return new EllipsisCondition(false); } } EllipsisCondition referableEllipsisCondition() : { } { { return new EllipsisCondition(); } } Condition nestedCondition() : { Condition condition; } { condition=choiceCondition() { return condition; } } Condition sequenceCondition() : { SequenceCondition sequenceCondition=new SequenceCondition(); Condition condition; } { condition=terminalCondition() { sequenceCondition.addCondition(condition); } ( LOOKAHEAD(2) condition=terminalCondition() { sequenceCondition.addCondition(condition); } )* { if (sequenceCondition.conditionSize()==1) return sequenceCondition.removeCondition(0); else return sequenceCondition; } } Condition choiceCondition() : { ChoiceCondition choiceCondition=new ChoiceCondition(); Condition condition; } { condition=terminalOrSequenceCondition() { choiceCondition.addCondition(condition); } ( LOOKAHEAD(3) ()* ()* condition=terminalOrSequenceCondition() { choiceCondition.addCondition(condition); } ) * { if (choiceCondition.conditionSize()==1) return choiceCondition.removeCondition(0); else return choiceCondition; } } TermCondition termCondition() : { String str; } { ( str = identifier() ) { return new TermCondition(str); } } SuperCondition superCondition() : { } { ( ) { return new SuperCondition(); } } LiteralCondition literalCondition() : { String str; } { ( str = literal() ) { return new LiteralCondition(str); } } CompositeItemCondition compositeItemCondition() : { Condition condition; CompositeItemCondition compositeItemCondition = new CompositeItemCondition(); } { ( ( condition=terminalConditionBody() { compositeItemCondition.addCondition(condition); } ) ) { return compositeItemCondition; } } // ---------------------------------- Primitives ------------------------------------- String context() : { String str; } { ( str = identifier() ) { return str; } } String label() : { String str; } { ( str = identifier() ) { return str; } } String nameSpace() : { String str; } { ( str = identifier() ) { return str; } } String identifier() : { } { ( | ) { return token.image; } } String stringOrLiteral() : { String str; } { ( str = string() | str = literal() ) { return str; } } String identifierOrLiteral() : { String str; } { ( str = identifier() | str = literal() ) { return str; } } String comparison() : { } { ( | | | | | | ) { return token.image; } } String string() : { StringBuilder str = new StringBuilder(); } { ( ( | | | ) { str.append(token.image); } ) + { return str.toString(); } } String literal() : { } { ( ) { return UnicodeUtilities.unquote(token.image); } } int number() : { } { { return Integer.decode(token.image); } }