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();

}

 

1
4 comments

This is not enough information to help you. Please post your `type` rule. Also, pinning `process` looks proper to me.

1
Avatar
Permanently deleted user

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!

 

 

 

0

As you can see your type rule matches identifier through entity type. 

PsiViewer plugin may be really useful here. 

0
Avatar
Permanently deleted user

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? 

 

 

0

Please sign in to leave a comment.