blambeau/finitio-rb

View on GitHub
lib/finitio/syntax/types.citrus

Summary

Maintainability
Test Coverage
require 'finitio/syntax/lexer'
require 'finitio/syntax/literals'

grammar Finitio::Syntax::Types
  include Finitio::Syntax::Lexer
  include Finitio::Syntax::Literals

  rule type_def
    (metadata? type_name ('<' vars:high_order_vars '>')? equal type)
    <Finitio::Syntax::TypeDef>
  end

  rule high_order_vars
    (type_name (comma type_name)*)
    <Finitio::Syntax::HighOrderVars>
  end

  rule main_type
    (metadata? type)
    <Finitio::Syntax::MainType>
  end

  rule type
    union_type
  end

  # union and sub types

  rule union_type
    (sub_type (pipe sub_type)*)
    <Finitio::Syntax::UnionType>
  end

  rule sub_type
    (rel_type constraint_def?)
    <Finitio::Syntax::SubType>
  end

  rule constraint_def
    ('(' spacing var_name pipe constraints spacing ')')
    <Finitio::Syntax::ConstraintDef>
  end

  rule constraints
      (constraint:named_constraint (opt_comma constraint:named_constraint)* opt_comma)
      <Finitio::Syntax::Constraints>
    | (spacing constraint:unnamed_constraint)
      <Finitio::Syntax::Constraints>
  end

  rule named_constraint
    (metadata? constraint_name colon expression)
    <Finitio::Syntax::NamedConstraint>
  end

  rule unnamed_constraint
    (metadata? expression)
    <Finitio::Syntax::UnnamedConstraint>
  end

  # relational types

  rule rel_type
      relation_type
    | tuple_type
    | high_order_type_instantiation
    | collection_type
  end

  rule relation_type
    ('{{' spacing heading spacing '}}')
    <Finitio::Syntax::RelationType>
  end

  rule tuple_type
    ('{' spacing heading spacing '}')
    <Finitio::Syntax::TupleType>
  end

  rule heading
    (attribute? (opt_comma attribute)* (opt_comma allow_extra:heading_extra)? opt_comma?)
    <Finitio::Syntax::Heading>
  end

  rule heading_extra
    (dots (':' spacing extra_type:type)?)
    <Finitio::Syntax::HeadingExtra>
  end

  rule attribute
    (metadata? attribute_name spacing multiplicity:(':?' | ':') spacing type)
    <Finitio::Syntax::Attribute>
  end

  # collection types

  rule collection_type
      set_type
    | seq_type
    | struct_type
    | term_type
  end

  rule set_type
    ('{' type '}')
    <Finitio::Syntax::SetType>
  end

  rule seq_type
    ('[' type ']')
    <Finitio::Syntax::SeqType>
  end

  rule struct_type
    ('<' type (comma type)* '>')
    <Finitio::Syntax::StructType>
  end

  # high-order types

  rule high_order_type_instantiation
    (high:type_name '<' vars:high_order_vars '>')
    <Finitio::Syntax::HighOrderTypeInstantiation>
  end

  # terminal forms

  rule term_type
      ad_type
    | builtin_type
    | any_type
    | type_ref
  end

  # ad type

  rule ad_type
    (('.' builtin_type_name)? spacing contract (opt_comma contract)* opt_comma)
    <Finitio::Syntax::AdType>
  end

  rule contract
    (metadata? '<' contract_name '>' spacing type spacing pair?)
    <Finitio::Syntax::Contract>
  end

  rule pair
      inline_pair
    | external_pair
  end

  rule inline_pair
    ('\\' dress:lambda_expr spacing '\\' undress:lambda_expr)
    <Finitio::Syntax::InlinePair>
  end

  rule external_pair
    ('.' builtin_type_name)
    <Finitio::Syntax::ExternalPair>
  end

  # any

  rule any_type
    '.'
    <Finitio::Syntax::AnyType>
  end

  # builtin and refs

  rule builtin_type
    ('.' builtin_type_name)
    <Finitio::Syntax::BuiltinType>
  end

  rule type_ref
    (type_name spacing)
    <Finitio::Syntax::TypeRef>
  end

  # metadata

  rule metadata
    (open_metadata metadata_attr (opt_comma metadata_attr)* opt_comma close_metadata)
    <Finitio::Syntax::Metadata>
  | (open_metadata description:(!'-/' .)+ close_metadata)
    <Finitio::Syntax::Metadata>
  end

  rule metadata_attr
    (attribute_name colon literal)
    <Finitio::Syntax::MetadataAttr>
  end

  # lambda and expressions

  rule lambda_expr
    ('(' spacing var_name pipe expression spacing ')')
    <Finitio::Syntax::LambdaExpr>
  end

  rule expression
    expression_part+
    <Finitio::Syntax::Expression>
  end

  rule expression_part
      ('(' expression ')')
    | (![\(,\)\n] .)+
  end

end