brintos

brintos / llvm-project-archived public Read only

0
0
Text · 21.8 KiB · 2dadd46 Raw
473 lines · javascript
1'use strict';2 3const builtin_dialect = require('./dialect/builtin');4const func_dialect = require('./dialect/func');5const llvm_dialect = require('./dialect/llvm');6const arith_dialect = require('./dialect/arith');7const math_dialect = require('./dialect/math');8const cf_dialect = require('./dialect/cf');9const scf_dialect = require('./dialect/scf');10const memref_dialect = require('./dialect/memref');11const vector_dialect = require('./dialect/vector');12const tensor_dialect = require('./dialect/tensor');13const bufferization_dialect = require('./dialect/bufferization');14const affine_dialect = require('./dialect/affine');15const linalg_dialect = require('./dialect/linalg');16 17const common = {18  // Top level production:19  //   (operation | attribute-alias-def | type-alias-def)20  toplevel : $ => seq($._toplevel, repeat($._toplevel)),21  _toplevel : $ => choice($.operation, $.attribute_alias_def, $.type_alias_def),22 23  // Common syntax (lang-ref)24  //  digit     ::= [0-9]25  //  hex_digit ::= [0-9a-fA-F]26  //  letter    ::= [a-zA-Z]27  //  id-punct  ::= [$._-]28  //29  //  integer-literal ::= decimal-literal | hexadecimal-literal30  //  decimal-literal ::= digit+31  //  hexadecimal-literal ::= `0x` hex_digit+32  //  float-literal ::= [-+]?[0-9]+[.][0-9]*([eE][-+]?[0-9]+)?33  //  string-literal  ::= `"` [^"\n\f\v\r]* `"`   TODO: define escaping rules34  //35  _digit : $ => /[0-9]/,36  integer_literal : $ => choice($._decimal_literal, $._hexadecimal_literal),37  _decimal_literal : $ => token(seq(optional(/[-+]/), repeat1(/[0-9]/))),38  _hexadecimal_literal : $ => token(seq('0x', repeat1(/[0-9a-fA-F]/))),39  float_literal : $ =>40      token(seq(optional(/[-+]/), repeat1(/[0-9]/), '.', repeat(/[0-9]/),41                optional(seq(/[eE]/, optional(/[-+]/), repeat1(/[0-9]/))))),42  string_literal : $ => token(seq('"', repeat(/[^\\"\n\f\v\r]+/), '"')),43  bool_literal : $ => token(choice('true', 'false')),44  unit_literal : $ => token('unit'),45  complex_literal : $ =>46      seq('(', choice($.integer_literal, $.float_literal), ',',47          choice($.integer_literal, $.float_literal), ')'),48  tensor_literal : $ =>49      seq(token(choice('dense', 'sparse')), '<',50          optional(choice(51              seq($.nested_idx_list, repeat(seq(',', $.nested_idx_list))),52              $._primitive_idx_literal)),53          '>'),54  array_literal : $ => seq(token('array'), '<', $.type, ':', $._idx_list, '>'),55  _literal : $ => choice($.integer_literal, $.float_literal, $.string_literal,56                         $.bool_literal, $.tensor_literal, $.array_literal,57                         $.complex_literal, $.unit_literal),58 59  nested_idx_list : $ =>60      seq('[', optional(choice($.nested_idx_list, $._idx_list)),61          repeat(seq(',', $.nested_idx_list)), ']'),62  _idx_list : $ => prec.right(seq($._primitive_idx_literal,63                                  repeat(seq(',', $._primitive_idx_literal)))),64  _primitive_idx_literal : $ => choice($.integer_literal, $.float_literal,65                                       $.bool_literal, $.complex_literal),66 67  // Identifiers68  //   bare-id ::= (letter|[_]) (letter|digit|[_$.])*69  //   bare-id-list ::= bare-id (`,` bare-id)*70  //   value-id ::= `%` suffix-id71  //   suffix-id ::= (digit+ | ((letter|id-punct) (letter|id-punct|digit)*))72  //   alias-name :: = bare-id73  //74  //   symbol-ref-id ::= `@` (suffix-id | string-literal) (`::`75  //                     symbol-ref-id)?76  //   value-id-list ::= value-id (`,` value-id)*77  //78  //   // Uses of value, e.g. in an operand list to an operation.79  //   value-use ::= value-id80  //   value-use-list ::= value-use (`,` value-use)*81  bare_id : $ => token(seq(/[a-zA-Z_]/, repeat(/[a-zA-Z0-9_$.]/))),82  _alias_or_dialect_id : $ => token(seq(/[a-zA-Z_]/, repeat(/[a-zA-Z0-9_$]/))),83  bare_id_list : $ => seq($.bare_id, repeat(seq(',', $.bare_id))),84  value_use : $ => seq('%', $._suffix_id),85  _suffix_id : $ => token(seq(86      choice(repeat1(/[0-9]/), seq(/[a-zA-Z_$.-]/, repeat(/[a-zA-Z0-9_$.-]/))),87      optional(seq(choice(':', '#'), repeat1(/[0-9]/))))),88  symbol_ref_id : $ => seq('@', choice($._suffix_id, $.string_literal),89                           optional(seq('::', $.symbol_ref_id))),90  _value_use_list : $ => seq($.value_use, repeat(seq(',', $.value_use))),91 92  // Operations93  //   operation            ::= op-result-list? (generic-operation |94  //                            custom-operation)95  //                            trailing-location?96  //   generic-operation    ::= string-literal `(` value-use-list? `)`97  //                            successor-list? region-list?98  //                            dictionary-attribute? `:` function-type99  //   custom-operation     ::= bare-id custom-operation-format100  //   op-result-list       ::= op-result (`,` op-result)* `=`101  //   op-result            ::= value-id (`:` integer-literal)102  //   successor-list       ::= `[` successor (`,` successor)* `]`103  //   successor            ::= caret-id (`:` bb-arg-list)?104  //   region-list          ::= `(` region (`,` region)* `)`105  //   dictionary-attribute ::= `{` (attribute-entry (`,` attribute-entry)*)?106  //                            `}`107  //   trailing-location    ::= (`loc` `(` location `)`)?108  operation : $ =>109      seq(field('lhs', optional($._op_result_list)),110          field('rhs', choice($.generic_operation, $.custom_operation)),111          field('location', optional($.trailing_location))),112  generic_operation : $ => seq(113      $.string_literal, $._value_use_list_parens, optional($._successor_list),114      optional($._region_list), optional($.attribute), ':', $.function_type),115  // custom-operation rule is defined later in the grammar, post the generic.116  _op_result_list : $ => seq($.op_result, repeat(seq(',', $.op_result)), '='),117  op_result : $ => seq($.value_use, optional(seq(':', $.integer_literal))),118  _successor_list : $ =>119      seq('[', $.successor, repeat(seq(',', $.successor)), ']'),120  successor : $ => seq($.caret_id, optional($._value_arg_list)),121  _region_list : $ => seq('(', $.region, repeat(seq(',', $.region)), ')'),122  dictionary_attribute : $ => seq('{', optional($.attribute_entry),123                                  repeat(seq(',', $.attribute_entry)), '}'),124  trailing_location : $ => seq(token('loc'), '(', $.location, ')'),125  // TODO: Complete location forms.126  location : $ => $.string_literal,127 128  // Blocks129  //   block           ::= block-label operation+130  //   block-label     ::= block-id block-arg-list? `:`131  //   block-id        ::= caret-id132  //   caret-id        ::= `^` suffix-id133  //   value-id-and-type ::= value-id `:` type134  //135  //   // Non-empty list of names and types.136  //   value-id-and-type-list ::= value-id-and-type (`,` value-id-and-type)*137  //138  //   block-arg-list ::= `(` value-id-and-type-list? `)`139  block : $ => seq($.block_label, repeat1($.operation)),140  block_label : $ => seq($._block_id, optional($.block_arg_list), ':'),141  _block_id : $ => $.caret_id,142  caret_id : $ => seq('^', $._suffix_id),143  _value_use_and_type : $ => seq($.value_use, optional(seq(':', $.type))),144  _value_use_and_type_list : $ =>145      seq($._value_use_and_type, repeat(seq(',', $._value_use_and_type))),146  block_arg_list : $ => seq('(', optional($._value_use_and_type_list), ')'),147  _value_arg_list : $ => seq('(', optional($._value_use_type_list), ')'),148  _value_use_type_list : $ => seq($._value_use_list, $._type_annotation),149 150  // Regions151  //   region      ::= `{` entry-block? block* `}`152  //   entry-block ::= operation+153  region : $ => seq('{', optional($.entry_block), repeat($.block), '}'),154  entry_block : $ => repeat1($.operation),155 156  // Types157  //   type ::= type-alias | dialect-type | builtin-type158  //159  //   type-list-no-parens ::=  type (`,` type)*160  //   type-list-parens ::= `(` type-list-no-parens? `)`161  //162  //   // This is a common way to refer to a value with a specified type.163  //   ssa-use-and-type ::= ssa-use `:` type164  //   ssa-use ::= value-use165  //166  //   // Non-empty list of names and types.167  //   ssa-use-and-type-list ::= ssa-use-and-type (`,` ssa-use-and-type)*168  //169  //   function-type ::= (type | type-list-parens) `->` (type |170  //                      type-list-parens)171  type : $ => choice($.type_alias, $.dialect_type, $.builtin_type),172  _type_list_no_parens : $ => prec.left(seq($.type, repeat(seq(',', $.type)))),173  _type_list_parens : $ => seq('(', optional($._type_list_no_parens), ')'),174  function_type : $ =>175      seq(choice($.type, $._type_list_parens), $._function_return),176  _function_return : $ => seq(token('->'), choice($.type, $._type_list_parens)),177  _type_annotation : $ =>178      seq(':', choice(seq($.type, choice('from', 'into', 'to'), $.type),179                      $._type_list_no_parens)),180  _function_type_annotation : $ => seq(':', $.function_type),181  _literal_and_type : $ => seq($._literal, optional($._type_annotation)),182 183  // Type aliases184  //   type-alias-def ::= '!' alias-name '=' type185  //   type-alias ::= '!' alias-name186  type_alias_def : $ => seq('!', $._alias_or_dialect_id, '=', $.type),187  type_alias : $ => seq('!', $._alias_or_dialect_id),188 189  // Dialect Types190  //   dialect-namespace ::= bare-id191  //192  //   opaque-dialect-item ::= dialect-namespace '<' string-literal '>'193  //194  //   pretty-dialect-item ::= dialect-namespace '.'195  //   pretty-dialect-item-lead-ident pretty-dialect-item-body?196  //197  //   pretty-dialect-item-lead-ident ::= '[A-Za-z][A-Za-z0-9._]*'198  //   pretty-dialect-item-body ::= '<' pretty-dialect-item-contents+ '>'199  //   pretty-dialect-item-contents ::= pretty-dialect-item-body200  //                                 | '(' pretty-dialect-item-contents+ ')'201  //                                 | '[' pretty-dialect-item-contents+ ']'202  //                                 | '{' pretty-dialect-item-contents+ '}'203  //                                 | '[^[<({>\])}\0]+'204  //205  //   dialect-type ::= '!' (opaque-dialect-item | pretty-dialect-item)206  dialect_type : $ =>207      seq('!', choice($.opaque_dialect_item, $.pretty_dialect_item)),208  dialect_namespace : $ => $._alias_or_dialect_id,209  dialect_ident : $ => $._alias_or_dialect_id,210  opaque_dialect_item : $ =>211      seq($.dialect_namespace, '<', $.string_literal, '>'),212  pretty_dialect_item : $ => seq($.dialect_namespace, '.', $.dialect_ident,213                                 optional($.pretty_dialect_item_body)),214  pretty_dialect_item_body : $ =>215      seq('<', repeat($._pretty_dialect_item_contents), '>'),216  _pretty_dialect_item_contents : $ =>217      prec.left(choice($.pretty_dialect_item_body, repeat1(/[^<>]/))),218 219  // Builtin types220  builtin_type : $ => choice(221      // TODO: Add opaque_type222      $.integer_type, $.float_type, $.complex_type, $.index_type, $.memref_type,223      $.none_type, $.tensor_type, $.vector_type, $.tuple_type),224 225  // signed-integer-type ::= `si`[1-9][0-9]*226  // unsigned-integer-type ::= `ui`[1-9][0-9]*227  // signless-integer-type ::= `i`[1-9][0-9]*228  // integer-type ::= signed-integer-type | unsigned-integer-type |229  // signless-integer-type230  integer_type : $ =>231      token(seq(choice('si', 'ui', 'i'), /[1-9]/, repeat(/[0-9]/))),232  float_type : $ => token(233      choice('f16', 'f32', 'f64', 'f80', 'f128', 'bf16', 'f8E3M4', 'f8E4M3FN',234             'f8E4M3', 'f8E5M2', 'f4E2M1FN', 'f6E2M3FN', 'f6E3M2FN',235             'f8E8M0FNU')),236  index_type : $ => token('index'),237  none_type : $ => token('none'),238  complex_type : $ => seq(token('complex'), '<', $._prim_type, '>'),239  _prim_type : $ =>240      choice($.integer_type, $.float_type, $.index_type, $.complex_type,241             $.none_type, $.memref_type, $.vector_type, $.tensor_type),242 243  // memref-type ::= `memref` `<` dimension-list-ranked type244  //                 (`,` layout-specification)? (`,` memory-space)? `>`245  // layout-specification ::= attribute-value246  // memory-space ::= attribute-value247  memref_type : $ =>248      seq(token('memref'), '<', field('dimension_list', $.dim_list),249          optional(seq(',', $.attribute_value)),250          optional(seq(',', $.attribute_value)), '>'),251  dim_list : $ => seq($._dim_primitive, repeat(seq('x', $._dim_primitive))),252  _dim_primitive : $ => choice($._prim_type, repeat1($._digit), '?', '*'),253 254  // tensor-type ::= `tensor` `<` dimension-list type (`,` encoding)? `>`255  // dimension-list ::= (dimension `x`)*256  // dimension ::= `?` | decimal-literal257  // encoding ::= attribute-value258  // tensor-type ::= `tensor` `<` `*` `x` type `>`259  tensor_type : $ => seq(token('tensor'), '<', $.dim_list,260                         optional(seq(',', $.tensor_encoding)), '>'),261  tensor_encoding : $ => $.attribute_value,262 263  // vector-type ::= `vector` `<` vector-dim-list vector-element-type `>`264  // vector-element-type ::= float-type | integer-type | index-type265  // vector-dim-list := (static-dim-list `x`)? (`[` static-dim-list `]` `x`)?266  // static-dim-list ::= decimal-literal (`x` decimal-literal)*267  vector_type : $ =>268      seq(token('vector'), '<', optional($.vector_dim_list), $._prim_type, '>'),269  vector_dim_list : $ =>270      choice(seq($._static_dim_list, 'x',271                 optional(seq('[', $._static_dim_list, ']', 'x'))),272             seq('[', $._static_dim_list, ']', 'x')),273  _static_dim_list : $ =>274      seq(repeat1($._digit), repeat(seq('x', repeat1($._digit)))),275 276  // tuple-type ::= `tuple` `<` (type ( `,` type)*)? `>`277  tuple_type : $ =>278      seq(token('tuple'), '<', $.tuple_dim, repeat(seq(',', $.tuple_dim)), '>'),279  tuple_dim : $ => $._prim_type,280 281  // Attributes282  //   attribute-entry ::= (bare-id | string-literal) `=` attribute-value283  //   attribute-value ::= attribute-alias | dialect-attribute |284  //   builtin-attribute285  attribute_entry : $ => seq(choice($.bare_id, $.string_literal),286                             optional(seq('=', $.attribute_value))),287  attribute_value : $ =>288      choice(seq('[', optional($._attribute_value_nobracket),289                 repeat(seq(',', $._attribute_value_nobracket)), ']'),290             $._attribute_value_nobracket),291  _attribute_value_nobracket : $ =>292      choice($.attribute_alias, $.dialect_attribute, $.builtin_attribute,293             $.dictionary_attribute, $._literal_and_type, $.type),294  attribute : $ => choice($.attribute_alias, $.dialect_attribute,295                          $.builtin_attribute, $.dictionary_attribute),296 297  // Attribute Value Aliases298  //   attribute-alias-def ::= '#' alias-name '=' attribute-value299  //   attribute-alias ::= '#' alias-name300  attribute_alias_def : $ =>301      seq('#', $._alias_or_dialect_id, '=', $.attribute_value),302  attribute_alias : $ => seq('#', $._alias_or_dialect_id),303 304  // Dialect Attribute Values305  dialect_attribute : $ =>306      seq('#', choice($.opaque_dialect_item, $.pretty_dialect_item)),307 308  // Builtin Attribute Values309  builtin_attribute : $ => choice(310      // TODO311      $.strided_layout, $.affine_map, $.affine_set),312  strided_layout : $ => seq(token('strided'), '<', '[', $._dim_list_comma, ']',313                            optional(seq(',', token('offset'), ':',314                                         choice($.integer_literal, '?', '*'))),315                            '>'),316  _dim_list_comma : $ =>317      seq($._dim_primitive, repeat(seq(',', $._dim_primitive))),318 319  affine_map : $ =>320      seq(token('affine_map'), '<', $._multi_dim_affine_expr_parens,321          optional($._multi_dim_affine_expr_sq), token('->'),322          $._multi_dim_affine_expr_parens, '>'),323  affine_set : $ =>324      seq(token('affine_set'), '<', $._multi_dim_affine_expr_parens,325          optional($._multi_dim_affine_expr_sq), ':',326          $._multi_dim_affine_expr_parens, '>'),327  _multi_dim_affine_expr_parens : $ =>328      seq('(', optional($._multi_dim_affine_expr), ')'),329  _multi_dim_affine_expr_sq : $ =>330      seq('[', optional($._multi_dim_affine_expr), ']'),331 332  // affine-expr ::= `(` affine-expr `)`333  //               | affine-expr `+` affine-expr334  //               | affine-expr `-` affine-expr335  //               | `-`? integer-literal `*` affine-expr336  //               | affine-expr `ceildiv` integer-literal337  //               | affine-expr `floordiv` integer-literal338  //               | affine-expr `mod` integer-literal339  //               | `-`affine-expr340  //               | bare-id341  //               | `-`? integer-literal342  // multi-dim-affine-expr ::= `(` `)`343  //                         | `(` affine-expr (`,` affine-expr)* `)`344 345  // semi-affine-expr ::= `(` semi-affine-expr `)`346  //                    | semi-affine-expr `+` semi-affine-expr347  //                    | semi-affine-expr `-` semi-affine-expr348  //                    | symbol-or-const `*` semi-affine-expr349  //                    | semi-affine-expr `ceildiv` symbol-or-const350  //                    | semi-affine-expr `floordiv` symbol-or-const351  //                    | semi-affine-expr `mod` symbol-or-const352  //                    | bare-id353  //                    | `-`? integer-literal354  // symbol-or-const ::= `-`? integer-literal | symbol-id355  // multi-dim-semi-affine-expr ::= `(` semi-affine-expr (`,` semi-affine-expr)*356  // `)`357 358  // affine-constraint ::= affine-expr `>=` `affine-expr`359  //                     | affine-expr `<=` `affine-expr`360  //                     | affine-expr `==` `affine-expr`361  // affine-constraint-conjunction ::= affine-constraint (`,`362  // affine-constraint)*363 364  _multi_dim_affine_expr : $ =>365      seq($._affine_expr, repeat(seq(',', $._affine_expr))),366  _affine_expr : $ => prec.right(choice(367      seq('(', $._affine_expr, ')'), seq('-', $._affine_expr),368      seq($._affine_expr, $._affine_token, $._affine_expr), $._affine_prim)),369  _affine_prim : $ =>370      choice($.integer_literal, $.value_use, $.bare_id,371             seq('symbol', '(', $.value_use, ')'),372             seq(choice('max', 'min'), '(', $._value_use_list, ')')),373  _affine_token : $ => token(374      choice('+', '-', '*', 'ceildiv', 'floordiv', 'mod', '==', '>=', '<=')),375 376  func_return : $ => seq(token('->'), $.type_list_attr_parens),377  func_arg_list : $ => seq(378      '(', optional(choice($.variadic, $._value_id_and_type_attr_list)), ')'),379  _value_id_and_type_attr_list : $ => seq(380      $._value_id_and_type_attr, repeat(seq(',', $._value_id_and_type_attr)),381      optional(seq(',', $.variadic))),382  _value_id_and_type_attr : $ => seq($._function_arg, optional($.attribute)),383  _function_arg : $ =>384      choice(seq($.value_use, ':', $.type), $.value_use, $.type),385  type_list_attr_parens : $ =>386      choice($.type,387             seq('(', $.type, optional($.attribute),388                 repeat(seq(',', $.type, optional($.attribute))), ')'),389             seq('(', ')')),390  variadic : $ => token('...'),391 392  // (func.func|llvm.func) takes arguments, an optional return type, and and393  // optional body394  _op_func : $ =>395      seq(field('visibility', optional('private')),396          field('name', $.symbol_ref_id), field('arguments', $.func_arg_list),397          field('return', optional($.func_return)),398          field('attributes', optional(seq(token('attributes'), $.attribute))),399          field('body', optional($.region))),400 401  // dim-use-list ::= `(` ssa-use-list? `)`402  // symbol-use-list ::= `[` ssa-use-list? `]`403  // dim-and-symbol-use-list ::= dim-use-list symbol-use-list?404  _value_use_list_parens : $ => seq('(', optional($._value_use_list), ')'),405  _dim_and_symbol_use_list : $ =>406      seq($._value_use_list_parens, optional($._dense_idx_list)),407 408  // assignment-list ::= assignment | assignment `,` assignment-list409  // assignment ::= ssa-value `=` ssa-value410  _value_assignment_list : $ => seq('(', optional($._value_assignment),411                                    repeat(seq(',', $._value_assignment)), ')'),412  _value_assignment : $ => seq($.value_use, '=', $.value_use),413 414  _dense_idx_list : $ => seq(415      '[',416      optional(seq(choice($.integer_literal, $.value_use),417                   repeat(seq(',', choice($.integer_literal, $.value_use))))),418      ']'),419 420  // lower-bound ::= `max`? affine-map-attribute dim-and-symbol-use-list |421  // shorthand-bound422  // upper-bound ::= `min`? affine-map-attribute dim-and-symbol-use-list |423  // shorthand-bound424  // shorthand-bound ::= ssa-id | `-`? integer-literal425  _bound : $ =>426      choice(seq($.attribute, $._dim_and_symbol_use_list), $._shorthand_bound),427  _shorthand_bound : $ => choice($.value_use, $.integer_literal),428 429  // Dialect-specific attributes430  restrict_attr : $ => token('restrict'),431  writable_attr : $ => token('writable'),432  gather_dims_attr : $ =>433      seq(token('gather_dims'), '(', $._dense_idx_list, ')'),434  scatter_dims_attr : $ =>435      seq(token('scatter_dims'), '(', $._dense_idx_list, ')'),436  unique_attr : $ => token('unique'),437  nofold_attr : $ => token('nofold'),438  outer_dims_perm_attr : $ =>439      seq(token('outer_dims_perm'), '=', $._dense_idx_list),440  inner_dims_pos_attr : $ =>441      seq(token('inner_dims_pos'), '=', $._dense_idx_list),442  inner_tiles_attr : $ => seq(token('inner_tiles'), '=', $._dense_idx_list),443  isWrite_attr : $ => token(choice('read', 'write')),444  localityHint_attr : $ => seq(token('locality'), '<', $.integer_literal, '>'),445  isDataCache_attr : $ => token(choice('data', 'instr')),446  fastmath_attr : $ =>447      seq(token('fastmath'), '<',448          seq($._fastmath_flag, repeat(seq(',', $._fastmath_flag))), '>'),449  _fastmath_flag : $ => token(choice('none', 'reassoc', 'nnan', 'ninf', 'nsz',450                                     'arcp', 'contract', 'afn', 'fast')),451 452  // Comment (standard BCPL)453  comment : $ => token(seq('//', /.*/)),454 455  // TODO: complete456  custom_operation : $ =>457      choice($.builtin_dialect, $.func_dialect, $.llvm_dialect, $.arith_dialect,458             $.math_dialect, $.cf_dialect, $.scf_dialect, $.memref_dialect,459             $.vector_dialect, $.tensor_dialect, $.bufferization_dialect,460             $.affine_dialect, $.linalg_dialect)461}462 463               module.exports = grammar({464  name : 'mlir',465  extras : $ => [/\s/, $.comment],466  conflicts : $ => [[ $._static_dim_list, $._static_dim_list ],467                    [ $.dictionary_attribute, $.region ]],468  rules : Object.assign(common, builtin_dialect, func_dialect, llvm_dialect,469                        arith_dialect, math_dialect, cf_dialect, scf_dialect,470                        memref_dialect, vector_dialect, tensor_dialect,471                        bufferization_dialect, affine_dialect, linalg_dialect)472});473