Skip to content

Commit 22b55b1

Browse files
committed
Adds support of nullable sequences.
1 parent 960baee commit 22b55b1

File tree

3 files changed

+91
-3
lines changed

3 files changed

+91
-3
lines changed

src/org/rascalmpl/parser/gtd/SGTDBF.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1301,7 +1301,7 @@ else if (!stack.isExpandable()) { // A 'normal' non-terminal.
13011301
expanded = true;
13021302
}
13031303

1304-
if(stack.canBeEmpty()){ // Star list or optional.
1304+
if(stack.canBeEmpty()){ // Star list, optional or empty sequence.
13051305
AbstractStackNode<P> empty =
13061306
stack.getEmptyChild().getCleanCopyWithResult(location, EpsilonStackNode.EPSILON_RESULT);
13071307
empty.initEdges();

src/org/rascalmpl/parser/gtd/stack/SequenceStackNode.java

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ public class SequenceStackNode<P> extends AbstractExpandableStackNode<P>{
2020
private final String name;
2121

2222
private final AbstractStackNode<P>[] children;
23+
private final AbstractStackNode<P> emptyChild;
2324

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

3031
this.children = generateChildren(children);
32+
this.emptyChild = children.length == 0 ? generateEmptyChild() : null;
3133
}
3234

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

3941
this.children = generateChildren(children);
42+
this.emptyChild = children.length == 0 ? generateEmptyChild() : null;
4043
}
4144

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

4851
children = original.children;
52+
this.emptyChild = original.emptyChild;
4953
}
5054

5155
/**
5256
* Generates and initializes the alternatives for this sequence.
5357
*/
5458
@SuppressWarnings("unchecked")
5559
private AbstractStackNode<P>[] generateChildren(AbstractStackNode<P>[] children){
60+
if(children.length == 0){
61+
return new AbstractStackNode[]{};
62+
}
63+
5664
AbstractStackNode<P>[] prod = (AbstractStackNode<P>[]) new AbstractStackNode[children.length];
5765

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

6674
return (AbstractStackNode<P>[]) new AbstractStackNode[]{prod[0]};
6775
}
76+
77+
/**
78+
* Generates and initializes the empty child for usage in empty sequences.
79+
*/
80+
@SuppressWarnings("unchecked")
81+
private AbstractStackNode<P> generateEmptyChild(){
82+
AbstractStackNode<P> empty = (AbstractStackNode<P>) EMPTY.getCleanCopy(DEFAULT_START_LOCATION);
83+
empty.setAlternativeProduction(production);
84+
return empty;
85+
}
6886

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

8199
public boolean canBeEmpty(){
82-
return false;
100+
return children.length == 0;
83101
}
84102

85103
public AbstractStackNode<P> getEmptyChild(){
86-
throw new UnsupportedOperationException();
104+
if(children.length > 0) {
105+
throw new UnsupportedOperationException();
106+
}
107+
return emptyChild;
87108
}
88109

89110
@Override
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
package org.rascalmpl.test.parser;
2+
3+
import java.io.IOException;
4+
import java.io.StringReader;
5+
6+
import org.rascalmpl.parser.gtd.SGTDBF;
7+
import org.rascalmpl.parser.gtd.result.out.DefaultNodeFlattener;
8+
import org.rascalmpl.parser.gtd.stack.AbstractStackNode;
9+
import org.rascalmpl.parser.gtd.stack.LiteralStackNode;
10+
import org.rascalmpl.parser.gtd.stack.NonTerminalStackNode;
11+
import org.rascalmpl.parser.gtd.stack.SequenceStackNode;
12+
import org.rascalmpl.parser.uptr.UPTRNodeFactory;
13+
import io.usethesource.vallang.IConstructor;
14+
import io.usethesource.vallang.ISourceLocation;
15+
import io.usethesource.vallang.IValue;
16+
import io.usethesource.vallang.io.StandardTextReader;
17+
18+
import org.rascalmpl.values.RascalFunctionValueFactory;
19+
import org.rascalmpl.values.RascalValueFactory;
20+
import org.rascalmpl.values.ValueFactoryFactory;
21+
import org.rascalmpl.values.parsetrees.ITree;
22+
/*
23+
S ::= (A () B)
24+
A ::= a
25+
B ::= b
26+
*/
27+
@SuppressWarnings({"unchecked", "cast"})
28+
public class Sequence4 extends SGTDBF<IConstructor, ITree, ISourceLocation> implements IParserTest{
29+
private final static IConstructor SYMBOL_START_S = VF.constructor(RascalValueFactory.Symbol_Sort, VF.string("S"));
30+
private final static IConstructor SYMBOL_SEQ = VF.constructor(RascalValueFactory.Symbol_Seq, VF.list());
31+
32+
private final static IConstructor PROD_S_SEQ_AB = VF.constructor(RascalValueFactory.Production_Default, SYMBOL_START_S, VF.list(SYMBOL_SEQ), VF.set());
33+
private final static IConstructor PROD_SEQUENCE = VF.constructor(RascalValueFactory.Production_Default, SYMBOL_SEQ, VF.list(), VF.set());
34+
35+
private final static AbstractStackNode<IConstructor> NONTERMINAL_START_S = new NonTerminalStackNode<IConstructor>(AbstractStackNode.START_SYMBOL_ID, 0, "S");
36+
private final static AbstractStackNode<IConstructor> SEQUENCE4 = new SequenceStackNode<IConstructor>(3, 0, PROD_SEQUENCE, new AbstractStackNode[]{});
37+
38+
private final static AbstractStackNode<IConstructor>[] S_EXPECT_1 = (AbstractStackNode<IConstructor>[]) new AbstractStackNode[1];
39+
static{
40+
S_EXPECT_1[0] = SEQUENCE4;
41+
S_EXPECT_1[0].setProduction(S_EXPECT_1);
42+
S_EXPECT_1[0].setAlternativeProduction(PROD_S_SEQ_AB);
43+
}
44+
45+
public Sequence4(){
46+
super();
47+
}
48+
49+
public AbstractStackNode<IConstructor>[] S(){
50+
return (AbstractStackNode<IConstructor>[]) new AbstractStackNode[]{S_EXPECT_1[0]};
51+
}
52+
53+
public ITree executeParser(){
54+
return parse(NONTERMINAL_START_S, null, "".toCharArray(), new DefaultNodeFlattener<IConstructor, ITree, ISourceLocation>(), new UPTRNodeFactory(true));
55+
}
56+
57+
public IValue getExpectedResult() throws IOException{
58+
String expectedInput = "appl(prod(sort(\"S\"),[seq([])],{}),[appl(prod(seq([]),[],{}),[])])";
59+
return new StandardTextReader().read(ValueFactoryFactory.getValueFactory(), RascalValueFactory.uptr, RascalValueFactory.Tree, new StringReader(expectedInput));
60+
}
61+
62+
public static void main(String[] args){
63+
Sequence4 s4 = new Sequence4();
64+
IConstructor result = s4.executeParser();
65+
System.out.println(result);
66+
}
67+
}

0 commit comments

Comments
 (0)