Проблемы с синтаксическим анализом decaf (объявление переменной в сравнении с конструктором)
Я использую bison (3.0.4) и лексер для реализации (частичной) грамматики языка программирования Decaf. Я только реализую то, что находится внутри класса.
Итак, моя задача проста: сохранить каждое производственное правило (в виде строки) в дереве, а затем просто распечатать его.
Например, если у вас есть следующая строка кода в качестве ввода
class Foo { Foo(int arg1) { some2 a; } }
Вы (должны) получить следующий вывод
<ClassDecl> --> class identifier <classBody>
<ClassBody> --> { <VariableDecl>* <ConstructorDecl>* <MethodDecl>* }
<ConstructorDecl> --> identifier ( <ParameterList> ) <Block>
<ParameterList> --> <Parameter> <, Parameter>*
<Parameter> --> <Type> identifier
<Type> --> <SimpleType>
<SimpleType> --> int
<Block> --> { <LocalVariableDecl>* <Statement>* }
<LocalVariableDecl> --> <Type> identifier ;
<Type> --> <SimpleType>
<SimpleType> --> identifier
Первая проблема (решенная) заключалась в том, что она анализировала объявление переменной вместо объявления конструктора, хотя у меня нет объявления переменной в области видимости самого класса (т. Е. У меня есть только внутри блока конструктора). Это решено
Тем не менее, если я дам следующее class abc { some1 abc; john doe; }
это говорит о том, что syntax error, unexpected SEMICOLON, expecting LP
, Итак, символ в строке 19 вызывает проблему.
Вот файл .y (только правило classBody)
class_decl:
CLASS ID LC class_body RC
;
/* FIXME: Gotta add more grammar here */
class_body: var_declmore constructor_declmore method_declmore
| var_declmore constructor_declmore
| var_declmore method_declmore
| constructor_declmore method_declmore
| method_declmore
| var_declmore
| constructor_declmore
| %empty
;
var_declmore: var_decl
| var_declmore var_decl
;
constructor_declmore: constructor_decl
| constructor_declmore constructor_decl
;
var_decl: type ID SEMICOLON
| type ID error
;
constructor_decl: ID LP parameter_list RP block
| ID error parameter_list RP block
;
Вот суть полного .y файла.
1 ответ
Существенная проблема заключается в том, что constructor_declmore
может быть пустым, и что оба var_decl
а также constructor_decl
можно начать с ID
,
Это проблема, потому что перед тем, как парсер сможет распознать constructor_decl
нужно уменьшить (пусто) constructor_declmore
, Но он, очевидно, не может сделать это сокращение, если не знает, что var_declmore
закончен.
Поэтому, когда он видит ID
он должен выбрать одно из двух действий:
Уменьшить пустой
constructor_declmore
тем самым решив, что больше нетvar_decl
s; или жеСдвинуть
ID
чтобы начать разбор новогоvar_decl
,
В отсутствие деклараций предшествования (что здесь не поможет), bison / yacc всегда разрешает конфликты сдвига / уменьшения в пользу действия сдвига. Так что в этом случае предполагается, что Foo
это ID
который начинает var_decl
, что приводит к сообщению об ошибке, которое вы заметили.
Следует также учитывать конфликт уменьшения / уменьшения, вызванный грамматикой. Это исходит от method_declmore: method_decl
правило, которое конфликтует с другим возможным способом создания method_declmore
начиная с пустого method_declmore
а затем добавив method_decl
,