grammarcontext-free-grammarbnfbnfc

Trying to convert a VHDL BNF to a labeled BNF for BNFC


I am in the trying to translate a VHDL BNF defined here to a labeled BNF to use with BNFC

After running bnfc vhdl93-bnf.cf the result is:

bnfc: user error (syntax error at line 22 before { , element_association })

I am not sure what the error is. I have been through the docs for BNFC and LBNF-report but I must have missed something.

Here is what I have so far:

rules abstract_literal ::= decimal_literal | based_literal ;

rules access_type_definition ::= "ACCESS" subtype_indication ;

rules actual_designator ::=
    expression
    | signal_name
    | variable_name
    | file_name
    | "OPEN" ;

rules actual_parameter_part ::= parameter_association_list ;

rules actual_part ::=
    actual_designator
    | function_name "(" actual_designator ")"
    | type_mark "(" actual_designator ")" ;

rules adding_operator ::= "+" | "-" | "&" ;

rules aggregate ::=
    "(" element_association { "," element_association } ")" 

rules alias_declaration ::=
    "ALIAS" alias_designator [ ":" subtype_indication ] "IS" name [ signature ]     ";" ;

rules alias_designator ::= identifier | character_literal | operator_symbol ;

rules allocator ::=
    "NEW" subtype_indication
    | "NEW" qualified_expression ;

rules architecture_body ::=
    "ARCHITECTURE" identifier "OF" entity_name "IS"
        architecture_declarative_part
    "BEGIN"
        architecture_statement_part
    "END" [ "ARCHITECTURE" ] [ architecture_simple_name ] ";"

rules architecture_declarative_part ::=
    { block_declarative_item }

rules architecture_statement_part ::=
    { concurrent_statement }

rules array_type_definition ::=
    unconstrained_array_definition  |   constrained_array_definition

rules assertion ::=
    "ASSERT" condition
        [ "REPORT" expression ]
        [ "SEVERITY" expression ]

rules assertion_statement ::=    [ label ":" ] assertion ";"

rules association_element ::=
    [ formal_part "=>" ] actual_part

rules association_list ::=
    association_element { "," association_element }

rules attribute_declaration ::=
    "ATTRIBUTE" identifier ":" type_mark ";"

rules attribute_designator ::= attribute_simple_name

rules attribute_name ::=
    prefix [ signature ] ' attribute_designator [ "(" expression ")" ]

rules attribute_specification ::=
    "ATTRIBUTE" attribute_designator "OF" entity_specification "IS" expression ";"

rules base ::= integer

rules base_specifier ::=  "B" | "O" | "X"

rules base_unit_declaration ::= identifier ";"

rules based_integer ::=
    extended_digit { [ underline ] extended_digit }

rules based_literal ::=
    base "#" based_integer [ . based_integer ] "#" [ exponent ]

rules basic_character ::=
    basic_graphic_character | format_effector

rules basic_graphic_character ::=
    upper_case_letter | digit | special_character| space_character

rules basic_identifier ::=
    letter { [ underline ] letter_or_digit }

rules binding_indication ::=
    [ "USE" entity_aspect ]
    [ generic_map_aspect ]
    [ port_map_aspect ]

rules bit_string_literal ::=    base_specifier " bit_value "

rules bit_value ::= extended_digit { [ underline ] extended_digit }

rules block_configuration ::=
    "FOR" block_specification
        { use_clause }
        { configuration_item }
    "END" "FOR" ";"

rules block_declarative_item ::=
    subprogram_declaration
    | subprogram_body
    | type_declaration
    | subtype_declaration
    | constant_declaration
    | signal_declaration
    | shared_variable_declaration
    | file_declaration
    | alias_declaration
    | component_declaration
    | attribute_declaration
    | attribute_specification
    | configuration_specification
    | disconnection_specification
    | use_clause
    | group_template_declaration
    | group_declaration

rules block_declarative_part ::=
    { block_declarative_item }

rules block_header ::=
    [ generic_clause
    [ generic_map_aspect ";" ] ]
    [ port_clause
    [ port_map_aspect ";" ] ]

rules block_specification ::=
    architecture_name
    | block_statement_label
    | generate_statement_label [ "(" index_specification ")" ]

rules block_statement ::=
    block_label :
        "BLOCK" [ "(" guard_expression ")" ] [ "IS" ]
            block_header
            block_declarative_part
        "BEGIN"
            block_statement_part
        "END" "BLOCK" [ block_label ] ";"

rules block_statement_part ::=
    { concurrent_statement }

rules case_statement ::=
    [ case_label ":" ]
        "CASE" expression "IS"
            case_statement_alternative
            { case_statement_alternative }
        "END" "CASE" [ case_label ] ";"

rules case_statement_alternative ::=
    "WHEN" choices "=>"
        sequence_of_statements

rules character_literal ::= ' graphic_character '

rules choice ::=
    simple_expression
    | discrete_range
    | element_simple_name
    | "OTHERS"

rules choices ::= choice { | choice }

rules component_configuration ::=
    "FOR" component_specification
        [ binding_indication ";" ]
        [ block_configuration ]
    "END" "FOR" ";"

rules component_declaration ::=
    "COMPONENT" identifier [ "IS" ]
        [ local_generic_clause ]
        [ local_port_clause ]
    "END" "COMPONENT" [ component_simple_name ] ";"

rules component_instantiation_statement ::=
    instantiation_label :
        instantiated_unit
            [ generic_map_aspect ]
            [ port_map_aspect ] ";"

rules component_specification ::=
    instantiation_list ":" component_name

rules composite_type_definition ::=
    array_type_definition
    | record_type_definition

rules concurrent_assertion_statement ::=
    [ label ":" ] [ "POSTPONED" ] assertion ";"

rules concurrent_procedure_call_statement ::=
    [ label ":" ] [ "POSTPONED" ] procedure_call ";"

rules concurrent_signal_assignment_statement ::=
      [ label ":" ] [ "POSTPONED" ] conditional_signal_assignment
    | [ label ":" ] [ "POSTPONED" ] selected_signal_assignment

rules concurrent_statement ::=
    block_statement
    | process_statement
    | concurrent_procedure_call_statement
    | concurrent_assertion_statement
    | concurrent_signal_assignment_statement
    | component_instantiation_statement
    | generate_statement

rules condition ::= boolean_expression

rules condition_clause ::= "UNTIL" condition

rules conditional_signal_assignment ::=
    target  <= options conditional_waveforms ";"

rules conditional_waveforms ::=
    { waveform "WHEN" condition "ELSE" }
    waveform [ "WHEN" condition ]

rules configuration_declaration ::=
    "CONFIGURATION" identifier "OF" entity_name "IS"
        configuration_declarative_part
        block_configuration
    "END" [ "CONFIGURATION" ] [ configuration_simple_name ] ";"

rules configuration_declarative_item ::=
    use_clause
    | attribute_specification
    | group_declaration

rules configuration_declarative_part ::=
    { configuration_declarative_item }

rules configuration_item ::=
    block_configuration
    | component_configuration

rules configuration_specification ::=
    "FOR" component_specification binding_indication ";"

rules constant_declaration ::=
    "CONSTANT" identifier_list ":" subtype_indication [ := expression ] ";"

rules constrained_array_definition ::=
    "ARRAY" index_constraint "OF" element_subtype_indication

rules constraint ::=
    range_constraint
    | index_constraint

rules context_clause ::= { context_item }

rules context_item ::=
    library_clause
    | use_clause

rules decimal_literal ::= integer [ . integer ] [ exponent ]

rules declaration ::=
    type_declaration
    | subtype_declaration
    | object_declaration
    | interface_declaration
    | alias_declaration
    | attribute_declaration
    | component_declaration
    | group_template_declaration
    | group_declaration
    | entity_declaration
    | configuration_declaration
    | subprogram_declaration
    | package_declaration

rules delay_mechanism ::=
    "TRANSPORT"
    | [ "REJECT" time_expression ] "INERTIAL"

rules design_file ::= design_unit { design_unit }

rules design_unit ::= context_clause library_unit

rules designator ::= identifier  |  operator_symbol

rules direction ::= "TO" | "DOWNTO"

rules disconnection_specification ::=
    "DISCONNECT" guarded_signal_specification "AFTER" time_expression ";"

rules discrete_range ::= discrete_subtype_indication | range

rules element_association ::=
    [ choices "=>" ] expression

rules element_declaration ::=
    identifier_list ":" element_subtype_definition ";"

rules element_subtype_definition ::= subtype_indication

rules entity_aspect ::=
      "ENTITY" entity_name [ "(" architecture_identifier")" ]
    | "CONFIGURATION" configuration_name
    | "OPEN"

rules entity_class ::=
    "ENTITY"         | "ARCHITECTURE"  | "CONFIGURATION"
    | "PROCEDURE"  | "FUNCTION"      | "PACKAGE"
    | "TYPE"         | "SUBTYPE"         | "CONSTANT"
    | "SIGNAL"     | "VARIABLE"      | "COMPONENT"
    | "LABEL"        | "LITERAL"         | "UNITS"
    | "GROUP"        | "FILE"

rules entity_class_entry ::=    entity_class [ <> ]

rules entity_class_entry_list ::=
    entity_class_entry { "," entity_class_entry }

rules entity_declaration ::=
    "ENTITY" identifier "IS"
        entity_header
        entity_declarative_part
      [ "BEGIN"
        entity_statement_part ]
    "END" [ "ENTITY" ] [ entity_simple_name ] ";"

rules entity_declarative_item ::=
    subprogram_declaration
    | subprogram_body
    | type_declaration
    | subtype_declaration
    | constant_declaration
    | signal_declaration
    | shared_variable_declaration
    | file_declaration
    | alias_declaration
    | attribute_declaration
    | attribute_specification
    | disconnection_specification
    | use_clause
    | group_template_declaration
    | group_declaration

rules entity_declarative_part ::=
    { entity_declarative_item }

rules entity_designator ::= entity_tag [ signature ]

rules entity_header ::=
    [ formal_generic_clause ]
    [ formal_port_clause ]

rules entity_name_list ::=
    entity_designator { "," entity_designator }
    | "OTHERS"
    | "ALL"

rules entity_specification ::=
    entity_name_list ":" entity_class

rules entity_statement ::=
    concurrent_assertion_statement
    | passive_concurrent_procedure_call_statement
    | passive_process_statement

rules entity_statement_part ::=
    { entity_statement }

rules entity_tag ::=    simple_name | character_literal | operator_symbol

rules enumeration_literal ::= identifier | character_literal

rules enumeration_type_definition ::=
    "(" enumeration_literal { "," enumeration_literal } ")"

rules exit_statement ::=
    [ label ":" ] "EXIT" [ loop_label ] [ "WHEN" condition ] ";"


rules exponent ::= "E" [ "+" ] integer | "E" "-" integer

rules expression ::=
      relation { "AND" relation }
    | relation { "OR" relation }
    | relation { "XOR" relation }
    | relation [ "NAND" relation ]
    | relation [ "NOR" relation ]
    | relation { "XNOR" relation }

rules extended_digit ::= digit | letter

rules extended_identifier ::=
    \ graphic_character { graphic_character } \

rules factor ::=
    primary [ "**" primary ]
    | "ABS" primary
    | "NOT" primary

rules file_declaration ::=
    "FILE" identifier_list ":" subtype_indication file_open_information ] ";"

rules file_logical_name ::= string_expression

rules file_open_information ::=
    [ "OPEN" file_open_kind_expression ] "IS" file_logical_name

rules file_type_definition ::=
    "FILE"  "OF" type_mark

rules floating_type_definition ::=  range_constraint

rules formal_designator ::=
    generic_name
    | port_name
    | parameter_name

rules formal_parameter_list ::= parameter_interface_list

rules formal_part ::=
    formal_designator
    | function_name "(" formal_designator ")"
    | type_mark "(" formal_designator ")"

rules full_type_declaration ::=
    "TYPE" identifier "IS" type_definition ";"

rules function_call ::=
    function_name [ "(" actual_parameter_part ")" ]

rules generate_statement ::=
    generate_label :
        generation_scheme "GENERATE"
            [ { block_declarative_item }
        "BEGIN" ]
            { concurrent_statement }
        "END" "GENERATE" [ generate_label ] ";"

rules generation_scheme ::=
    "FOR" generate_parameter_specification
    | "IF" condition

rules generic_clause ::=
    "GENERIC" "(" generic_list ")" ";"

rules generic_list ::= generic_interface_list

rules generic_map_aspect ::=
    "GENERIC" "MAP" "(" generic_association_list ")"

rules graphic_character ::=
    basic_graphic_character  | lower_case_letter | other_special_character

rules group_constituent ::= name | character_literal

rules group_constituent_list ::= group_constituent { "," group_constituent }

rules group_template_declaration ::=
    "GROUP" identifier "IS" "(" entity_class_entry_list ")" ";"

rules group_declaration ::=
    "GROUP" identifier ":" group_template_name "(" group_constituent_list ")" ";"

rules guarded_signal_specification ::=
    guarded_signal_list ":" type_mark

rules identifier ::=
    basic_identifier | extended_identifier

rules identifier_list ::= identifier { "," identifier }

rules if_statement ::=
    [ if_label ":" ]
        "IF" condition "THEN"
            sequence_of_statements
        { "ELSIF" condition "THEN"
            sequence_of_statements }
        [ "ELSE"
            sequence_of_statements ]
        "END" "IF" [ if_label ] ";"

rules incomplete_type_declaration ::=    "TYPE" identifier ";"

rules index_constraint ::= "(" discrete_range { "," discrete_range } ")"

rules index_specification ::=
    discrete_range
    | static_expression

rules index_subtype_definition ::= type_mark range <>

rules indexed_name ::= prefix "(" expression { "," expression } ")"

rules instantiated_unit ::=
    [ "COMPONENT" ] component_name
    | "ENTITY" entity_name [ "(" architecture_identifier ")" ]
    | "CONFIGURATION" configuration_name

rules instantiation_list ::=
    instantiation_label { "," instantiation_label }
    | "OTHERS"
    | "ALL"

rules integer ::= digit { [ underline ] digit }

rules integer_type_definition ::= range_constraint

rules interface_constant_declaration ::=
    [ "CONSTANT" ] identifier_list ":" [ "IN" ] subtype_indication [ := static_expression ]

rules interface_declaration ::=
    interface_constant_declaration
    | interface_signal_declaration
    | interface_variable_declaration
    | interface_file_declaration

rules interface_element ::= interface_declaration

rules interface_file_declaration ::=
    "FILE" identifier_list ":" subtype_indication

rules interface_list ::=
    interface_element { ";" interface_element }

rules interface_signal_declaration ::=
    ["SIGNAL"] identifier_list ":" [ mode ] subtype_indication [ "BUS" ] [ := static_expression ]

rules interface_variable_declaration ::=
    ["VARIABLE"] identifier_list ":" [ mode ] subtype_indication [ := static_expression ]

rules iteration_scheme ::=
    "WHILE" condition
    | "FOR" loop_parameter_specification

rules label ::= identifier

rules letter ::= upper_case_letter | lower_case_letter

rules letter_or_digit ::= letter | digit

rules library_clause ::= "LIBRARY" logical_name_list ";"

rules library_unit ::=
    primary_unit
    | secondary_unit

rules literal ::=
    numeric_literal
    | enumeration_literal
    | string_literal
    | bit_string_literal
    | "NULL"

rules logical_name ::= identifier

rules logical_name_list ::= logical_name { "," logical_name }

rules logical_operator ::= "AND" | "OR" | "NAND" | "NOR" | "XOR" | "XNOR"

rules loop_statement ::=
    [ loop_label ":" ]
        [ iteration_scheme ] "LOOP"
            sequence_of_statements
        "END" "LOOP" [ loop_label ] ";"

rules miscellaneous_operator ::= "**" | "ABS" | "NOT"

rules mode ::= "IN" | "OUT" | "INOUT" | "BUFFER" | "LINKAGE"

rules multiplying_operator ::= * | "/" | "MOD" | "REM"

rules name ::=
    simple_name
    | operator_symbol
    | selected_name
    | indexed_name
    | slice_name
    | attribute_name

rules next_statement ::=
    [ label ":" ] "NEXT" [ loop_label ] [ "WHEN" condition ] ";"

rules null_statement ::= [ label ":" ] "NULL" ";"

rules numeric_literal ::=
    abstract_literal
    | physical_literal

rules object_declaration ::=
    constant_declaration
    | signal_declaration
    | variable_declaration
    | file_declaration

rules operator_symbol ::= string_literal

rules options ::= [ "GUARDED" ] [ delay_mechanism ]

rules package_body ::=
    "PACKAGE" body package_simple_name "IS"
        package_body_declarative_part
    "END" [ "PACKAGE" "BODY" ] [ package_simple_name ] ";"

rules package_body_declarative_item ::=
    subprogram_declaration
    | subprogram_body
    | type_declaration
    | subtype_declaration
    | constant_declaration
    | shared_variable_declaration
    | file_declaration
    | alias_declaration
    | use_clause
    | group_template_declaration
    | group_declaration

rules package_body_declarative_part ::=
    { package_body_declarative_item }

rules package_declaration ::=
    "PACKAGE" identifier "IS"
        package_declarative_part
    "END" [ "PACKAGE" ] [ package_simple_name ] ";"

rules package_declarative_item ::=
    subprogram_declaration
    | type_declaration
    | subtype_declaration
    | constant_declaration
    | signal_declaration
    | shared_variable_declaration
    | file_declaration
    | alias_declaration
    | component_declaration
    | attribute_declaration
    | attribute_specification
    | disconnection_specification
    | use_clause
    | group_template_declaration
    | group_declaration

rules package_declarative_part ::=
    { package_declarative_item }

rules parameter_specification ::=
    identifier "IN" discrete_range

rules physical_literal ::= [ abstract_literal ] unit_name

rules physical_type_definition ::=
    range_constraint
        "UNITS"
            base_unit_declaration
            { secondary_unit_declaration }
        "END" "UNITS" [ physical_type_simple_name ]

rules port_clause ::=
    "PORT" "(" port_list ")" ";"

rules port_list ::= port_interface_list

rules port_map_aspect ::=
    "PORT" "MAP" "(" port_association_list ")"

rules prefix ::=
    name
    | function_call

rules primary ::=
    name
    | literal
    | aggregate
    | function_call
    | qualified_expression
    | type_conversion
    | allocator
    | "(" expression ")"

rules primary_unit ::=
    entity_declaration
    | configuration_declaration
    | package_declaration

rules procedure_call ::= procedure_name [ "(" actual_parameter_part ")" ]

rules procedure_call_statement ::=
    [ label ":" ] procedure_call ";"

rules process_declarative_item ::=
    subprogram_declaration
    | subprogram_body
    | type_declaration
    | subtype_declaration
    | constant_declaration
    | variable_declaration
    | file_declaration
    | alias_declaration
    | attribute_declaration
    | attribute_specification
    | use_clause
    | group_template_declaration
    | group_declaration

rules process_declarative_part ::=
    { process_declarative_item }

rules process_statement ::=
    [ process_label ":" ]
        [ "POSTPONED" ] "PROCESS" [ "(" sensitivity_list ")" ] [ "IS" ]
            process_declarative_part
        "BEGIN"
            process_statement_part
        "END" [ "POSTPONED" ] "PROCESS" [ process_label ] ";"

rules process_statement_part ::=
    { sequential_statement }

rules qualified_expression ::=
    type_mark ' "(" expression ")"
    | type_mark ' aggregate

rules range ::=
    range_attribute_name
    | simple_expression direction simple_expression

rules range_constraint ::= range range

rules record_type_definition ::=
    "RECORD"
        element_declaration
        { element_declaration }
    "END" "RECORD" [ record_type_simple_name ]

rules relation ::=
    shift_expression [ relational_operator shift_expression ]

rules relational_operator ::=     =  |  "/"=  |  <  |  <=    |  >  |  >=

rules report_statement ::=
    [ label ":" ]
        "REPORT" expression
            [ "SEVERITY" expression ] ";"

rules return_statement ::=
    [ label ":" ] "RETURN" [ expression ] ";"

rules scalar_type_definition ::=
    enumeration_type_definition   | integer_type_definition
    | floating_type_definition    | physical_type_definition

rules secondary_unit ::=
    architecture_body
    | package_body

rules secondary_unit_declaration ::=    identifier = physical_literal ";"

rules selected_name ::= prefix . suffix

rules selected_signal_assignment ::=
    "WITH" expression "SELECT"
        target  <= options selected_waveforms ";"

rules selected_waveforms ::=
    { waveform "WHEN" choices "," }
    waveform "WHEN" choices

rules sensitivity_clause ::=    "ON" sensitivity_list

rules sensitivity_list ::= signal_name { "," signal_name }

rules sequence_of_statements ::=
    { sequential_statement }

rules sequential_statement ::=
    wait_statement
    | assertion_statement
    | report_statement
    | signal_assignment_statement
    | variable_assignment_statement
    | procedure_call_statement
    | if_statement
    | case_statement
    | loop_statement
    | next_statement
    | exit_statement
    | return_statement
    | null_statement

rules shift_expression ::=
    simple_expression [ shift_operator simple_expression ]

rules shift_operator ::= "SLL" | "SRL" | "SLA" | "SRA" | "ROL" | "ROR"

rules sign ::= "+" | "-"

rules signal_assignment_statement ::=
    [ label ":" ] target <= [ delay_mechanism ] waveform ";"

rules signal_declaration ::=
    signal identifier_list ":" subtype_indication [ signal_kind ] [ := expression ] ";"

rules signal_kind ::=    "REGISTER"  |  "BUS"

rules signal_list ::=
    signal_name { "," signal_name }
    | "OTHERS"
    | "ALL"

rules signature ::= [ [ type_mark { "," type_mark } ] [ return type_mark ] ]

rules simple_expression ::=
    [ sign ] term { adding_operator term }

rules simple_name ::=    identifier

rules slice_name ::=    prefix "(" discrete_range ")"

rules string_literal ::= " { graphic_character } "

rules subprogram_body ::=
    subprogram_specification "IS"
        subprogram_declarative_part
    "BEGIN"
        subprogram_statement_part
    "END" [ subprogram_kind ] [ designator ] ";"

rules subprogram_declaration ::=
    subprogram_specification ";"

rules subprogram_declarative_item ::=
    subprogram_declaration
    | subprogram_body
    | type_declaration
    | subtype_declaration
    | constant_declaration
    | variable_declaration
    | file_declaration
    | alias_declaration
    | attribute_declaration
    | attribute_specification
    | use_clause
    | group_template_declaration
    | group_declaration

rules subprogram_declarative_part ::=
    { subprogram_declarative_item }

rules subprogram_kind ::= "PROCEDURE" | "FUNCTION"

rules subprogram_specification ::=
    "PROCEDURE" designator [ "(" formal_parameter_list ")" ]
    | [ "PURE" | "IMPURE" ]  "FUNCTION" designator [ "(" formal_parameter_list ")" ]
        "RETURN" type_mark

rules subprogram_statement_part ::=
    { sequential_statement }

rules subtype_declaration ::=
    "SUBTYPE" identifier "IS" subtype_indication ";"

rules subtype_indication ::=
    [ resolution_function_name ] type_mark [ constraint ]

rules suffix ::=
    simple_name
    | character_literal
    | operator_symbol
    | "ALL"

rules target ::=
    name
    | aggregate

rules term ::=
    factor { multiplying_operator factor }

rules timeout_clause ::= "FOR" time_expression

rules type_conversion ::= type_mark "(" expression ")"

rules type_declaration ::=
    full_type_declaration
    | incomplete_type_declaration

rules type_definition ::=
    scalar_type_definition
    | composite_type_definition
    | access_type_definition
    | file_type_definition

rules type_mark ::=
    type_name
    | subtype_name

rules unconstrained_array_definition ::=
    "ARRAY" "(" index_subtype_definition { "," index_subtype_definition } ")"
        "OF" element_subtype_indication

rules use_clause ::=
    "USE" selected_name { "," selected_name } ";"

rules variable_assignment_statement ::=
    [ label ":" ] target  := expression ";"

rules variable_declaration ::=
    [ "SHARED" ] "VARIABLE" identifier_list ":" subtype_indication [ := expression ] ";"

rules wait_statement ::=
    [ label ":" ] "WAIT" [ sensitivity_clause ] [ condition_clause ] [ timeout_clause ] ";"

rules waveform ::=
    waveform_element { "," waveform_element }
    | "UNAFFECTED"

rules waveform_element ::=
    value_expression [ "AFTER" time_expression ]
    | "NULL" [ "AFTER" time_expression ]

Solution

  • I see at least two problems in the grammar:

    If you want to indicate that an element is optional, you need to write the different cases. E.g.:

    rules FooOptionalBar ::= Foo Bar | Foo;
    

    or

    rules FooOptionalBar ::= Foo OptionalBar;
    rules OptionalBar ::= Bar | ;