как обнаружить более одной ошибки в YACC - PullRequest
0 голосов
/ 06 марта 2011

в этом коде (синтаксический анализатор для языка c с использованием yacc) после обнаружения первой ошибки выполнение программы останавливается. что мне делать, чтобы все ошибки отображались и тогда останавливалось только выполнение программы. Я читал некоторые, где вы можете использовать yyerrork, но я не мог применить его. Пожалуйста, помогите.

<code>
    %token IDENTIFIER CONSTANT STRING_LITERAL SIZEOF
%token PTR_OP INC_OP DEC_OP LEFT_OP RIGHT_OP LE_OP GE_OP EQ_OP NE_OP
%token AND_OP OR_OP MUL_ASSIGN DIV_ASSIGN MOD_ASSIGN ADD_ASSIGN
%token SUB_ASSIGN LEFT_ASSIGN RIGHT_ASSIGN AND_ASSIGN
%token XOR_ASSIGN OR_ASSIGN TYPE_NAME</p>

<p>%token TYPEDEF EXTERN STATIC AUTO REGISTER
%token CHAR SHORT INT LONG SIGNED UNSIGNED FLOAT DOUBLE CONST VOLATILE VOID
%token STRUCT UNION ENUM ELLIPSIS</p>

<p>%token CASE DEFAULT IF ELSE SWITCH WHILE DO FOR GOTO CONTINUE BREAK RETURN</p>

<p>%start translation_unit
%%</p>

<p>primary_expression
    : IDENTIFIER
    | CONSTANT
    | STRING_LITERAL
    | '(' expression ')'
    ;</p>

<p>postfix_expression
    : primary_expression
    | postfix_expression '[' expression ']'
    | postfix_expression '(' ')'
    | postfix_expression '(' argument_expression_list ')'
    | postfix_expression '.' IDENTIFIER
    | postfix_expression PTR_OP IDENTIFIER
    | postfix_expression INC_OP
    | postfix_expression DEC_OP
    ;</p>

<p>argument_expression_list
    : assignment_expression
    | argument_expression_list ',' assignment_expression
    ;</p>

<p>unary_expression
    : postfix_expression
    | INC_OP unary_expression
    | DEC_OP unary_expression
    | unary_operator cast_expression
    | SIZEOF unary_expression
    | SIZEOF '(' type_name ')'
    ;</p>

<p>unary_operator
    : '&'
    | '*'
    | '+'
    | '-'
    | '~'
    | '!'
    ;</p>

<p>cast_expression
    : unary_expression
    | '(' type_name ')' cast_expression
    ;</p>

<p>multiplicative_expression
    : cast_expression
    | multiplicative_expression '*' cast_expression
    | multiplicative_expression '/' cast_expression
    | multiplicative_expression '%' cast_expression
    ;</p>

<p>additive_expression
    : multiplicative_expression
    | additive_expression '+' multiplicative_expression
    | additive_expression '-' multiplicative_expression
    ;</p>

<p>shift_expression
    : additive_expression
    | shift_expression LEFT_OP additive_expression
    | shift_expression RIGHT_OP additive_expression
    ;</p>

<p>relational_expression
    : shift_expression
    | relational_expression '<' shift_expression
    | relational_expression '>' shift_expression
    | relational_expression LE_OP shift_expression
    | relational_expression GE_OP shift_expression
    ;</p>

<p>equality_expression
    : relational_expression
    | equality_expression EQ_OP relational_expression
    | equality_expression NE_OP relational_expression
    ;</p>

<p>and_expression
    : equality_expression
    | and_expression '&' equality_expression
    ;</p>

<p>exclusive_or_expression
    : and_expression
    | exclusive_or_expression '^' and_expression
    ;</p>

<p>inclusive_or_expression
    : exclusive_or_expression
    | inclusive_or_expression '|' exclusive_or_expression
    ;</p>

<p>logical_and_expression
    : inclusive_or_expression
    | logical_and_expression AND_OP inclusive_or_expression
    ;</p>

<p>logical_or_expression
    : logical_and_expression
    | logical_or_expression OR_OP logical_and_expression
    ;</p>

<p>conditional_expression
    : logical_or_expression
    | logical_or_expression '?' expression ':' conditional_expression
    ;</p>

<p>assignment_expression
    : conditional_expression
    | unary_expression assignment_operator assignment_expression
    ;</p>

<p>assignment_operator
    : '='
    | MUL_ASSIGN
    | DIV_ASSIGN
    | MOD_ASSIGN
    | ADD_ASSIGN
    | SUB_ASSIGN
    | LEFT_ASSIGN
    | RIGHT_ASSIGN
    | AND_ASSIGN
    | XOR_ASSIGN
    | OR_ASSIGN
    ;</p>

<p>expression
    : assignment_expression
    | expression ',' assignment_expression
    ;</p>

<p>constant_expression
    : conditional_expression
    ;</p>

<p>declaration
    : declaration_specifiers ';'
    | declaration_specifiers init_declarator_list ';'
    ;</p>

<p>declaration_specifiers
    : storage_class_specifier
    | storage_class_specifier declaration_specifiers
    | type_specifier
    | type_specifier declaration_specifiers
    | type_qualifier
    | type_qualifier declaration_specifiers
    ;</p>

<p>init_declarator_list
    : init_declarator
    | init_declarator_list ',' init_declarator
    ;</p>

<p>init_declarator
    : declarator
    | declarator '=' initializer
    ;</p>

<p>storage_class_specifier
    : TYPEDEF
    | EXTERN
    | STATIC
    | AUTO
    | REGISTER
    ;</p>

<p>type_specifier
    : VOID
    | CHAR
    | SHORT
    | INT
    | LONG
    | FLOAT
    | DOUBLE
    | SIGNED
    | UNSIGNED
    | struct_or_union_specifier
    | enum_specifier
    | TYPE_NAME
    ;</p>

<p>struct_or_union_specifier
    : struct_or_union IDENTIFIER '{' struct_declaration_list '}'
    | struct_or_union '{' struct_declaration_list '}'
    | struct_or_union IDENTIFIER
    ;</p>

<p>struct_or_union
    : STRUCT
    | UNION
    ;</p>

<p>struct_declaration_list
    : struct_declaration
    | struct_declaration_list struct_declaration
    ;</p>

<p>struct_declaration
    : specifier_qualifier_list struct_declarator_list ';'
    ;</p>

<p>specifier_qualifier_list
    : type_specifier specifier_qualifier_list
    | type_specifier
    | type_qualifier specifier_qualifier_list
    | type_qualifier
    ;</p>

<p>struct_declarator_list
    : struct_declarator
    | struct_declarator_list ',' struct_declarator
    ;</p>

<p>struct_declarator
    : declarator
    | ':' constant_expression
    | declarator ':' constant_expression
    ;</p>

<p>enum_specifier
    : ENUM '{' enumerator_list '}'
    | ENUM IDENTIFIER '{' enumerator_list '}'
    | ENUM IDENTIFIER
    ;</p>

<p>enumerator_list
    : enumerator
    | enumerator_list ',' enumerator
    ;</p>

<p>enumerator
    : IDENTIFIER
    | IDENTIFIER '=' constant_expression
    ;</p>

<p>type_qualifier
    : CONST
    | VOLATILE
    ;</p>

<p>declarator
    : pointer direct_declarator
    | direct_declarator
    ;</p>

<p>direct_declarator
    : IDENTIFIER
    | '(' declarator ')'
    | direct_declarator '[' constant_expression ']'
    | direct_declarator '[' ']'
    | direct_declarator '(' parameter_type_list ')'
    | direct_declarator '(' identifier_list ')'
    | direct_declarator '(' ')'
    ;</p>

<p>pointer
    : '<em>'
    | '</em>' type_qualifier_list
    | '<em>' pointer
    | '</em>' type_qualifier_list pointer
    ;</p>

<p>type_qualifier_list
    : type_qualifier
    | type_qualifier_list type_qualifier
    ;</p>

<p>parameter_type_list
    : parameter_list
    | parameter_list ',' ELLIPSIS
    ;</p>

<p>parameter_list
    : parameter_declaration
    | parameter_list ',' parameter_declaration
    ;</p>

<p>parameter_declaration
    : declaration_specifiers declarator
    | declaration_specifiers abstract_declarator
    | declaration_specifiers
    ;</p>

<p>identifier_list
    : IDENTIFIER
    | identifier_list ',' IDENTIFIER
    ;</p>

<p>type_name
    : specifier_qualifier_list
    | specifier_qualifier_list abstract_declarator
    ;</p>

<p>abstract_declarator
    : pointer
    | direct_abstract_declarator
    | pointer direct_abstract_declarator
    ;</p>

<p>direct_abstract_declarator
    : '(' abstract_declarator ')'
    | '[' ']'
    | '[' constant_expression ']'
    | direct_abstract_declarator '[' ']'
    | direct_abstract_declarator '[' constant_expression ']'
    | '(' ')'
    | '(' parameter_type_list ')'
    | direct_abstract_declarator '(' ')'
    | direct_abstract_declarator '(' parameter_type_list ')'
    ;</p>

<p>initializer
    : assignment_expression
    | '{' initializer_list '}'
    | '{' initializer_list ',' '}'
    ;</p>

<p>initializer_list
    : initializer
    | initializer_list ',' initializer
    ;</p>

<p>statement
    : labeled_statement
    | compound_statement
    | expression_statement
    | selection_statement
    | iteration_statement
    | jump_statement
    ;</p>

<p>labeled_statement
    : IDENTIFIER ':' statement
    | CASE constant_expression ':' statement
    | DEFAULT ':' statement
    ;</p>

<p>compound_statement
    : '{' '}'
    | '{' statement_list '}'
    | '{' declaration_list '}'
    | '{' declaration_list statement_list '}'
    ;</p>

<p>declaration_list
    : declaration
    | declaration_list declaration
    ;</p>

<p>statement_list
    : statement
    | statement_list statement
    ;</p>

<p>expression_statement
    : ';'
    | expression ';'
    ;</p>

<p>selection_statement
    : IF '(' expression ')' statement
    | IF '(' expression ')' statement ELSE statement
    | SWITCH '(' expression ')' statement
    ;</p>

<p>iteration_statement
    : WHILE '(' expression ')' statement
    | DO statement WHILE '(' expression ')' ';'
    | FOR '(' expression_statement expression_statement ')' statement
    | FOR '(' expression_statement expression_statement expression ')' statement
    ;</p>

<p>jump_statement
    : GOTO IDENTIFIER ';'
    | CONTINUE ';'
    | BREAK ';'
    | RETURN ';'
    | RETURN expression ';'
    ;</p>

<p>translation_unit
    : external_declaration
    | translation_unit external_declaration
    ;</p>

<p>external_declaration
    : function_definition
    | declaration
    ;</p>

<p>function_definition
    : declaration_specifiers declarator declaration_list compound_statement
    | declaration_specifiers declarator compound_statement
    | declarator declaration_list compound_statement
    | declarator compound_statement
    ;</p>

<p>%%</p>

<h1>include </h1>

<p>extern char yytext[];
extern int column;</p>

<p>yyerror(s)
char *s;
{
    fflush(stdout);
    printf("\n%*s\n%*s\n", column, "^", column, s);
} 

Ответы [ 2 ]

1 голос
/ 06 марта 2011

Вам нужно дать yacc некоторые правила для восстановления после синтаксической ошибки и попытки продолжить.В вашей грамматике вы можете добавить правило вроде:

declaration: error ';'

Это правило позволит восстанавливаться после ошибок, обнаруженных при синтаксическом анализе объявления - анализатор будет сканировать ввод, пока не увидит ';'и сказать, что это конец декларации и попытаться продолжить оттуда.Вы также можете добавить такие правила, как:

struct_or_union_specifier
    : struct_or_union IDENTIFIER '{' error '}'
    | struct_or_union '{' error '}'

, чтобы перейти к следующему }, когда вы столкнетесь с ошибкой в ​​спецификаторе структуры.Вы можете поэкспериментировать с добавлением большего количества правил, но сложно определить, какое правило восстановления после ошибок будет использоваться в любой конкретной ситуации (yacc выдает состояния, пока не найдет правило, которое имеет действие для ошибки, поэтому вам действительно нужно понять состояниемашина, которую он собирает для вашего парсера)

0 голосов
/ 06 марта 2011

Мальчик, это возвращает меня на несколько лет назад.Я думал, что теперь народ использует Бизона.Сложно восстанавливаться после ошибок, YACC пытается исправить ситуацию.Я помню, как иногда приходилось играть со стеком и использовать yyerrok, чтобы анализатор мог продолжить.Помните, что когда дела идут на юг, часто есть веская причина, и эта веская причина колеблется, хотя и создает много ложных срабатываний.Тем не менее, с большим трудом, если вы знаете свой грамматик, и если вы хотите настроить грамматику, возможно довольно хорошее исправление ошибок.

Я нашел URL-адрес ссылки, которую использовал: http://dinosaur.compilertools.net/yacc/index.html

...