Commit 8a1e3690 authored by earplov's avatar earplov
Browse files

artf707902 and artf707903: cfg section handlers and cfg editor pages for: include, define


Signed-off-by: default avatarearplov <arpad.lovassy@ericsson.com>
parent 3cdd0801
package org.eclipse.titan.common.parsers;
import java.util.List;
import org.antlr.v4.runtime.Parser;
import org.antlr.v4.runtime.misc.Interval;
import org.antlr.v4.runtime.tree.ParseTree;
import org.antlr.v4.runtime.tree.ParseTreeVisitor;
//NOTE: it doesn't know its start and end tokens, it just contains a string
/**
* Parse tree type for adding new strings to an existing ParseTree structure,
* which was build during a parsing.
* It has no info about its start and end tokens, it just contains a string
* It can have children
* @author Arpad Lovassy
*/
public class AddedParseTree implements ParseTree {
private String mText;
public List<ParseTree> children;
public AddedParseTree( final String aText ) {
mText = aText;
......@@ -24,7 +27,7 @@ public class AddedParseTree implements ParseTree {
@Override
public int getChildCount() {
return children != null ? children.size() : 0;
return 0;
}
@Override
......@@ -44,7 +47,7 @@ public class AddedParseTree implements ParseTree {
@Override
public ParseTree getChild( int i ) {
return children != null && i >= 0 && i < children.size() ? children.get( i ) : null;
return null;
}
@Override
......
......@@ -321,10 +321,10 @@ pr_Section returns [ ISection section ]:
{ $section = null;
}
( pr_MainControllerSection
| i = pr_IncludeSection { $section = $i.includeSection; }
| i = pr_IncludeSection { $section = $i.includeSection; includeSectionHandler.setLastSectionRoot( $i.ctx ); }
| pr_OrderedIncludeSection
| pr_ExecuteSection
| pr_DefineSection
| d = pr_DefineSection { defineSectionHandler.setLastSectionRoot( $d.ctx ); }
| pr_ExternalCommandsSection
| pr_TestportParametersSection
| pr_GroupsSection
......@@ -382,12 +382,16 @@ pr_MainControllerItemTcpPort:
pr_IncludeSection returns [ IncludeSection includeSection ]:
{ $includeSection = new IncludeSection();
}
h = INCLUDE_SECTION { includeSectionHandler.setLastSectionRoot( $h ); }
INCLUDE_SECTION
( f = STRING2
{ String fileName = $f.getText().substring( 1, $f.getText().length() - 1 );
$includeSection.addIncludeFileName( fileName );
mIncludeFiles.add( fileName );
includeSectionHandler.getFiles().add( new TerminalNodeImpl( $f ) );
final TerminalNodeImpl node = new TerminalNodeImpl( $f );
node.parent = $ctx;
//another solution for the same thing
//node.parent = includeSectionHandler.getLastSectionRoot();
includeSectionHandler.getFiles().add( node );
}
)*
;
......@@ -408,7 +412,7 @@ pr_ExecuteSectionItem:
;
pr_DefineSection:
h = DEFINE_SECTION { defineSectionHandler.setLastSectionRoot( $h ); }
DEFINE_SECTION
( def = pr_MacroAssignment
{ if ( $def.definition != null ) {
defineSectionHandler.getDefinitions().add( $def.definition );
......
......@@ -10,11 +10,11 @@ package org.eclipse.titan.common.parsers.cfg;
import java.util.ArrayList;
import java.util.List;
import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.CommonToken;
import org.antlr.v4.runtime.ParserRuleContext;
import org.antlr.v4.runtime.Token;
import org.antlr.v4.runtime.TokenStream;
import org.antlr.v4.runtime.TokenStreamRewriter;
import org.antlr.v4.runtime.WritableToken;
import org.antlr.v4.runtime.tree.ParseTree;
import org.antlr.v4.runtime.tree.TerminalNodeImpl;
import org.eclipse.titan.common.parsers.AddedParseTree;
......@@ -137,18 +137,6 @@ public final class ConfigTreeNodeUtilities {
return builder;
}
private static final void appendHiddenBefore( final ParserRuleContext aRule,
final CommonTokenStream aTokens ) {
Token firstToken = aRule.getStart();
List<Token> hiddenTokens = aTokens.getHiddenTokensToLeft( firstToken.getTokenIndex() );
StringBuilder sb = new StringBuilder();
for (Token token : hiddenTokens) {
sb.append( token.getText() );
}
TokenStreamRewriter rewriter = new TokenStreamRewriter( aTokens );
rewriter.insertBefore( firstToken, sb.toString() );
}
private static final StringBuilder appendHiddenAfter(final StringBuilder builder, final LocationAST root) {
LocationAST child = root.getFirstChild();
......@@ -168,17 +156,6 @@ public final class ConfigTreeNodeUtilities {
return builder;
}
private static final StringBuilder appendChildren(final StringBuilder builder, final LocationAST root) {
LocationAST child = root.getFirstChild();
StringBuilder internalBuilder = builder;
while(child != null){
print(internalBuilder,child);
child = child.getNextSibling();
}
return internalBuilder;
}
/**
* RECURSIVE
* Builds parse tree text including hidden tokens (also before the rule)
......@@ -230,6 +207,14 @@ public final class ConfigTreeNodeUtilities {
final StringBuilder aSb,
final List<Integer> aDisallowedNodes ) {
final int startIndex = aToken.getTokenIndex();
if ( startIndex == -1 ) {
// Token has no index.
// If a token is added to the parse tree after parse time, token start index in unknown (-1),
// because token has no index in the token stream.
final String tokenText = aToken.getText();
aSb.append( tokenText != null ? tokenText : "" );
return;
}
int startHiddenIndex = startIndex;
while ( isHiddenToken( startHiddenIndex - 1, aTokenStream ) ) {
startHiddenIndex--;
......@@ -240,12 +225,8 @@ public final class ConfigTreeNodeUtilities {
}
for ( int i = startHiddenIndex; i <= startIndex; i++ ) {
final Token t = aTokenStream.get( i );
if ( t != null ) {
final String tokenText = t.getText();
aSb.append( tokenText != null ? tokenText : "" );
} else {
//TODO: program error
}
final String tokenText = t.getText();
aSb.append( tokenText != null ? tokenText : "" );
}
}
......@@ -293,28 +274,13 @@ public final class ConfigTreeNodeUtilities {
} else {
rule.children.add(aChild);
}
}
else if ( aParent instanceof AddedParseTree ) {
final AddedParseTree node = (AddedParseTree)aParent;
if ( node.children == null ) {
node.children = new ArrayList<ParseTree>();
}
if ( aIndex >= 0 ) {
node.children.set(aIndex, aChild);
} else {
node.children.add(aChild);
}
}
else if ( aParent instanceof TerminalNodeImpl ) {
//TODO: program error
}
else {
//TODO: program error
} else {
//TODO: program error: only ParserRuleContext can have children
}
}
/**
* Removes child form parent's list
* Removes child from parent's list
* @param aParent parent node to remove the child from
* @param aChild child element to remove
*/
......@@ -325,57 +291,66 @@ public final class ConfigTreeNodeUtilities {
}
if ( aParent instanceof ParserRuleContext ) {
final ParserRuleContext rule = (ParserRuleContext)aParent;
if ( rule.children != null ) {
rule.children.remove(aChild);
if ( rule.children != null && aChild != null ) {
//delete child by text
final List<ParseTree> list = rule.children;
final int size = list.size();
final String childText = aChild.getText();
for ( int i = size - 1; i >= 0; i-- ) {
if ( childText.equals( list.get( i ).getText() ) ) {
list.remove( i );
break;
}
}
}
}
else if ( aParent instanceof AddedParseTree ) {
final AddedParseTree node = (AddedParseTree)aParent;
if ( node.children != null ) {
node.children.remove(aChild);
}
}
else if ( aParent instanceof TerminalNodeImpl ) {
//TODO: program error
}
else {
//TODO: program error
} else {
//TODO: program error: only ParserRuleContext can have children
}
}
/**
* Changes the text of a parse tree
* @param aParseTree parsetree to modify
* @param aParseTree parse tree to modify
* @param aText new text
*/
public static void setText( final ParseTree aParseTree, final String aText ) {
String text = "\n" + aText;
if ( aParseTree == null ) {
//TODO: program error
System.out.println("ERROR: ConfigTreeNodeUtilities.setText() aParseTree == null");
//TODO: program error: aParseTree == null
return;
}
if ( aParseTree instanceof ParserRuleContext ) {
final ParserRuleContext rule = (ParserRuleContext)aParseTree;
// in case of a rule we don't want to keep the original sub-tree structure,
// just delete it and replace the children with an AddedParseTree
// just delete it and replace the children with an AddedParseTree
if ( rule.children != null ) {
rule.children.clear();
} else {
rule.children = new ArrayList<ParseTree>();
}
ParseTree newNode = new AddedParseTree( text );
ParseTree newNode = new AddedParseTree( aText );
addChild(rule, newNode);
}
else if ( aParseTree instanceof AddedParseTree ) {
} else if ( aParseTree instanceof AddedParseTree ) {
final AddedParseTree node = (AddedParseTree)aParseTree;
node.setText( text );
}
else if ( aParseTree instanceof TerminalNodeImpl ) {
//TODO: program error
}
else {
//TODO: program error
node.setText( aText );
} else if ( aParseTree instanceof TerminalNodeImpl ) {
final TerminalNodeImpl node = (TerminalNodeImpl)aParseTree;
final Token t = node.symbol;
if ( t instanceof WritableToken ) {
final WritableToken ct = (WritableToken)t;
ct.setText(aText);
} else {
//TODO: program error: unhandled token class type
}
} else {
//TODO: program error: unhandled ParseTree class type
}
}
/**
* Creates a new hidden token node, which can be added to a ParseTree
* @param aText token text
*/
public static TerminalNodeImpl createHiddenTokenNode( final String aText ) {
return new TerminalNodeImpl( new CommonToken( 0, aText ) );
}
}
package org.eclipse.titan.common.parsers.cfg.indices;
import org.antlr.v4.runtime.ParserRuleContext;
/**
* Base class of config section handlers, they are responsible for storing section data,
* which are edited through the corresponding config editor tab,
* and are written back to the cfg file.
* @author Arpad Lovassy
*/
public abstract class ConfigSectionHandlerBase {
/** The root rule of a section */
private ParserRuleContext mLastSectionRoot = null;
public ParserRuleContext getLastSectionRoot() {
return mLastSectionRoot;
}
public void setLastSectionRoot( final ParserRuleContext lastSectionRoot ) {
this.mLastSectionRoot = lastSectionRoot;
}
}
......@@ -10,70 +10,54 @@ package org.eclipse.titan.common.parsers.cfg.indices;
import java.util.ArrayList;
import java.util.List;
import org.antlr.v4.runtime.ParserRuleContext;
import org.antlr.v4.runtime.Token;
import org.eclipse.titan.common.parsers.LocationAST;
import org.antlr.v4.runtime.tree.ParseTree;
import org.antlr.v4.runtime.tree.TerminalNodeImpl;
/**
* Stores temporary config editor data of the define section
* @author Kristof Szabados
* */
public final class DefineSectionHandler {
* @author Arpad Lovassy
*/
public final class DefineSectionHandler extends ConfigSectionHandlerBase {
public static class Definition {
private LocationAST root = null;
private LocationAST definitionName = null;
private LocationAST definitionValue = null;
/** definition rule */
private ParseTree mRoot = null;
private ParseTree mDefinitionName = null;
private ParseTree mDefinitionValue = null;
public LocationAST getRoot() {
return root;
public ParseTree getRoot() {
return mRoot;
}
public void setRoot(final LocationAST root) {
this.root = root;
public void setRoot(final ParseTree aRoot) {
this.mRoot = aRoot;
}
public LocationAST getDefinitionName() {
return definitionName;
public ParseTree getDefinitionName() {
return mDefinitionName;
}
public void setDefinitionName(final LocationAST definitionName) {
this.definitionName = definitionName;
public void setDefinitionName(final ParseTree aDefinitionName) {
this.mDefinitionName = aDefinitionName;
}
public LocationAST getDefinitionValue() {
return definitionValue;
public void setDefinitionName(final Token aDefinitionName) {
this.mDefinitionName = new TerminalNodeImpl( aDefinitionName );
}
public void setDefinitionValue(final LocationAST definitionValue) {
this.definitionValue = definitionValue;
public ParseTree getDefinitionValue() {
return mDefinitionValue;
}
public void setDefinitionName(final Token aToken) {
final ParserRuleContext rule = new ParserRuleContext();
rule.addChild(aToken);
this.definitionName = new LocationAST(rule);
}
public void setDefinitionValue(final ParserRuleContext aRule) {
this.definitionValue = new LocationAST(aRule);
}
public void setRoot(final ParserRuleContext aRule) {
this.root = new LocationAST(aRule);
public void setDefinitionValue(final ParseTree aDefinitionValue) {
this.mDefinitionValue = aDefinitionValue;
}
}
private LocationAST lastSectionRoot = null;
private List<Definition> definitions = new ArrayList<Definition>();
public LocationAST getLastSectionRoot() {
return lastSectionRoot;
}
public void setLastSectionRoot(final LocationAST lastSectionRoot) {
this.lastSectionRoot = lastSectionRoot;
}
public List<Definition> getDefinitions() {
return definitions;
}
......@@ -81,11 +65,4 @@ public final class DefineSectionHandler {
public void setDefinitions(final List<Definition> definitions) {
this.definitions = definitions;
}
public void setLastSectionRoot(final Token aToken) {
final ParserRuleContext rule = new ParserRuleContext();
rule.addChild(aToken);
this.lastSectionRoot = new LocationAST(rule);
}
}
......@@ -11,38 +11,23 @@ import java.util.ArrayList;
import java.util.List;
import org.antlr.v4.runtime.ParserRuleContext;
import org.antlr.v4.runtime.Token;
import org.antlr.v4.runtime.tree.ParseTree;
import org.antlr.v4.runtime.tree.TerminalNodeImpl;
/**
* Stores temporary config editor data of the include section
* @author Kristof Szabados
* @author Arpad Lovassy
*/
public final class IncludeSectionHandler {
public final class IncludeSectionHandler extends ConfigSectionHandlerBase {
private ParseTree mLastSectionRoot = null;
/** list of include files, which are stored as ParseTree nodes */
private List<ParseTree> mFiles = new ArrayList<ParseTree>();
public ParseTree getLastSectionRoot() {
return mLastSectionRoot;
}
public void setLastSectionRoot( final ParseTree lastSectionRoot ) {
this.mLastSectionRoot = lastSectionRoot;
}
public void setLastSectionRoot( final Token aToken ) {
mLastSectionRoot = new TerminalNodeImpl( aToken );
}
public List<ParseTree> getFiles() {
return mFiles;
}
public void addFile(final ParserRuleContext aIncludeFile ) {
public void addFile( final ParserRuleContext aIncludeFile ) {
mFiles.add( aIncludeFile );
}
}
......@@ -7,11 +7,13 @@
******************************************************************************/
package org.eclipse.titan.designer.editors.configeditor.pages.include;
import org.antlr.v4.runtime.tree.ParseTree;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.dnd.DropTargetEvent;
import org.eclipse.swt.dnd.DropTargetListener;
import org.eclipse.titan.common.parsers.LocationAST;
import org.eclipse.titan.common.parsers.cfg.ConfigTreeNodeUtilities;
import org.eclipse.titan.common.parsers.cfg.indices.DefineSectionHandler;
import org.eclipse.titan.common.parsers.cfg.indices.DefineSectionHandler.Definition;
import org.eclipse.titan.designer.editors.configeditor.ConfigEditor;
......@@ -83,14 +85,15 @@ public final class DefineSectionDropTargetListener implements DropTargetListener
int baseindex = defineSectionHandler.getDefinitions().indexOf(element);
LocationAST oldSibling = element.getRoot().getNextSibling();
final ParseTree parent = defineSectionHandler.getLastSectionRoot();
ConfigTreeNodeUtilities.removeChild(parent, element.getRoot());
ConfigTreeNodeUtilities.addChild(parent, element.getRoot(), baseindex);
if (items.length > 0) {
element.getRoot().setNextSibling(items[0].getRoot());
for (int i = 0; i < items.length - 1; i++) {
items[i].getRoot().setNextSibling(items[i + 1].getRoot());
defineSectionHandler.getDefinitions().add(++baseindex, items[i]);
}
items[items.length - 1].getRoot().setNextSibling(oldSibling);
defineSectionHandler.getDefinitions().add(++baseindex, items[items.length - 1]);
}
......
......@@ -10,6 +10,8 @@ package org.eclipse.titan.designer.editors.configeditor.pages.include;
import java.util.Arrays;
import java.util.Iterator;
import org.antlr.v4.runtime.ParserRuleContext;
import org.antlr.v4.runtime.tree.ParseTree;
import org.eclipse.jface.viewers.ICellModifier;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.SelectionChangedEvent;
......@@ -30,8 +32,7 @@ import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.titan.common.parsers.CommonHiddenStreamToken;
import org.eclipse.titan.common.parsers.LocationAST;
import org.eclipse.titan.common.parsers.AddedParseTree;
import org.eclipse.titan.common.parsers.cfg.ConfigTreeNodeUtilities;
import org.eclipse.titan.common.parsers.cfg.indices.DefineSectionHandler;
import org.eclipse.titan.common.parsers.cfg.indices.DefineSectionHandler.Definition;
......@@ -124,18 +125,12 @@ public final class DefineSubPage {
createNewDefineSection();
}
Definition newItem = createNewDefineItem();
final Definition newItem = createNewDefineItem();
if (newItem == null) {
return;
}
if (defineSectionHandler.getDefinitions().isEmpty()) {
defineSectionHandler.getLastSectionRoot().setNextSibling(newItem.getRoot());
} else {
Definition item = defineSectionHandler.getDefinitions().get(defineSectionHandler.getDefinitions().size() - 1);
item.getRoot().setNextSibling(newItem.getRoot());
}
ConfigTreeNodeUtilities.addChild( defineSectionHandler.getLastSectionRoot(), newItem.getRoot() );
defineSectionHandler.getDefinitions().add(newItem);
internalRefresh();
......@@ -226,10 +221,10 @@ public final class DefineSubPage {
switch (columnIndex) {
case 0:
definition.getDefinitionName().setText(((String) value).trim());
ConfigTreeNodeUtilities.setText( definition.getDefinitionName(), ((String) value).trim() );
break;
case 1:
definition.getDefinitionValue().setText(((String) value).trim());
ConfigTreeNodeUtilities.setText( definition.getDefinitionValue(), ((String) value).trim() );
break;
default:
break;
......@@ -277,12 +272,12 @@ public final class DefineSubPage {
return;
}
defineSectionHandler.setLastSectionRoot(new LocationAST("[DEFINE]"));
defineSectionHandler.getLastSectionRoot().setHiddenBefore(new CommonHiddenStreamToken("\n"));
LocationAST sectionRoot = new LocationAST("");
sectionRoot.setFirstChild(defineSectionHandler.getLastSectionRoot());
ParserRuleContext sectionRoot = new ParserRuleContext();
defineSectionHandler.setLastSectionRoot( sectionRoot );
ParseTree header = new AddedParseTree("\n[DEFINE]");
ConfigTreeNodeUtilities.addChild(sectionRoot, header);