-
Notifications
You must be signed in to change notification settings - Fork 77
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
"Except" does not work correctly with shared prefixes in nonterminals, leading to ambiguity #1915
Comments
@arnoldlankamp this looks to be a prefix-sharing issue:
Perhaps you could have a look; but if you don't have the time no worries. Groetjes! |
Interesting 🤔, I don't immediately see a way in which prefix-sharing and completion filters would be able to interact in this specific case, since the completion filter is not on any of the prefix-shared nodes, but on an indirectly related non-terminal, which is processed independently. The cleanest way to check if this issue is indeed related to prefix-sharing is to disable this feature. Which can be done by changing this flag from
By adding a dummy symbol you're also effectively disabling prefix-sharing for a certain alternative, but also a introduce a potentially significant change to the order in which symbols are evaluated by the parser, which may lead to false positive test results. I'm not trying to imply this is what's going on right now, but it is something to consider. If changing the above flag turns out to resolve the issue, you could even consider using it as a temporary patch and live with the associated performance hit until a proper fix arrives. In any case, I'll have a look at the root cause of this issue when I have some time. |
I just wrote a test case and found out I misunderstood the problem and was testing the wrong thing 🤦♂️ . This has something to do with labeled alternatives not being rejected. So the origin of this problem is somewhere in the ExpectBuilder, which handles the prefix merging. I guess it's not correctly considering nesting restrictions in all cases. At least I know where to look now 😅 . |
By the way if anyone could supply me with the generated parser for the given grammar (the Java file) that would save me some time, since I don't have Rascal installed on my laptop. |
The ExpectBuilder relies on the nesting restrictions implicitly, by assuming the ParserGenerator assigns stack nodes identifiers that take sharing permissibility into account (e.g.: that they are unique for alternatives with the same priority and partially overlapping prefixes). This should be working as intended, for as far as I can see 🤔 . To say more I'll need to have a look at the generated parser code. |
I'll post it here in a few minutes. Installing Rascal is easy from the VScode extensions view. Just search for Rascal and pick install. |
package example;
import java.io.IOException;
import java.io.StringReader;
import io.usethesource.vallang.type.TypeFactory;
import io.usethesource.vallang.IConstructor;
import io.usethesource.vallang.ISourceLocation;
import io.usethesource.vallang.IValue;
import io.usethesource.vallang.IValueFactory;
import io.usethesource.vallang.exceptions.FactTypeUseException;
import io.usethesource.vallang.io.StandardTextReader;
import org.rascalmpl.parser.gtd.stack.*;
import org.rascalmpl.parser.gtd.stack.filter.*;
import org.rascalmpl.parser.gtd.stack.filter.follow.*;
import org.rascalmpl.parser.gtd.stack.filter.match.*;
import org.rascalmpl.parser.gtd.stack.filter.precede.*;
import org.rascalmpl.parser.gtd.preprocessing.ExpectBuilder;
import org.rascalmpl.parser.gtd.util.IntegerKeyedHashMap;
import org.rascalmpl.parser.gtd.util.IntegerList;
import org.rascalmpl.parser.gtd.util.IntegerMap;
import org.rascalmpl.values.ValueFactoryFactory;
import org.rascalmpl.values.RascalValueFactory;
import org.rascalmpl.values.parsetrees.ITree;
@SuppressWarnings("all")
public class S extends org.rascalmpl.parser.gtd.SGTDBF<IConstructor, ITree, ISourceLocation> {
protected final static IValueFactory VF = ValueFactoryFactory.getValueFactory();
protected static IValue _read(java.lang.String s, io.usethesource.vallang.type.Type type) {
try {
return new StandardTextReader().read(VF, org.rascalmpl.values.RascalValueFactory.uptr, type, new StringReader(s));
}
catch (FactTypeUseException e) {
throw new RuntimeException("unexpected exception in generated parser", e);
} catch (IOException e) {
throw new RuntimeException("unexpected exception in generated parser", e);
}
}
protected static java.lang.String _concat(java.lang.String ...args) {
int length = 0;
for (java.lang.String s :args) {
length += s.length();
}
java.lang.StringBuilder b = new java.lang.StringBuilder(length);
for (java.lang.String s : args) {
b.append(s);
}
return b.toString();
}
protected static final TypeFactory _tf = TypeFactory.getInstance();
private static final IntegerMap _resultStoreIdMappings;
private static final IntegerKeyedHashMap<IntegerList> _dontNest;
protected static void _putDontNest(IntegerKeyedHashMap<IntegerList> result, int parentId, int childId) {
IntegerList donts = result.get(childId);
if (donts == null) {
donts = new IntegerList();
result.put(childId, donts);
}
donts.add(parentId);
}
protected int getResultStoreId(int parentId) {
return _resultStoreIdMappings.get(parentId);
}
protected static IntegerKeyedHashMap<IntegerList> _initDontNest() {
IntegerKeyedHashMap<IntegerList> result = new IntegerKeyedHashMap<IntegerList>();
_putDontNest(result, 100, 27);
return result;
}
protected static IntegerMap _initDontNestGroups() {
IntegerMap result = new IntegerMap();
int resultStoreId = result.size();
++resultStoreId;
result.putUnsafe(100, resultStoreId);
return result;
}
protected boolean hasNestingRestrictions(java.lang.String name){
return (_dontNest.size() != 0); // TODO Make more specific.
}
protected IntegerList getFilteredParents(int childId) {
return _dontNest.get(childId);
}
// initialize priorities
static {
_dontNest = _initDontNest();
_resultStoreIdMappings = _initDontNestGroups();
}
// Production declarations
private static final IConstructor cHJvZChsaXQoInNvcnQoXCJDXCIpIiksW1xjaGFyLWNsYXNzKFtyYW5nZSgxMTUsMTE1KV0pLFxjaGFyLWNsYXNzKFtyYW5nZSgxMTEsMTExKV0pLFxjaGFyLWNsYXNzKFtyYW5nZSgxMTQsMTE0KV0pLFxjaGFyLWNsYXNzKFtyYW5nZSgxMTYsMTE2KV0pLFxjaGFyLWNsYXNzKFtyYW5nZSg0MCw0MCldKSxcY2hhci1jbGFzcyhbcmFuZ2UoMzQsMzQpXSksXGNoYXItY2xhc3MoW3JhbmdlKDY3LDY3KV0pLFxjaGFyLWNsYXNzKFtyYW5nZSgzNCwzNCldKSxcY2hhci1jbGFzcyhbcmFuZ2UoNDEsNDEpXSldLHt9KQ0000 = (IConstructor) _read("prod(lit(\"sort(\\\"C\\\")\"),[\\char-class([range(115,115)]),\\char-class([range(111,111)]),\\char-class([range(114,114)]),\\char-class([range(116,116)]),\\char-class([range(40,40)]),\\char-class([range(34,34)]),\\char-class([range(67,67)]),\\char-class([range(34,34)]),\\char-class([range(41,41)])],{})", RascalValueFactory.Production);
private static final IConstructor cmVndWxhcihpdGVyKFxjaGFyLWNsYXNzKFtyYW5nZSg0OCw1NyldKSkp = (IConstructor) _read("regular(iter(\\char-class([range(48,57)])))", RascalValueFactory.Production);
private static final IConstructor cHJvZChsaXQoIjoiKSxbXGNoYXItY2xhc3MoW3JhbmdlKDU4LDU4KV0pXSx7fSk00 = (IConstructor) _read("prod(lit(\":\"),[\\char-class([range(58,58)])],{})", RascalValueFactory.Production);
private static final IConstructor cHJvZChlbXB0eSgpLFtdLHt9KQ0000 = (IConstructor) _read("prod(empty(),[],{})", RascalValueFactory.Production);
private static final IConstructor cHJvZChsYWJlbCgiYyIsbGV4KCJBIikpLFtsZXgoIkMiKV0se30p = (IConstructor) _read("prod(label(\"c\",lex(\"A\")),[lex(\"C\")],{})", RascalValueFactory.Production);
private static final IConstructor cHJvZChsaXQoImMiKSxbXGNoYXItY2xhc3MoW3JhbmdlKDk5LDk5KV0pXSx7fSk00 = (IConstructor) _read("prod(lit(\"c\"),[\\char-class([range(99,99)])],{})", RascalValueFactory.Production);
private static final IConstructor cHJvZChsYWJlbCgiYiIsbGV4KCJBIikpLFtsZXgoIkMiKSxsZXgoIkIiKV0se30p = (IConstructor) _read("prod(label(\"b\",lex(\"A\")),[lex(\"C\"),lex(\"B\")],{})", RascalValueFactory.Production);
private static final IConstructor cHJvZChsYWJlbCgiJE1ldGFIb2xlIixsZXgoIkMiKSksW1xjaGFyLWNsYXNzKFtyYW5nZSgwLDApXSksbGl0KCJzb3J0KFwiQ1wiKSIpLGxpdCgiOiIpLGl0ZXIoXGNoYXItY2xhc3MoW3JhbmdlKDQ4LDU3KV0pKSxcY2hhci1jbGFzcyhbcmFuZ2UoMCwwKV0pXSx7dGFnKCJob2xlVHlwZSIobGV4KCJDIikpKX0p = (IConstructor) _read("prod(label(\"$MetaHole\",lex(\"C\")),[\\char-class([range(0,0)]),lit(\"sort(\\\"C\\\")\"),lit(\":\"),iter(\\char-class([range(48,57)])),\\char-class([range(0,0)])],{tag(\"holeType\"(lex(\"C\")))})", RascalValueFactory.Production);
private static final IConstructor cHJvZChsYWJlbCgiJE1ldGFIb2xlIixsZXgoIkEiKSksW1xjaGFyLWNsYXNzKFtyYW5nZSgwLDApXSksbGl0KCJzb3J0KFwiQVwiKSIpLGxpdCgiOiIpLGl0ZXIoXGNoYXItY2xhc3MoW3JhbmdlKDQ4LDU3KV0pKSxcY2hhci1jbGFzcyhbcmFuZ2UoMCwwKV0pXSx7dGFnKCJob2xlVHlwZSIobGV4KCJBIikpKX0p = (IConstructor) _read("prod(label(\"$MetaHole\",lex(\"A\")),[\\char-class([range(0,0)]),lit(\"sort(\\\"A\\\")\"),lit(\":\"),iter(\\char-class([range(48,57)])),\\char-class([range(0,0)])],{tag(\"holeType\"(lex(\"A\")))})", RascalValueFactory.Production);
private static final IConstructor cHJvZChsYXlvdXRzKCIkZGVmYXVsdCQiKSxbXSx7fSk00 = (IConstructor) _read("prod(layouts(\"$default$\"),[],{})", RascalValueFactory.Production);
private static final IConstructor cHJvZChsYWJlbCgiJE1ldGFIb2xlIixsZXgoIlMiKSksW1xjaGFyLWNsYXNzKFtyYW5nZSgwLDApXSksbGl0KCJzb3J0KFwiU1wiKSIpLGxpdCgiOiIpLGl0ZXIoXGNoYXItY2xhc3MoW3JhbmdlKDQ4LDU3KV0pKSxcY2hhci1jbGFzcyhbcmFuZ2UoMCwwKV0pXSx7dGFnKCJob2xlVHlwZSIobGV4KCJTIikpKX0p = (IConstructor) _read("prod(label(\"$MetaHole\",lex(\"S\")),[\\char-class([range(0,0)]),lit(\"sort(\\\"S\\\")\"),lit(\":\"),iter(\\char-class([range(48,57)])),\\char-class([range(0,0)])],{tag(\"holeType\"(lex(\"S\")))})", RascalValueFactory.Production);
private static final IConstructor cHJvZChsaXQoInNvcnQoXCJCXCIpIiksW1xjaGFyLWNsYXNzKFtyYW5nZSgxMTUsMTE1KV0pLFxjaGFyLWNsYXNzKFtyYW5nZSgxMTEsMTExKV0pLFxjaGFyLWNsYXNzKFtyYW5nZSgxMTQsMTE0KV0pLFxjaGFyLWNsYXNzKFtyYW5nZSgxMTYsMTE2KV0pLFxjaGFyLWNsYXNzKFtyYW5nZSg0MCw0MCldKSxcY2hhci1jbGFzcyhbcmFuZ2UoMzQsMzQpXSksXGNoYXItY2xhc3MoW3JhbmdlKDY2LDY2KV0pLFxjaGFyLWNsYXNzKFtyYW5nZSgzNCwzNCldKSxcY2hhci1jbGFzcyhbcmFuZ2UoNDEsNDEpXSldLHt9KQ0000 = (IConstructor) _read("prod(lit(\"sort(\\\"B\\\")\"),[\\char-class([range(115,115)]),\\char-class([range(111,111)]),\\char-class([range(114,114)]),\\char-class([range(116,116)]),\\char-class([range(40,40)]),\\char-class([range(34,34)]),\\char-class([range(66,66)]),\\char-class([range(34,34)]),\\char-class([range(41,41)])],{})", RascalValueFactory.Production);
private static final IConstructor cHJvZChsaXQoImIiKSxbXGNoYXItY2xhc3MoW3JhbmdlKDk4LDk4KV0pXSx7fSk00 = (IConstructor) _read("prod(lit(\"b\"),[\\char-class([range(98,98)])],{})", RascalValueFactory.Production);
private static final IConstructor cHJvZChsZXgoIlMiKSxbY29uZGl0aW9uYWwobGV4KCJBIikse2V4Y2VwdCgiYyIpfSldLHt9KQ0000 = (IConstructor) _read("prod(lex(\"S\"),[conditional(lex(\"A\"),{except(\"c\")})],{})", RascalValueFactory.Production);
private static final IConstructor cHJvZChsaXQoInNvcnQoXCJBXCIpIiksW1xjaGFyLWNsYXNzKFtyYW5nZSgxMTUsMTE1KV0pLFxjaGFyLWNsYXNzKFtyYW5nZSgxMTEsMTExKV0pLFxjaGFyLWNsYXNzKFtyYW5nZSgxMTQsMTE0KV0pLFxjaGFyLWNsYXNzKFtyYW5nZSgxMTYsMTE2KV0pLFxjaGFyLWNsYXNzKFtyYW5nZSg0MCw0MCldKSxcY2hhci1jbGFzcyhbcmFuZ2UoMzQsMzQpXSksXGNoYXItY2xhc3MoW3JhbmdlKDY1LDY1KV0pLFxjaGFyLWNsYXNzKFtyYW5nZSgzNCwzNCldKSxcY2hhci1jbGFzcyhbcmFuZ2UoNDEsNDEpXSldLHt9KQ0000 = (IConstructor) _read("prod(lit(\"sort(\\\"A\\\")\"),[\\char-class([range(115,115)]),\\char-class([range(111,111)]),\\char-class([range(114,114)]),\\char-class([range(116,116)]),\\char-class([range(40,40)]),\\char-class([range(34,34)]),\\char-class([range(65,65)]),\\char-class([range(34,34)]),\\char-class([range(41,41)])],{})", RascalValueFactory.Production);
private static final IConstructor cHJvZChsaXQoInNvcnQoXCJTXCIpIiksW1xjaGFyLWNsYXNzKFtyYW5nZSgxMTUsMTE1KV0pLFxjaGFyLWNsYXNzKFtyYW5nZSgxMTEsMTExKV0pLFxjaGFyLWNsYXNzKFtyYW5nZSgxMTQsMTE0KV0pLFxjaGFyLWNsYXNzKFtyYW5nZSgxMTYsMTE2KV0pLFxjaGFyLWNsYXNzKFtyYW5nZSg0MCw0MCldKSxcY2hhci1jbGFzcyhbcmFuZ2UoMzQsMzQpXSksXGNoYXItY2xhc3MoW3JhbmdlKDgzLDgzKV0pLFxjaGFyLWNsYXNzKFtyYW5nZSgzNCwzNCldKSxcY2hhci1jbGFzcyhbcmFuZ2UoNDEsNDEpXSldLHt9KQ0000 = (IConstructor) _read("prod(lit(\"sort(\\\"S\\\")\"),[\\char-class([range(115,115)]),\\char-class([range(111,111)]),\\char-class([range(114,114)]),\\char-class([range(116,116)]),\\char-class([range(40,40)]),\\char-class([range(34,34)]),\\char-class([range(83,83)]),\\char-class([range(34,34)]),\\char-class([range(41,41)])],{})", RascalValueFactory.Production);
private static final IConstructor cHJvZChsZXgoIkIiKSxbbGl0KCJiIildLHt9KQ0000 = (IConstructor) _read("prod(lex(\"B\"),[lit(\"b\")],{})", RascalValueFactory.Production);
private static final IConstructor cHJvZChsYWJlbCgiJE1ldGFIb2xlIixsZXgoIkIiKSksW1xjaGFyLWNsYXNzKFtyYW5nZSgwLDApXSksbGl0KCJzb3J0KFwiQlwiKSIpLGxpdCgiOiIpLGl0ZXIoXGNoYXItY2xhc3MoW3JhbmdlKDQ4LDU3KV0pKSxcY2hhci1jbGFzcyhbcmFuZ2UoMCwwKV0pXSx7dGFnKCJob2xlVHlwZSIobGV4KCJCIikpKX0p = (IConstructor) _read("prod(label(\"$MetaHole\",lex(\"B\")),[\\char-class([range(0,0)]),lit(\"sort(\\\"B\\\")\"),lit(\":\"),iter(\\char-class([range(48,57)])),\\char-class([range(0,0)])],{tag(\"holeType\"(lex(\"B\")))})", RascalValueFactory.Production);
private static final IConstructor cHJvZChsZXgoIkMiKSxbbGl0KCJjIildLHt9KQ0000 = (IConstructor) _read("prod(lex(\"C\"),[lit(\"c\")],{})", RascalValueFactory.Production);
private static final IConstructor cHJvZChsZXgoIlMiKSxbbGV4KCJDIildLHt9KQ0000 = (IConstructor) _read("prod(lex(\"S\"),[lex(\"C\")],{})", RascalValueFactory.Production);
// Item declarations
protected static class layouts_$default$ {
public final static AbstractStackNode<IConstructor>[] EXPECTS;
static{
ExpectBuilder<IConstructor> builder = new ExpectBuilder<IConstructor>(_resultStoreIdMappings);
init(builder);
EXPECTS = builder.buildExpectArray();
}
protected static final void _init_cHJvZChsYXlvdXRzKCIkZGVmYXVsdCQiKSxbXSx7fSk00(ExpectBuilder<IConstructor> builder) {
AbstractStackNode<IConstructor>[] tmp = (AbstractStackNode<IConstructor>[]) new AbstractStackNode[1];
tmp[0] = new EpsilonStackNode<IConstructor>(3, 0);
builder.addAlternative(S.cHJvZChsYXlvdXRzKCIkZGVmYXVsdCQiKSxbXSx7fSk00, tmp);
}
public static void init(ExpectBuilder<IConstructor> builder){
_init_cHJvZChsYXlvdXRzKCIkZGVmYXVsdCQiKSxbXSx7fSk00(builder);
}
}
protected static class A {
public final static AbstractStackNode<IConstructor>[] EXPECTS;
static{
ExpectBuilder<IConstructor> builder = new ExpectBuilder<IConstructor>(_resultStoreIdMappings);
init(builder);
EXPECTS = builder.buildExpectArray();
}
protected static final void _init_cHJvZChsYWJlbCgiYiIsbGV4KCJBIikpLFtsZXgoIkMiKSxsZXgoIkIiKV0se30p(ExpectBuilder<IConstructor> builder) {
AbstractStackNode<IConstructor>[] tmp = (AbstractStackNode<IConstructor>[]) new AbstractStackNode[2];
tmp[1] = new NonTerminalStackNode<IConstructor>(15, 1, "B", null, null);
tmp[0] = new NonTerminalStackNode<IConstructor>(14, 0, "C", null, null);
builder.addAlternative(S.cHJvZChsYWJlbCgiYiIsbGV4KCJBIikpLFtsZXgoIkMiKSxsZXgoIkIiKV0se30p, tmp);
}
protected static final void _init_cHJvZChsYWJlbCgiJE1ldGFIb2xlIixsZXgoIkEiKSksW1xjaGFyLWNsYXNzKFtyYW5nZSgwLDApXSksbGl0KCJzb3J0KFwiQVwiKSIpLGxpdCgiOiIpLGl0ZXIoXGNoYXItY2xhc3MoW3JhbmdlKDQ4LDU3KV0pKSxcY2hhci1jbGFzcyhbcmFuZ2UoMCwwKV0pXSx7dGFnKCJob2xlVHlwZSIobGV4KCJBIikpKX0p(ExpectBuilder<IConstructor> builder) {
AbstractStackNode<IConstructor>[] tmp = (AbstractStackNode<IConstructor>[]) new AbstractStackNode[5];
tmp[3] = new ListStackNode<IConstructor>(22, 3, cmVndWxhcihpdGVyKFxjaGFyLWNsYXNzKFtyYW5nZSg0OCw1NyldKSkp, new CharStackNode<IConstructor>(21, 0, new int[][]{{48,57}}, null, null), true, null, null);
tmp[1] = new LiteralStackNode<IConstructor>(19, 1, cHJvZChsaXQoInNvcnQoXCJBXCIpIiksW1xjaGFyLWNsYXNzKFtyYW5nZSgxMTUsMTE1KV0pLFxjaGFyLWNsYXNzKFtyYW5nZSgxMTEsMTExKV0pLFxjaGFyLWNsYXNzKFtyYW5nZSgxMTQsMTE0KV0pLFxjaGFyLWNsYXNzKFtyYW5nZSgxMTYsMTE2KV0pLFxjaGFyLWNsYXNzKFtyYW5nZSg0MCw0MCldKSxcY2hhci1jbGFzcyhbcmFuZ2UoMzQsMzQpXSksXGNoYXItY2xhc3MoW3JhbmdlKDY1LDY1KV0pLFxjaGFyLWNsYXNzKFtyYW5nZSgzNCwzNCldKSxcY2hhci1jbGFzcyhbcmFuZ2UoNDEsNDEpXSldLHt9KQ0000, new int[] {115,111,114,116,40,34,65,34,41}, null, null);
tmp[0] = new CharStackNode<IConstructor>(18, 0, new int[][]{{0,0}}, null, null);
tmp[4] = new CharStackNode<IConstructor>(23, 4, new int[][]{{0,0}}, null, null);
tmp[2] = new LiteralStackNode<IConstructor>(20, 2, cHJvZChsaXQoIjoiKSxbXGNoYXItY2xhc3MoW3JhbmdlKDU4LDU4KV0pXSx7fSk00, new int[] {58}, null, null);
builder.addAlternative(S.cHJvZChsYWJlbCgiJE1ldGFIb2xlIixsZXgoIkEiKSksW1xjaGFyLWNsYXNzKFtyYW5nZSgwLDApXSksbGl0KCJzb3J0KFwiQVwiKSIpLGxpdCgiOiIpLGl0ZXIoXGNoYXItY2xhc3MoW3JhbmdlKDQ4LDU3KV0pKSxcY2hhci1jbGFzcyhbcmFuZ2UoMCwwKV0pXSx7dGFnKCJob2xlVHlwZSIobGV4KCJBIikpKX0p, tmp);
}
protected static final void _init_cHJvZChsYWJlbCgiYyIsbGV4KCJBIikpLFtsZXgoIkMiKV0se30p(ExpectBuilder<IConstructor> builder) {
AbstractStackNode<IConstructor>[] tmp = (AbstractStackNode<IConstructor>[]) new AbstractStackNode[1];
tmp[0] = new NonTerminalStackNode<IConstructor>(27, 0, "C", null, null);
builder.addAlternative(S.cHJvZChsYWJlbCgiYyIsbGV4KCJBIikpLFtsZXgoIkMiKV0se30p, tmp);
}
public static void init(ExpectBuilder<IConstructor> builder){
_init_cHJvZChsYWJlbCgiYiIsbGV4KCJBIikpLFtsZXgoIkMiKSxsZXgoIkIiKV0se30p(builder);
_init_cHJvZChsYWJlbCgiJE1ldGFIb2xlIixsZXgoIkEiKSksW1xjaGFyLWNsYXNzKFtyYW5nZSgwLDApXSksbGl0KCJzb3J0KFwiQVwiKSIpLGxpdCgiOiIpLGl0ZXIoXGNoYXItY2xhc3MoW3JhbmdlKDQ4LDU3KV0pKSxcY2hhci1jbGFzcyhbcmFuZ2UoMCwwKV0pXSx7dGFnKCJob2xlVHlwZSIobGV4KCJBIikpKX0p(builder);
_init_cHJvZChsYWJlbCgiYyIsbGV4KCJBIikpLFtsZXgoIkMiKV0se30p(builder);
}
}
protected static class C {
public final static AbstractStackNode<IConstructor>[] EXPECTS;
static{
ExpectBuilder<IConstructor> builder = new ExpectBuilder<IConstructor>(_resultStoreIdMappings);
init(builder);
EXPECTS = builder.buildExpectArray();
}
protected static final void _init_cHJvZChsYWJlbCgiJE1ldGFIb2xlIixsZXgoIkMiKSksW1xjaGFyLWNsYXNzKFtyYW5nZSgwLDApXSksbGl0KCJzb3J0KFwiQ1wiKSIpLGxpdCgiOiIpLGl0ZXIoXGNoYXItY2xhc3MoW3JhbmdlKDQ4LDU3KV0pKSxcY2hhci1jbGFzcyhbcmFuZ2UoMCwwKV0pXSx7dGFnKCJob2xlVHlwZSIobGV4KCJDIikpKX0p(ExpectBuilder<IConstructor> builder) {
AbstractStackNode<IConstructor>[] tmp = (AbstractStackNode<IConstructor>[]) new AbstractStackNode[5];
tmp[3] = new ListStackNode<IConstructor>(35, 3, cmVndWxhcihpdGVyKFxjaGFyLWNsYXNzKFtyYW5nZSg0OCw1NyldKSkp, new CharStackNode<IConstructor>(34, 0, new int[][]{{48,57}}, null, null), true, null, null);
tmp[1] = new LiteralStackNode<IConstructor>(32, 1, cHJvZChsaXQoInNvcnQoXCJDXCIpIiksW1xjaGFyLWNsYXNzKFtyYW5nZSgxMTUsMTE1KV0pLFxjaGFyLWNsYXNzKFtyYW5nZSgxMTEsMTExKV0pLFxjaGFyLWNsYXNzKFtyYW5nZSgxMTQsMTE0KV0pLFxjaGFyLWNsYXNzKFtyYW5nZSgxMTYsMTE2KV0pLFxjaGFyLWNsYXNzKFtyYW5nZSg0MCw0MCldKSxcY2hhci1jbGFzcyhbcmFuZ2UoMzQsMzQpXSksXGNoYXItY2xhc3MoW3JhbmdlKDY3LDY3KV0pLFxjaGFyLWNsYXNzKFtyYW5nZSgzNCwzNCldKSxcY2hhci1jbGFzcyhbcmFuZ2UoNDEsNDEpXSldLHt9KQ0000, new int[] {115,111,114,116,40,34,67,34,41}, null, null);
tmp[0] = new CharStackNode<IConstructor>(31, 0, new int[][]{{0,0}}, null, null);
tmp[4] = new CharStackNode<IConstructor>(36, 4, new int[][]{{0,0}}, null, null);
tmp[2] = new LiteralStackNode<IConstructor>(33, 2, cHJvZChsaXQoIjoiKSxbXGNoYXItY2xhc3MoW3JhbmdlKDU4LDU4KV0pXSx7fSk00, new int[] {58}, null, null);
builder.addAlternative(S.cHJvZChsYWJlbCgiJE1ldGFIb2xlIixsZXgoIkMiKSksW1xjaGFyLWNsYXNzKFtyYW5nZSgwLDApXSksbGl0KCJzb3J0KFwiQ1wiKSIpLGxpdCgiOiIpLGl0ZXIoXGNoYXItY2xhc3MoW3JhbmdlKDQ4LDU3KV0pKSxcY2hhci1jbGFzcyhbcmFuZ2UoMCwwKV0pXSx7dGFnKCJob2xlVHlwZSIobGV4KCJDIikpKX0p, tmp);
}
protected static final void _init_cHJvZChsZXgoIkMiKSxbbGl0KCJjIildLHt9KQ0000(ExpectBuilder<IConstructor> builder) {
AbstractStackNode<IConstructor>[] tmp = (AbstractStackNode<IConstructor>[]) new AbstractStackNode[1];
tmp[0] = new LiteralStackNode<IConstructor>(39, 0, cHJvZChsaXQoImMiKSxbXGNoYXItY2xhc3MoW3JhbmdlKDk5LDk5KV0pXSx7fSk00, new int[] {99}, null, null);
builder.addAlternative(S.cHJvZChsZXgoIkMiKSxbbGl0KCJjIildLHt9KQ0000, tmp);
}
public static void init(ExpectBuilder<IConstructor> builder){
_init_cHJvZChsYWJlbCgiJE1ldGFIb2xlIixsZXgoIkMiKSksW1xjaGFyLWNsYXNzKFtyYW5nZSgwLDApXSksbGl0KCJzb3J0KFwiQ1wiKSIpLGxpdCgiOiIpLGl0ZXIoXGNoYXItY2xhc3MoW3JhbmdlKDQ4LDU3KV0pKSxcY2hhci1jbGFzcyhbcmFuZ2UoMCwwKV0pXSx7dGFnKCJob2xlVHlwZSIobGV4KCJDIikpKX0p(builder);
_init_cHJvZChsZXgoIkMiKSxbbGl0KCJjIildLHt9KQ0000(builder);
}
}
protected static class B {
public final static AbstractStackNode<IConstructor>[] EXPECTS;
static{
ExpectBuilder<IConstructor> builder = new ExpectBuilder<IConstructor>(_resultStoreIdMappings);
init(builder);
EXPECTS = builder.buildExpectArray();
}
protected static final void _init_cHJvZChsZXgoIkIiKSxbbGl0KCJiIildLHt9KQ0000(ExpectBuilder<IConstructor> builder) {
AbstractStackNode<IConstructor>[] tmp = (AbstractStackNode<IConstructor>[]) new AbstractStackNode[1];
tmp[0] = new LiteralStackNode<IConstructor>(42, 0, cHJvZChsaXQoImIiKSxbXGNoYXItY2xhc3MoW3JhbmdlKDk4LDk4KV0pXSx7fSk00, new int[] {98}, null, null);
builder.addAlternative(S.cHJvZChsZXgoIkIiKSxbbGl0KCJiIildLHt9KQ0000, tmp);
}
protected static final void _init_cHJvZChsYWJlbCgiJE1ldGFIb2xlIixsZXgoIkIiKSksW1xjaGFyLWNsYXNzKFtyYW5nZSgwLDApXSksbGl0KCJzb3J0KFwiQlwiKSIpLGxpdCgiOiIpLGl0ZXIoXGNoYXItY2xhc3MoW3JhbmdlKDQ4LDU3KV0pKSxcY2hhci1jbGFzcyhbcmFuZ2UoMCwwKV0pXSx7dGFnKCJob2xlVHlwZSIobGV4KCJCIikpKX0p(ExpectBuilder<IConstructor> builder) {
AbstractStackNode<IConstructor>[] tmp = (AbstractStackNode<IConstructor>[]) new AbstractStackNode[5];
tmp[4] = new CharStackNode<IConstructor>(50, 4, new int[][]{{0,0}}, null, null);
tmp[2] = new LiteralStackNode<IConstructor>(47, 2, cHJvZChsaXQoIjoiKSxbXGNoYXItY2xhc3MoW3JhbmdlKDU4LDU4KV0pXSx7fSk00, new int[] {58}, null, null);
tmp[3] = new ListStackNode<IConstructor>(49, 3, cmVndWxhcihpdGVyKFxjaGFyLWNsYXNzKFtyYW5nZSg0OCw1NyldKSkp, new CharStackNode<IConstructor>(48, 0, new int[][]{{48,57}}, null, null), true, null, null);
tmp[1] = new LiteralStackNode<IConstructor>(46, 1, cHJvZChsaXQoInNvcnQoXCJCXCIpIiksW1xjaGFyLWNsYXNzKFtyYW5nZSgxMTUsMTE1KV0pLFxjaGFyLWNsYXNzKFtyYW5nZSgxMTEsMTExKV0pLFxjaGFyLWNsYXNzKFtyYW5nZSgxMTQsMTE0KV0pLFxjaGFyLWNsYXNzKFtyYW5nZSgxMTYsMTE2KV0pLFxjaGFyLWNsYXNzKFtyYW5nZSg0MCw0MCldKSxcY2hhci1jbGFzcyhbcmFuZ2UoMzQsMzQpXSksXGNoYXItY2xhc3MoW3JhbmdlKDY2LDY2KV0pLFxjaGFyLWNsYXNzKFtyYW5nZSgzNCwzNCldKSxcY2hhci1jbGFzcyhbcmFuZ2UoNDEsNDEpXSldLHt9KQ0000, new int[] {115,111,114,116,40,34,66,34,41}, null, null);
tmp[0] = new CharStackNode<IConstructor>(45, 0, new int[][]{{0,0}}, null, null);
builder.addAlternative(S.cHJvZChsYWJlbCgiJE1ldGFIb2xlIixsZXgoIkIiKSksW1xjaGFyLWNsYXNzKFtyYW5nZSgwLDApXSksbGl0KCJzb3J0KFwiQlwiKSIpLGxpdCgiOiIpLGl0ZXIoXGNoYXItY2xhc3MoW3JhbmdlKDQ4LDU3KV0pKSxcY2hhci1jbGFzcyhbcmFuZ2UoMCwwKV0pXSx7dGFnKCJob2xlVHlwZSIobGV4KCJCIikpKX0p, tmp);
}
public static void init(ExpectBuilder<IConstructor> builder){
_init_cHJvZChsZXgoIkIiKSxbbGl0KCJiIildLHt9KQ0000(builder);
_init_cHJvZChsYWJlbCgiJE1ldGFIb2xlIixsZXgoIkIiKSksW1xjaGFyLWNsYXNzKFtyYW5nZSgwLDApXSksbGl0KCJzb3J0KFwiQlwiKSIpLGxpdCgiOiIpLGl0ZXIoXGNoYXItY2xhc3MoW3JhbmdlKDQ4LDU3KV0pKSxcY2hhci1jbGFzcyhbcmFuZ2UoMCwwKV0pXSx7dGFnKCJob2xlVHlwZSIobGV4KCJCIikpKX0p(builder);
}
}
protected static class S {
public final static AbstractStackNode<IConstructor>[] EXPECTS;
static{
ExpectBuilder<IConstructor> builder = new ExpectBuilder<IConstructor>(_resultStoreIdMappings);
init(builder);
EXPECTS = builder.buildExpectArray();
}
protected static final void _init_cHJvZChsYWJlbCgiJE1ldGFIb2xlIixsZXgoIlMiKSksW1xjaGFyLWNsYXNzKFtyYW5nZSgwLDApXSksbGl0KCJzb3J0KFwiU1wiKSIpLGxpdCgiOiIpLGl0ZXIoXGNoYXItY2xhc3MoW3JhbmdlKDQ4LDU3KV0pKSxcY2hhci1jbGFzcyhbcmFuZ2UoMCwwKV0pXSx7dGFnKCJob2xlVHlwZSIobGV4KCJTIikpKX0p(ExpectBuilder<IConstructor> builder) {
AbstractStackNode<IConstructor>[] tmp = (AbstractStackNode<IConstructor>[]) new AbstractStackNode[5];
tmp[2] = new LiteralStackNode<IConstructor>(93, 2, cHJvZChsaXQoIjoiKSxbXGNoYXItY2xhc3MoW3JhbmdlKDU4LDU4KV0pXSx7fSk00, new int[] {58}, null, null);
tmp[4] = new CharStackNode<IConstructor>(96, 4, new int[][]{{0,0}}, null, null);
tmp[0] = new CharStackNode<IConstructor>(91, 0, new int[][]{{0,0}}, null, null);
tmp[1] = new LiteralStackNode<IConstructor>(92, 1, cHJvZChsaXQoInNvcnQoXCJTXCIpIiksW1xjaGFyLWNsYXNzKFtyYW5nZSgxMTUsMTE1KV0pLFxjaGFyLWNsYXNzKFtyYW5nZSgxMTEsMTExKV0pLFxjaGFyLWNsYXNzKFtyYW5nZSgxMTQsMTE0KV0pLFxjaGFyLWNsYXNzKFtyYW5nZSgxMTYsMTE2KV0pLFxjaGFyLWNsYXNzKFtyYW5nZSg0MCw0MCldKSxcY2hhci1jbGFzcyhbcmFuZ2UoMzQsMzQpXSksXGNoYXItY2xhc3MoW3JhbmdlKDgzLDgzKV0pLFxjaGFyLWNsYXNzKFtyYW5nZSgzNCwzNCldKSxcY2hhci1jbGFzcyhbcmFuZ2UoNDEsNDEpXSldLHt9KQ0000, new int[] {115,111,114,116,40,34,83,34,41}, null, null);
tmp[3] = new ListStackNode<IConstructor>(95, 3, cmVndWxhcihpdGVyKFxjaGFyLWNsYXNzKFtyYW5nZSg0OCw1NyldKSkp, new CharStackNode<IConstructor>(94, 0, new int[][]{{48,57}}, null, null), true, null, null);
builder.addAlternative(S.cHJvZChsYWJlbCgiJE1ldGFIb2xlIixsZXgoIlMiKSksW1xjaGFyLWNsYXNzKFtyYW5nZSgwLDApXSksbGl0KCJzb3J0KFwiU1wiKSIpLGxpdCgiOiIpLGl0ZXIoXGNoYXItY2xhc3MoW3JhbmdlKDQ4LDU3KV0pKSxcY2hhci1jbGFzcyhbcmFuZ2UoMCwwKV0pXSx7dGFnKCJob2xlVHlwZSIobGV4KCJTIikpKX0p, tmp);
}
protected static final void _init_cHJvZChsZXgoIlMiKSxbY29uZGl0aW9uYWwobGV4KCJBIikse2V4Y2VwdCgiYyIpfSldLHt9KQ0000(ExpectBuilder<IConstructor> builder) {
AbstractStackNode<IConstructor>[] tmp = (AbstractStackNode<IConstructor>[]) new AbstractStackNode[1];
tmp[0] = new NonTerminalStackNode<IConstructor>(100, 0, "A", null, null);
builder.addAlternative(S.cHJvZChsZXgoIlMiKSxbY29uZGl0aW9uYWwobGV4KCJBIikse2V4Y2VwdCgiYyIpfSldLHt9KQ0000, tmp);
}
protected static final void _init_cHJvZChsZXgoIlMiKSxbbGV4KCJDIildLHt9KQ0000(ExpectBuilder<IConstructor> builder) {
AbstractStackNode<IConstructor>[] tmp = (AbstractStackNode<IConstructor>[]) new AbstractStackNode[1];
tmp[0] = new NonTerminalStackNode<IConstructor>(102, 0, "C", null, null);
builder.addAlternative(S.cHJvZChsZXgoIlMiKSxbbGV4KCJDIildLHt9KQ0000, tmp);
}
public static void init(ExpectBuilder<IConstructor> builder){
_init_cHJvZChsYWJlbCgiJE1ldGFIb2xlIixsZXgoIlMiKSksW1xjaGFyLWNsYXNzKFtyYW5nZSgwLDApXSksbGl0KCJzb3J0KFwiU1wiKSIpLGxpdCgiOiIpLGl0ZXIoXGNoYXItY2xhc3MoW3JhbmdlKDQ4LDU3KV0pKSxcY2hhci1jbGFzcyhbcmFuZ2UoMCwwKV0pXSx7dGFnKCJob2xlVHlwZSIobGV4KCJTIikpKX0p(builder);
_init_cHJvZChsZXgoIlMiKSxbY29uZGl0aW9uYWwobGV4KCJBIikse2V4Y2VwdCgiYyIpfSldLHt9KQ0000(builder);
_init_cHJvZChsZXgoIlMiKSxbbGV4KCJDIildLHt9KQ0000(builder);
}
}
// Parse methods
public AbstractStackNode<IConstructor>[] layouts_$default$() {
return layouts_$default$.EXPECTS;
}
public AbstractStackNode<IConstructor>[] A() {
return A.EXPECTS;
}
public AbstractStackNode<IConstructor>[] C() {
return C.EXPECTS;
}
public AbstractStackNode<IConstructor>[] B() {
return B.EXPECTS;
}
public AbstractStackNode<IConstructor>[] S() {
return S.EXPECTS;
}
} This was generated using: import lang::rascal::grammar::ParserGenerator;
import Grammar;
import IO;
writeFile(|home:///S.java|, newGenerate("example", "S", grammar(#S))); |
Note to self and Arnold: this disambiguation filter is handled by the NoNesting relation and not by the enter and completion filters. Next to the forbidden nestings generated by the associativity and priority relations (which transitively closed), these We have
The final symbol of each rule is always used to identify the rule: rel[int,int] computeDontNests(Items items, Grammar grammar, Grammar uniqueGrammar) {
// first we compute a map from productions to their last items (which identify each production)
prodItems = (p:items[getType(rhs)][item(p,size(lhs)-1)].itemId | /Production p:prod(Symbol rhs,list[Symbol] lhs, _) := grammar); It's unclear to me what happens with an epsilon rule that must be rejected. |
Thanks for the generated parser's code 👍 . As far as I can see everything seems to be correctly generated. The ExpectBuilder definitely seems to most likely source of this bug. Probably because it's merging stack nodes without taking properly taking the nesting restrictions into account. If so there are two possible ways of fixing this:
So I guess I'll go with the first option. I'll let you know as soon as I've had some time to implement a solution. |
Yes, let's go for the first. Of course, we still are working under hypotheses, but if that fixes it the hypotheses are confirmed :-) I'm happy we have good regression tests. Let's add this case to the manually written cases? Thanks for looking into this Arnold; you can do it 100x faster than I could. |
I already started writing a new test case on a branch a few days ago, since I need it to debug the issue anyway. However it may be a few days until I get around to spending more time on this issue. I'll let you know when it's done. |
Excellent! |
I just finished writing a new test case on a branch, which reproduces the issue. I've also pinned down the problem to somewhere around here: rascal/src/org/rascalmpl/parser/gtd/preprocessing/ExpectBuilder.java Lines 112 to 113 in 5270320
It looks to be taking nesting restrictions into account while merging alternatives, but it's apparently missing one or more cases. I'll try to find some time to have a better look at it next week. I know what the problem is and know what needs to be done to rectify it, but I don't want to rush out a fix today and potentially break something else in the process. Until then, disabling prefix-sharing by setting:
false , is still available as temporary workaround.
|
@jurgenvinju By the way, I noticed these alternatives in the generated parser code you posted:
It looks like each sort has an extra alternative that looks like: |
Describe the bug
When nonterminals share prefixes, "except" does not work correctly.
To Reproduce
Expected behavior
There should be no ambiguity here. Adding
()
at the start of either constructor ofA
makes the problem go away, e.g.:Desktop (please complete the following information):
The text was updated successfully, but these errors were encountered: