org.opencypher.generator.TreeBuilder Maven / Gradle / Ivy
The newest version!
/*
* Copyright (c) 2015-2018 "Neo Technology,"
* Network Engine for Objects in Lund AB [http://neotechnology.com]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Attribution Notice under the terms of the Apache License 2.0
*
* This work was created by the collective efforts of the openCypher community.
* Without limiting the terms of Section 6, any Derivative Work that is not
* approved by the public consensus process of the openCypher Implementers Group
* should not be described as “Cypher” (and Cypher® is a registered trademark of
* Neo4j Inc.) or as "openCypher". Extensions by implementers or prototypes or
* proposals for change that have been documented or implemented should only be
* described as "implementation extensions to Cypher" or as "proposed changes to
* Cypher that are not yet approved by the openCypher community".
*/
package org.opencypher.generator;
import java.util.Iterator;
import java.util.Map;
import java.util.function.Supplier;
import org.opencypher.grammar.Alternatives;
import org.opencypher.grammar.CharacterSet;
import org.opencypher.grammar.Grammar;
import org.opencypher.grammar.Literal;
import org.opencypher.grammar.NonTerminal;
import org.opencypher.grammar.Optional;
import org.opencypher.grammar.Production;
import org.opencypher.grammar.ProductionTransformation;
import org.opencypher.grammar.Repetition;
import org.opencypher.grammar.Sequence;
import org.opencypher.grammar.TermTransformation;
import static org.opencypher.generator.Node.root;
class TreeBuilder implements TermTransformation, TreeBuilder.State, RuntimeException>,
ProductionTransformation, RuntimeException>
{
private final Choices choice;
private final Supplier context;
private final Map> replacements;
TreeBuilder( Choices choice, Supplier context, Map> replacements )
{
this.choice = choice;
this.context = context;
this.replacements = replacements;
}
Node buildTree( State root )
{
for ( TreeBuilder.State state = root; state != null; )
{
state = state.generate( this );
}
return root.node;
}
@Override
public State transformProduction( Void param, Production production )
{
return state( production.definition(), root( production.name() ), context.get() );
}
static State state( Grammar.Term term, Node.Tree root, T context )
{
return new State<>( root, term, context, null );
}
@Override
public State transformAlternatives( State current, Alternatives alternatives )
{
return new State<>( current.node, choice.choose( current.node, alternatives.eligibleForGeneration() ),
current.context,
current.next() );
}
@Override
public State transformSequence( State current, Sequence sequence )
{
return sequence( current.node, sequence.iterator(), current.context, current.next() );
}
@Override
public State transformLiteral( State current, Literal value )
{
current.node.literal( value );
return current.next();
}
@Override
public State transformNonTerminal( State current, NonTerminal nonTerminal )
{
ProductionReplacement replacement = replacements.get( nonTerminal.productionName() );
if ( replacement != null )
{
current.node.production( nonTerminal.productionName(), replacement, current.context,
node -> buildTree( new State<>(
node, nonTerminal.productionDefinition(), current.context, null ) ) );
return current.next();
}
return new State<>(
current.node.child( nonTerminal.productionName() ),
nonTerminal.productionDefinition(),
current.context,
current.next() );
}
@Override
public State transformOptional( State current, Optional optional )
{
int times = choice.includeOptional( current.node, optional ) ? 1 : 0;
return repeat( current.node, times, optional.term(), current.context, current.next() );
}
@Override
public State transformRepetition( State current, Repetition repetition )
{
return repeat(
current.node,
choice.repetition( current.node, repetition ),
repetition.term(),
current.context,
current.next() );
}
@Override
public State transformEpsilon( State current )
{
return current.next();
}
@Override
public State transformCharacters( State current, CharacterSet characters )
{
return codePoint( current, choice.codePoint( current.node, characters ) );
}
private State codePoint( State current, int cp )
{
current.node.codePoint( cp );
return current.next();
}
private static State sequence( Node.Tree node, Iterator sequence, T context, State next )
{
return new StateSequence<>( sequence, node, context, next ).get();
}
private static State repeat( Node.Tree node, int times, Grammar.Term term, T context, State next )
{
return new StateRepetition<>( node, times, term, context, next ).get();
}
static final class State implements Supplier>
{
private final Node.Tree node;
private final Grammar.Term term;
private final T context;
private final Supplier> next;
private State( Node.Tree node, Grammar.Term term, T context, Supplier> next )
{
this.node = node;
this.term = term;
this.context = context;
this.next = next == null ? () -> null : next;
}
@Override
public String toString()
{
return "TreeBuilder.State{" + node + " @ " + term + "}";
}
private State next()
{
return next.get();
}
State generate( TreeBuilder builder )
{
return term.transform( builder, this );
}
@Override
public State get()
{
return this;
}
}
private static class StateSequence implements Supplier>
{
private final Iterator sequence;
private final Node.Tree node;
private final T context;
private final State next;
StateSequence( Iterator sequence, Node.Tree node, T context, State next )
{
this.sequence = sequence;
this.node = node;
this.context = context;
this.next = next;
}
@Override
public State get()
{
return sequence.hasNext() ? new State<>( node, sequence.next(), context, this ) : next;
}
}
private static class StateRepetition implements Supplier>
{
private final Node.Tree node;
private final Grammar.Term term;
private final T context;
private final State next;
private int count;
StateRepetition( Node.Tree node, int times, Grammar.Term term, T context, State next )
{
this.node = node;
this.count = times;
this.term = term;
this.context = context;
this.next = next;
}
@Override
public State get()
{
return count-- > 0 ? new State<>( node, term, context, this ) : next;
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy