Skip to content

Adds nullable sequence and alternative support #2267

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/org/rascalmpl/parser/gtd/SGTDBF.java
Original file line number Diff line number Diff line change
Expand Up @@ -1323,7 +1323,7 @@ else if (!stack.isExpandable()) { // A 'normal' non-terminal.
expanded = true;
}

if(stack.canBeEmpty()){ // Star list or optional.
if(stack.canBeEmpty()){ // Star list, optional or empty sequence / alternative.
AbstractStackNode<P> empty =
stack.getEmptyChild().getCleanCopyWithResult(location, EpsilonStackNode.EPSILON_RESULT);
empty.initEdges();
Expand Down
21 changes: 19 additions & 2 deletions src/org/rascalmpl/parser/gtd/stack/AlternativeStackNode.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ public class AlternativeStackNode<P> extends AbstractExpandableStackNode<P>{
private final String name;

private final AbstractStackNode<P>[] children;
private final AbstractStackNode<P> emptyChild;

public AlternativeStackNode(int id, int dot, P production, AbstractStackNode<P>[] alternatives){
super(id, dot);
Expand All @@ -28,6 +29,7 @@ public AlternativeStackNode(int id, int dot, P production, AbstractStackNode<P>[
this.name = String.valueOf(id);

this.children = generateAlternatives(alternatives);
this.emptyChild = children.length == 0 ? generateEmptyChild() : null;
}

public AlternativeStackNode(int id, int dot, P production, AbstractStackNode<P>[] alternatives, IEnterFilter[] enterFilters, ICompletionFilter[] completionFilters){
Expand All @@ -37,6 +39,7 @@ public AlternativeStackNode(int id, int dot, P production, AbstractStackNode<P>[
this.name = String.valueOf(id);

this.children = generateAlternatives(alternatives);
this.emptyChild = children.length == 0 ? generateEmptyChild() : null;
}

private AlternativeStackNode(AlternativeStackNode<P> original, int startLocation){
Expand All @@ -46,6 +49,7 @@ private AlternativeStackNode(AlternativeStackNode<P> original, int startLocation
name = original.name;

children = original.children;
this.emptyChild = original.emptyChild;
}

/**
Expand All @@ -67,6 +71,16 @@ private AbstractStackNode<P>[] generateAlternatives(AbstractStackNode<P>[] alter

return children;
}

/**
* Generates and initializes the empty child for usage in empty alternatives.
*/
@SuppressWarnings("unchecked")
private AbstractStackNode<P> generateEmptyChild(){
AbstractStackNode<P> empty = (AbstractStackNode<P>) EMPTY.getCleanCopy(DEFAULT_START_LOCATION);
empty.setAlternativeProduction(production);
return empty;
}

public String getName(){
return name;
Expand All @@ -81,11 +95,14 @@ public AbstractStackNode<P>[] getChildren(){
}

public boolean canBeEmpty(){
return false;
return children.length == 0;
}

public AbstractStackNode<P> getEmptyChild(){
throw new UnsupportedOperationException();
if(children.length > 0) {
throw new UnsupportedOperationException();
}
return emptyChild;
}

@Override
Expand Down
25 changes: 23 additions & 2 deletions src/org/rascalmpl/parser/gtd/stack/SequenceStackNode.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ public class SequenceStackNode<P> extends AbstractExpandableStackNode<P>{
private final String name;

private final AbstractStackNode<P>[] children;
private final AbstractStackNode<P> emptyChild;

public SequenceStackNode(int id, int dot, P production, AbstractStackNode<P>[] children){
super(id, dot);
Expand All @@ -28,6 +29,7 @@ public SequenceStackNode(int id, int dot, P production, AbstractStackNode<P>[] c
this.name = String.valueOf(id);

this.children = generateChildren(children);
this.emptyChild = children.length == 0 ? generateEmptyChild() : null;
}

public SequenceStackNode(int id, int dot, P production, AbstractStackNode<P>[] children, IEnterFilter[] enterFilters, ICompletionFilter[] completionFilters){
Expand All @@ -37,6 +39,7 @@ public SequenceStackNode(int id, int dot, P production, AbstractStackNode<P>[] c
this.name = String.valueOf(id);

this.children = generateChildren(children);
this.emptyChild = children.length == 0 ? generateEmptyChild() : null;
}

private SequenceStackNode(SequenceStackNode<P> original, int startLocation){
Expand All @@ -46,13 +49,18 @@ private SequenceStackNode(SequenceStackNode<P> original, int startLocation){
name = original.name;

children = original.children;
this.emptyChild = original.emptyChild;
}

/**
* Generates and initializes the alternatives for this sequence.
*/
@SuppressWarnings("unchecked")
private AbstractStackNode<P>[] generateChildren(AbstractStackNode<P>[] children){
if(children.length == 0){
return new AbstractStackNode[]{};
}

AbstractStackNode<P>[] prod = (AbstractStackNode<P>[]) new AbstractStackNode[children.length];

for(int i = children.length - 1; i >= 0; --i){
Expand All @@ -65,6 +73,16 @@ private AbstractStackNode<P>[] generateChildren(AbstractStackNode<P>[] children)

return (AbstractStackNode<P>[]) new AbstractStackNode[]{prod[0]};
}

/**
* Generates and initializes the empty child for usage in empty sequences.
*/
@SuppressWarnings("unchecked")
private AbstractStackNode<P> generateEmptyChild(){
AbstractStackNode<P> empty = (AbstractStackNode<P>) EMPTY.getCleanCopy(DEFAULT_START_LOCATION);
empty.setAlternativeProduction(production);
return empty;
}

public String getName(){
return name;
Expand All @@ -79,11 +97,14 @@ public AbstractStackNode<P>[] getChildren(){
}

public boolean canBeEmpty(){
return false;
return children.length == 0;
}

public AbstractStackNode<P> getEmptyChild(){
throw new UnsupportedOperationException();
if(children.length > 0) {
throw new UnsupportedOperationException();
}
return emptyChild;
}

@Override
Expand Down
70 changes: 70 additions & 0 deletions test/org/rascalmpl/test/parser/Alternative2.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/*******************************************************************************
* Copyright (c) 2009-2011 CWI
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:

* * Arnold Lankamp - [email protected]
*******************************************************************************/
package org.rascalmpl.test.parser;

import java.io.IOException;
import java.io.StringReader;

import org.rascalmpl.parser.gtd.SGTDBF;
import org.rascalmpl.parser.gtd.result.out.DefaultNodeFlattener;
import org.rascalmpl.parser.gtd.stack.AbstractStackNode;
import org.rascalmpl.parser.gtd.stack.AlternativeStackNode;
import org.rascalmpl.parser.gtd.stack.NonTerminalStackNode;
import org.rascalmpl.parser.uptr.UPTRNodeFactory;
import io.usethesource.vallang.IConstructor;
import io.usethesource.vallang.ISourceLocation;
import io.usethesource.vallang.IValue;
import io.usethesource.vallang.io.StandardTextReader;

import org.rascalmpl.values.RascalValueFactory;
import org.rascalmpl.values.ValueFactoryFactory;
import org.rascalmpl.values.parsetrees.ITree;

@SuppressWarnings({"unchecked", "cast"})
public class Alternative2 extends SGTDBF<IConstructor, ITree, ISourceLocation> implements IParserTest{
private final static IConstructor SYMBOL_START_S = VF.constructor(RascalValueFactory.Symbol_Sort, VF.string("S"));
private final static IConstructor SYMBOL_ALT = VF.constructor(RascalValueFactory.Symbol_Alt, VF.set());

private final static IConstructor PROD_S_ALT = VF.constructor(RascalValueFactory.Production_Default, SYMBOL_START_S, VF.list(SYMBOL_ALT), VF.set());
private final static IConstructor PROD_ALT = VF.constructor(RascalValueFactory.Production_Default, SYMBOL_ALT, VF.list(), VF.set());

private final static AbstractStackNode<IConstructor> NONTERMINAL_START_S = new NonTerminalStackNode<IConstructor>(AbstractStackNode.START_SYMBOL_ID, 0, "S");
private final static AbstractStackNode<IConstructor>[] S_EXPECT_1 = (AbstractStackNode<IConstructor>[]) new AbstractStackNode[1];
static{
S_EXPECT_1[0] = new AlternativeStackNode<IConstructor>(4, 0, PROD_ALT, (AbstractStackNode<IConstructor>[]) new AbstractStackNode[]{});
S_EXPECT_1[0].setProduction(S_EXPECT_1);
S_EXPECT_1[0].setAlternativeProduction(PROD_S_ALT);
}

public Alternative2(){
super();
}

public AbstractStackNode<IConstructor>[] S(){
return new AbstractStackNode[]{S_EXPECT_1[0]};
}

public ITree executeParser(){
return parse(NONTERMINAL_START_S, null, "".toCharArray(), new DefaultNodeFlattener<IConstructor, ITree, ISourceLocation>(), new UPTRNodeFactory(true));
}

public IValue getExpectedResult() throws IOException{
String expectedInput = "appl(prod(sort(\"S\"),[alt({})],{}),[appl(prod(alt({}),[],{}),[])])";
return new StandardTextReader().read(ValueFactoryFactory.getValueFactory(), RascalValueFactory.uptr, RascalValueFactory.Tree, new StringReader(expectedInput));
}

public static void main(String[] args){
Alternative2 a2 = new Alternative2();
IConstructor result = a2.executeParser();
System.out.println(result);
}
}
2 changes: 2 additions & 0 deletions test/org/rascalmpl/test/parser/ParserTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -110,11 +110,13 @@ public void testOptional(){
public void testSequence(){
executeParser(new Sequence1());
executeParser(new Sequence2());
executeParser(new Sequence4());
}

@Test
public void testAlternative(){
executeParser(new Alternative1());
executeParser(new Alternative2());
}

@Test
Expand Down
65 changes: 65 additions & 0 deletions test/org/rascalmpl/test/parser/Sequence4.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package org.rascalmpl.test.parser;

import java.io.IOException;
import java.io.StringReader;

import org.rascalmpl.parser.gtd.SGTDBF;
import org.rascalmpl.parser.gtd.result.out.DefaultNodeFlattener;
import org.rascalmpl.parser.gtd.stack.AbstractStackNode;
import org.rascalmpl.parser.gtd.stack.NonTerminalStackNode;
import org.rascalmpl.parser.gtd.stack.SequenceStackNode;
import org.rascalmpl.parser.uptr.UPTRNodeFactory;
import io.usethesource.vallang.IConstructor;
import io.usethesource.vallang.ISourceLocation;
import io.usethesource.vallang.IValue;
import io.usethesource.vallang.io.StandardTextReader;

import org.rascalmpl.values.RascalValueFactory;
import org.rascalmpl.values.ValueFactoryFactory;
import org.rascalmpl.values.parsetrees.ITree;
/*
S ::= (A () B)
A ::= a
B ::= b
*/
@SuppressWarnings({"unchecked", "cast"})
public class Sequence4 extends SGTDBF<IConstructor, ITree, ISourceLocation> implements IParserTest{
private final static IConstructor SYMBOL_START_S = VF.constructor(RascalValueFactory.Symbol_Sort, VF.string("S"));
private final static IConstructor SYMBOL_SEQ = VF.constructor(RascalValueFactory.Symbol_Seq, VF.list());

private final static IConstructor PROD_S_SEQ_AB = VF.constructor(RascalValueFactory.Production_Default, SYMBOL_START_S, VF.list(SYMBOL_SEQ), VF.set());
private final static IConstructor PROD_SEQUENCE = VF.constructor(RascalValueFactory.Production_Default, SYMBOL_SEQ, VF.list(), VF.set());

private final static AbstractStackNode<IConstructor> NONTERMINAL_START_S = new NonTerminalStackNode<IConstructor>(AbstractStackNode.START_SYMBOL_ID, 0, "S");
private final static AbstractStackNode<IConstructor> SEQUENCE4 = new SequenceStackNode<IConstructor>(3, 0, PROD_SEQUENCE, new AbstractStackNode[]{});

private final static AbstractStackNode<IConstructor>[] S_EXPECT_1 = (AbstractStackNode<IConstructor>[]) new AbstractStackNode[1];
static{
S_EXPECT_1[0] = SEQUENCE4;
S_EXPECT_1[0].setProduction(S_EXPECT_1);
S_EXPECT_1[0].setAlternativeProduction(PROD_S_SEQ_AB);
}

public Sequence4(){
super();
}

public AbstractStackNode<IConstructor>[] S(){
return (AbstractStackNode<IConstructor>[]) new AbstractStackNode[]{S_EXPECT_1[0]};
}

public ITree executeParser(){
return parse(NONTERMINAL_START_S, null, "".toCharArray(), new DefaultNodeFlattener<IConstructor, ITree, ISourceLocation>(), new UPTRNodeFactory(true));
}

public IValue getExpectedResult() throws IOException{
String expectedInput = "appl(prod(sort(\"S\"),[seq([])],{}),[appl(prod(seq([]),[],{}),[])])";
return new StandardTextReader().read(ValueFactoryFactory.getValueFactory(), RascalValueFactory.uptr, RascalValueFactory.Tree, new StringReader(expectedInput));
}

public static void main(String[] args){
Sequence4 s4 = new Sequence4();
IConstructor result = s4.executeParser();
System.out.println(result);
}
}
Loading