Make Script-level Annotation friendlier to EBNF grammar. #14562
Replies: 2 comments 4 replies
|
I understand what you mean, but I think this discussion is mostly theoretical, not a real issue. The GDScript implementation doesn't use a formal grammar, even the outdated documentation page states that EBNF is provided as a reference and may be incorrect. Compliance with the grammar doesn't guarantee that the source file is valid. It may still contain semantic errors. Annotation resolution is primarily performed by the static analyzer, although some annotations have special processing in the parser. You're right that it's difficult to describe a grammar that would even allow for correct AST construction (identifying which node an annotation belongs to). However, the problems begin even earlier: the tokenizer is interactive (its modes are controlled by the parser), while the current outdated grammar omits whitespace tokens altogether. The problem with determining whether an annotation applies to the script/root class or to the first member of the root class is caused by the fact that in GDScript, files are classes, and both I would advise you not to put script-level annotations into a separate category in EBNF. Just use the general "annotation" category, even though different annotations apply at different levels. |
|
I'm closing this discussion because even though I like one of the solutions I proposed. With the removal of the grammar page, I don't feel like any of the proposed solutions are necessary anymore. |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
I wanted to see if I could tackle updating the GDScript Grammar page; however, there are some very strange behaviors with the parser at the beginning of the file that will make translating to EBNF much more complicated than anticipated.
In trying to understand the way GDScript is parsed I discovered the following code makes a valid and full file without any error:
Note: There is a warning because there is no static variable to unload, but EBNF only cares about syntax, so its fine.
All 4 lines can be moved around to your hearts content and compressed to a single line separated by spaces with no issue.
Before we continue I have a definition.
Script-level annotation: an annotation that must come before the class definition and have at most 1 instance of itself in a file.
Complexity
Before I get to the real problem, the current design of script-level annotation is not built to be extensible in EBNF.
Limiting the number of occurrences while allowing freedom of order actually makes the context-free grammar (EBNF is a context-free grammar) more complex, even though it seems trivial to a Turing machine.
Below, I will show you two languages that have alphabet {a, b} and show that the smaller language L(a) is actually is more complicated to fully represent all instances
L(a) = {"", "a", "b", "ab", "ba"}
L(b) = {"", "a", "b", "ab", "ba", "aa", "bb", "aab", ...}
You might think a is not that much more complex than b, but that's because the number of characters in the alphabet is 2.
I mapped the number of options a will have to have written with the formula:
f(n) = sum(C(n, k) * (k!)) for 0<=k<=n
n represents the number of script-level annotations that can be arranged in any order.
you are choosing k items from n annotations and you're permuting the items you chose for every choice k to represent all possible ordering of script-level annotation. The following are how much individual options one must represent for different number of annotations:
f(0) = 1
f(1) = 2
F(2) = 5
f(3) = 16
f(4) = 65
f(5) = 326
The nice thing is the option sequence (denoted by
[ ]) can optimize your result, but optimizing 65 options is a big task and is not extensible when you add more script-level annotations. Meanwhile b's increases linearly, making it highly extensible.Current issue in complexity
Everything above assumes script-level annotations are equal. However the following file has an error:
because whereas before, the
@abstractis read as the script being an abstract class, now the annotation is trying to make the variable abstract.This makes the formalization even more complicated because you will have to split the possibilities
So, Solutions?
I already showed one way, which is to allow more than one of each individual annotation, but I feel that would cause a lot of headaches for the little payoff of making the EBNF easier to write.
Another way is to add more restrictions by enforcing order of the annotation (eg. have
@tool->@icon->static_unload), This will allow the EBNF to grow linearly when creating new script-level annotation. The problem is this would break compatibility.The next one is my favorite solution. Separate
@abstractfrom the rest of the script-level annotations, and put it in the class definition logic. Although technically breaks compatibility, I noticed nowhere in the documentation does it imply the following is a valid file:@abstractIt creates an empty, nameless, abstract
RefCounted. This is a completely useless file, but being a valid file actually makes the EBNF more complex than it should be due to it being intermixed with the other script-level annotations. You can't even add anything to it without class definition becauseis invalid, even though
is valid.
Overall,
@abstractis too inconsistent with it's behavior to be treated as a standard script-level annotation, so I suggest putting it into the class definition instead.Each solution only addresses one of my issues. The first two addresses the extensibility problem when adding more script-level annotations, while the last specifically targets the issue I get from
@abstract. The last tangentially helps with formalizing by reducing script-level annotations from 4 to 3. I feel like separating@abstractis the most actionable one and is good enough unless there are plans for more script-level annotations.The only other suggestion I have is when drafting the new EBNF, add a comment that explains how it actually works, while having a simplified version of the grammar relating to script-level annotations. I don't really like this solution, but is a good compromise.
All reactions