ANTLR C грамматика не распознает точечную нотацию - PullRequest
0 голосов
/ 17 сентября 2018

Мы используем ANTLR для анализа C, и большая часть нашего кода имеет точечную нотацию для структур.Прошло некоторое время с тех пор, как я написал C, но из того, что я помню, эти два утверждения являются синонимами:

void hello() {
    this->hello = "hello";
    this.hello = "hello";
}

ANTLR может анализировать greeting->hello без каких-либо проблем, однако точка-нотация выбрасываетследующая ошибка:

line 3:4 mismatched input 'this.hello' expecting '}'

Если мы переключим операторы следующим образом:

void hello() {
    this.hello = "hello";
    this->hello = "hello";
}

Ошибки:

line 2:4 mismatched input 'this.hello' expecting {'__extension__', '__builtin_va_arg', '__builtin_offsetof', '__m128', '__m128d', '__m128i', '__typeof__', '__inline__', '__stdcall', '__declspec', '__asm', '__attribute__', '__asm__', 'auto', 'break', 'case', 'char', 'const', 'continue', 'default', 'do', 'double', 'enum', 'extern', 'float', 'for', 'goto', 'if', 'inline', 'int', 'long', 'register', 'restrict', 'return', 'short', 'signed', 'sizeof', 'static', 'struct', 'switch', 'typedef', 'union', 'unsigned', 'void', 'volatile', 'while', '_Alignas', '_Alignof', '_Atomic', '_Bool', '_Complex', '_Generic', '_Noreturn', '_Static_assert', '_Thread_local', '(', '{', '}', '+', '++', '-', '--', '*', '&', '&&', '!', '~', ';', Identifier, Constant, DigitSequence, StringLiteral}
line 3:8 no viable alternative at input 'this->'
line 4:0 extraneous input '}' expecting <EOF>

Мы используем C грамматика из ANTLR Grammars хранилища .При этом мы настроили его для обработки #include операторов, и это можно увидеть здесь .Мы добавили эти два парсера и эти два лексера:

includeExpression
    : IncludeDirective includedLibExpression '"'
    | IncludeDirective includedLibExpression '>'
    ;

includedLibExpression
    : IncludedHeaderDirective
    ;

IncludeDirective
    : '#' Whitespace? 'include' Whitespace '"'
    | '#' Whitespace? 'include' Whitespace '<'
    ;

IncludedHeaderDirective
    : ('a'..'z' | 'A'..'Z' | '.' | '_' | '/')+
    ;

Затем, чтобы использовать новые парсеры, мы добавили ниже к translationUnit.Чтобы еще больше запутать, если строка с includeExpression в translationUnit закомментирована, мы все равно получим ошибки.

translationUnit
    :   externalDeclaration
    |   translationUnit externalDeclaration
    |   includeExpression+?
    ;

Конкретный синтаксический анализатор, который должен это поднять, это:

postfixExpression
    :   primaryExpression
    |   postfixExpression '[' expression ']'
    |   postfixExpression '(' argumentExpressionList? ')'
    |   postfixExpression '.' Identifier
    |   postfixExpression '->' Identifier
    |   postfixExpression '++'
    |   postfixExpression '--'
    |   '(' typeName ')' '{' initializerList '}'
    |   '(' typeName ')' '{' initializerList ',' '}'
    |   '__extension__' '(' typeName ')' '{' initializerList '}'
    |   '__extension__' '(' typeName ')' '{' initializerList ',' '}'
;

Что меня действительно удивляет, так это тот факт, что обозначения точек и обозначения стрелок располагаются одна за другой, но распознается только обозначение стрелок.

1 Ответ

0 голосов
/ 17 сентября 2018

Вы добавили следующее правило лексера в грамматику:

IncludedHeaderDirective
    : ('a'..'z' | 'A'..'Z' | '.' | '_' | '/')+
    ;

Этот шаблон соответствует строке this.hello. Поэтому, когда лексер достигает строки 2 вашего ввода, он может применить правило Identifier для соответствия this или правило IncludeHeaderDirective для соответствия this.hello. Так как последний является более длинным соответствием, он выбирается согласно правилу максимального жаворонка.

Поскольку IncludedHeaderDirective не является допустимым выражением, вы получаете ошибку, которую делаете. Чтобы соответствовать правилу postfixExpression '.' Identifier, this.hello должен был бы быть размечен как Identifier, '.', Identifier, но существование правила IncludedHeaderDirective предотвращает это.

...