package Breccia.parser.plain; import Breccia.parser.AdjunctSlow; import Breccia.parser.CommandPoint; import Breccia.parser.Granum; import Java.DelimitableCharSequence; import java.util.ArrayList; import java.util.List; import static Java.CharBuffers.newDelimitableCharSequence; /** @param The type of cursor. */ public abstract class CommandPoint_ extends Point_ implements CommandPoint { /** Makes a command point with a compound command, one that may comprise more than the keyword. */ CommandPoint_( final C cursor ) { this( cursor, false ); } /** @param hasSimpleCommand Whether the command always comprises the keyword alone. * If true, then never add to its component list; rather leave it empty. */ CommandPoint_( final C cursor, final boolean hasSimpleCommand ) { super( cursor ); components = List.of( perfectIndent, bullet, descriptor ); keyword = hasSimpleCommand? command.text : newDelimitableCharSequence(cursor.buffer); } // ━━━ C o m m a n d P o i n t ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ public final @Override AppendageClause appendageClause() throws MalformedText { ensureComposition(); return appendageClause; } public final @Override List modifiers() { return modifiers; } // ━━━ G r a n u m ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ public final @Override List components() { return components; } // ━━━ P o i n t ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ public final @Override Descriptor descriptor() { return descriptor; } //// P r i v a t e //////////////////////////////////////////////////////////////////////////////////// AppendageClause appendageClause; final AppendageClause_ appendageClauseWhenPresent = new AppendageClause_(); final Command command = new Command(); private final List components; final Descriptor descriptor = new Descriptor(); /** @see BrecciaCursor#commandPointKeywords */ final DelimitableCharSequence keyword; final List modifiers = new ArrayList<>( /*initial capacity*/2 ); // ━━━ F r a c t u m _ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ protected @Override void commit() { super.commit(); cursor.commandPoint( this ); } // ━━━ P o i n t _ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ /** Late composition. Do not call this method directly. It is called by `ensureComposition` alone, * which in turn is called by the access methods of the parts of this command point that allow * for late composition, namely `appendageClause`, `descriptor.components` and any others * specified by subclasses, q.v. * * @see #ensureComposition() * @see #appendageClause() * @see Descriptor#components() */ abstract @Override void compose() throws MalformedText; // ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ final class Appendage extends Granum_ { Appendage() { super( CommandPoint_.this.cursor ); } final CoalescentGranalList components = new GranalArrayList( cursor.spooler ); // ━━━ G r a n u m ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ public @Override @AdjunctSlow int column() { return cursor.bufferColumn( text.start() ); } public @Override List components() { assert components.isFlush(); return components; } public @Override @AdjunctSlow int lineNumber() { return cursor.bufferLineNumber( text.start() ); } public @Override String tagName() { return "Appendage"; }} // ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ final class AppendageClause_ extends Granum_ implements AppendageClause { AppendageClause_() { super( CommandPoint_.this.cursor ); components = List.of( delimiter, appendage ); } final Appendage appendage = new Appendage(); private final List components; final FlatGranum delimiter = FlatGranum.make( cursor, "Delimiter"); // ━━━ A p p e n d a g e C l a u s e ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ public @Override Granum appendage() { return appendage; } public @Override Granum delimiter() { return delimiter; } // ━━━ G r a n u m ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ public @Override @AdjunctSlow int column() { return cursor.bufferColumn( text.start() ); } public @Override List components() { return components; } public @Override @AdjunctSlow int lineNumber() { return cursor.bufferLineNumber( text.start() ); }} // ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ final class Command extends Granum_ { Command() { super( CommandPoint_.this.cursor ); } final CoalescentGranalList components = new GranalArrayList( cursor.spooler ); // ━━━ G r a n u m ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ public @Override @AdjunctSlow int column() { // The command is collinear with the bullet. return bullet.column() + cursor.bufferClusterCount(bullet.text.start(),text.start()); } public @Override List components() { assert components.isFlush(); return components; } public @Override @AdjunctSlow int lineNumber() { return CommandPoint_.this.lineNumber(); } // Always the command begins on the first line of the command point. public @Override String tagName() { return "Command"; }} // ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ protected abstract class End_ extends Point_.End_ implements CommandPoint.End { protected @Override void commit() { super.commit(); cursor.commandPointEnd( this ); }}} // Copyright © 2021-2022 Michael Allan. Licence MIT.