BNF: Problem with optional field in method signature
Greetings,
I am having a problem writing a BNF for a custom language. The problem is that my grammar indicates method signatures can have an optional type. But if I leave out the type in my actual file, I get an error. Here is a snippet of my BNF:
processDeclaration
::= typeModifier? 'process' type? Identifier formalParameters processBody
This succeeds:
public process int MyProcess () {
}
But if I remove the "int", I get an error at the "()":
public process MyProcess () {
}
It expects the Identifier there. I assume it is consuming "MyProcess" as the type.
Unfortunately, I cannot post much of the code. But if anyone has had a similar problem, I'd be interested to hear about it.
Thanks.
EDIT1: By the way, my grammar succeeds (as expected) if I leave out the "public" typeModifier. I am not sure why that optional field works and the "type" optional field does not.
EDIT2: The generated code shows (correctly) that the Type (MyLangType) is nullable.
public interface MyLangProcessDeclaration extends PsiElement {
@NotNull
MyLangIdentifier getIdentifier();
@NotNull
MyLangFormalParameters getFormalParameters();
@NotNull
MyLangProcessBody getProcessBody();
@Nullable
MyLangType getType();
@Nullable
MyLangTypeModifier getTypeModifier();
}
请先登录再写评论。
This is not enough information to help you. Please post your `type` rule. Also, pinning `process` looks proper to me.
Hi Alexandr, I have posted some more of my grammar below. I tried pin=2, but didn't see much difference. For the following code:
public process MyProcess () {
}
I see an error at the "(" and it says: "PsiErrorElement:MyLangTokenType.[ orMyLangTokenType.id expected, got '('". It succeeds when I put some type (ex: int) after "process".
More of my grammar:
processDeclaration ::= typeModifier? 'process' type? Identifier formalParameters processBody {pin=2}
typeModifier ::= 'public' | 'private'
type
::= entityType listIndicator?
| collectionType
| primitiveType listIndicator?
entityType
::= Identifier
listIndicator
::= ('[' ']')
collectionType
::= collectionTypeList
| collectionTypeMap
collectionTypeList
::= 'list' '<' type '>'
collectionTypeMap
::= 'map' '<' forType ',' toType '>'
forType
::= type
toType
::= type
primitiveType
::= 'boolean'
| 'string'
| 'int'
| 'float'
| 'timestamp'
Identifier ::= id
// "id" is defined at top of file with tokens
id='regexp:\p{Alpha}\w*'
space='regexp:\s+'
Thanks!
As you can see your type rule matches identifier through entity type.
PsiViewer plugin may be really useful here.
Hi Alexandr, thanks for the feedback and happy new year :)
Does the grammar try to find a rule that matches if one rule fails? My input fails for entity type, but does the grammar fallback and try to match another rule?