Bug 427276 - The code of method init(IGrammarAccess) is exceeding the 65535 bytes limit
Summary: The code of method init(IGrammarAccess) is exceeding the 65535 bytes limit
Status: NEW
Alias: None
Product: TMF
Classification: Modeling
Component: Xtext (show other bugs)
Version: 2.5.0   Edit
Hardware: PC Windows 7
: P3 normal (vote)
Target Milestone: ---   Edit
Assignee: Project Inbox CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2014-02-03 10:14 EST by Oliver Libutzki CLA
Modified: 2014-02-05 07:13 EST (History)
1 user (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Oliver Libutzki CLA 2014-02-03 10:14:33 EST
After running the mwe2 workflow (containing org.eclipse.xtext.generator.serializer.SerializerFragment) I get this error:
"The code of method init(IGrammarAccess) is exceeding the 65535 bytes limit" in Abstract{languagename}SyntacticSequencer

Please provide a possibility to split the init method (or do it generally).

Btw. the problem occurred after introducing a couple of unordered groups in the grammar file.
Comment 1 Oliver Libutzki CLA 2014-02-03 10:56:58 EST
I quickfixed this by using a custom SerializerFragment and a custom AbstractSyntacticSequencer, but it's ugly as there is no way to bind custom classes in the mwe2 workflow.

The AbstractSyntacticSequencer looks like this:

val initPartitions = Lists.partition(util.allAmbiguousTransitionsBySyntax, 10)
@SuppressWarnings("all")
public «_abstract»class «filename.simpleName» extends AbstractSyntacticSequencer {

	[...]
	
	@Inject
	protected void init(IGrammarAccess access) {
		«FOR i: 0 ..<initPartitions.size»
			init«i»(access);
		«ENDFOR»
	}
	
	«FOR i: 0 ..<initPartitions.size»
		private void init«i»(IGrammarAccess access) {
			grammarAccess = («file.imported(grammar.gaFQName)») access;
			«FOR group : initPartitions.get(i)»
				match_«group.first» = « group.second.elementAliasToConstructor(file)»;
			«ENDFOR»
		}
	«ENDFOR»
	
	[...]
}
Comment 2 Moritz Eysholdt CLA 2014-02-05 06:09:36 EST
Hi Oliver, 

thank you for the report. I can reproduce the issue and I think instead of "partitioning" the generated code the SerializerFragment should generate less code by merging compatible constraints into a single one.

For example, the following grammar

---------------------
Greeting:
	'Hello' name=ID '{'	(
		"foo" ("{" foo=ID "}")? &
		"bar" ("{" bar=ID "}")? 
	) "}" ;
----------------------

leads to to the creation of four constraints:

----------------------
('bar' | 'foo')*
('bar' | 'foo')+
('bar'* 'foo')+
('foo'* 'bar')+
----------------------

The number of constraints increases with the number of members of the unordered group:
3 members -> 5 constraints
4 member -> 6 constraints
5 member -> 7 constraints
etc.

In you scenario, Oliver, theres constraint became to big and to many.

A fix to be discussed:
The generated constraints can be grouped by merging one constraint into another one if the first constraint matches a syntactical subset of the letter constraints. Example: All constraints of the example above match syntactical subsets of ('bar' | 'foo')*. 


Workarounds:

1. Don't use the SerializerFragment. Using the serializer dos not require you to use the SerializerFragment because the serializer actually is an interpreter and the generated code is not seraialization logic but just API.

2. In your grammar, avoid syntactic ambiguities inside unordered groups: Example: This ("foo" ("{" foo=ID "}")?) is bad, because if feature foo is unset, the serializer doesn't know whether is should write our keyword foo or not. Better: ("foo" "{" foo=ID "}").
Comment 3 Oliver Libutzki CLA 2014-02-05 07:13:02 EST
Hi Moritz,

thank you for your detailed answer.

As we do not use the Serializer API, I just removed the SerializerFragment.