rip-parser 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (80) hide show
  1. checksums.yaml +7 -0
  2. data/.editorconfig +15 -0
  3. data/.gitignore +9 -0
  4. data/.rspec +1 -0
  5. data/.ruby-version +1 -0
  6. data/Gemfile +3 -0
  7. data/LICENSE.md +9 -0
  8. data/README.md +13 -0
  9. data/Rakefile +1 -0
  10. data/bin/console +8 -0
  11. data/bin/setup +8 -0
  12. data/legacy/normalizer.rb +279 -0
  13. data/legacy/parser_spec.rb +999 -0
  14. data/legacy/rules.rb +250 -0
  15. data/legacy/rules_spec.rb +1700 -0
  16. data/rip-parser.gemspec +20 -0
  17. data/source/rip/parser/about.rb +9 -0
  18. data/source/rip/parser/error.rb +36 -0
  19. data/source/rip/parser/grammar.rb +23 -0
  20. data/source/rip/parser/keywords.rb +84 -0
  21. data/source/rip/parser/location.rb +47 -0
  22. data/source/rip/parser/node.rb +115 -0
  23. data/source/rip/parser/rules/assignment.rb +23 -0
  24. data/source/rip/parser/rules/binary_condition.rb +24 -0
  25. data/source/rip/parser/rules/character.rb +40 -0
  26. data/source/rip/parser/rules/class.rb +60 -0
  27. data/source/rip/parser/rules/common.rb +47 -0
  28. data/source/rip/parser/rules/date_time.rb +31 -0
  29. data/source/rip/parser/rules/expression.rb +122 -0
  30. data/source/rip/parser/rules/import.rb +23 -0
  31. data/source/rip/parser/rules/invocation.rb +15 -0
  32. data/source/rip/parser/rules/invocation_index.rb +15 -0
  33. data/source/rip/parser/rules/keyword.rb +12 -0
  34. data/source/rip/parser/rules/lambda.rb +45 -0
  35. data/source/rip/parser/rules/list.rb +18 -0
  36. data/source/rip/parser/rules/map.rb +15 -0
  37. data/source/rip/parser/rules/module.rb +29 -0
  38. data/source/rip/parser/rules/number.rb +21 -0
  39. data/source/rip/parser/rules/pair.rb +13 -0
  40. data/source/rip/parser/rules/property.rb +33 -0
  41. data/source/rip/parser/rules/range.rb +15 -0
  42. data/source/rip/parser/rules/reference.rb +16 -0
  43. data/source/rip/parser/rules/string.rb +41 -0
  44. data/source/rip/parser/rules/unit.rb +17 -0
  45. data/source/rip/parser/rules.rb +7 -0
  46. data/source/rip/parser/utilities/normalizer.rb +638 -0
  47. data/source/rip/parser.rb +24 -0
  48. data/source/rip-parser.rb +1 -0
  49. data/spec/fixtures/syntax_sample.rip +96 -0
  50. data/spec/spec_helper.rb +20 -0
  51. data/spec/support/helpers.rb +57 -0
  52. data/spec/support/parslet.rb +1 -0
  53. data/spec/support/shared_examples.rb +9 -0
  54. data/spec/unit/rip/parser/grammar_spec.rb +8 -0
  55. data/spec/unit/rip/parser/location_spec.rb +89 -0
  56. data/spec/unit/rip/parser/node_spec.rb +157 -0
  57. data/spec/unit/rip/parser/rules/assignment_spec.rb +59 -0
  58. data/spec/unit/rip/parser/rules/binary_condition_spec.rb +41 -0
  59. data/spec/unit/rip/parser/rules/character_spec.rb +29 -0
  60. data/spec/unit/rip/parser/rules/class_spec.rb +181 -0
  61. data/spec/unit/rip/parser/rules/common_spec.rb +88 -0
  62. data/spec/unit/rip/parser/rules/date_time_spec.rb +61 -0
  63. data/spec/unit/rip/parser/rules/expression_spec.rb +95 -0
  64. data/spec/unit/rip/parser/rules/import_spec.rb +64 -0
  65. data/spec/unit/rip/parser/rules/invocation_index_spec.rb +46 -0
  66. data/spec/unit/rip/parser/rules/invocation_spec.rb +46 -0
  67. data/spec/unit/rip/parser/rules/keyword_spec.rb +17 -0
  68. data/spec/unit/rip/parser/rules/lambda_spec.rb +174 -0
  69. data/spec/unit/rip/parser/rules/list_spec.rb +45 -0
  70. data/spec/unit/rip/parser/rules/map_spec.rb +36 -0
  71. data/spec/unit/rip/parser/rules/module_spec.rb +63 -0
  72. data/spec/unit/rip/parser/rules/number_spec.rb +40 -0
  73. data/spec/unit/rip/parser/rules/pair_spec.rb +25 -0
  74. data/spec/unit/rip/parser/rules/property_spec.rb +27 -0
  75. data/spec/unit/rip/parser/rules/range_spec.rb +37 -0
  76. data/spec/unit/rip/parser/rules/reference_spec.rb +43 -0
  77. data/spec/unit/rip/parser/rules/string_spec.rb +166 -0
  78. data/spec/unit/rip/parser/rules/unit_spec.rb +17 -0
  79. data/spec/unit/rip/parser_spec.rb +106 -0
  80. metadata +192 -0
@@ -0,0 +1,20 @@
1
+ require_relative './source/rip/parser/about'
2
+
3
+ Gem::Specification.new do |spec|
4
+ spec.name = 'rip-parser'
5
+ spec.version = Rip::Parser::About.version
6
+ spec.author = 'Thomas Ingram'
7
+ spec.license = 'MIT'
8
+ spec.summary = 'Composable parser for Rip'
9
+ spec.homepage = 'http://www.rip-lang.org/'
10
+
11
+ spec.files = `git ls-files -z`.split("\x0")
12
+ spec.require_paths = [ 'source' ]
13
+
14
+ spec.add_runtime_dependency 'parslet', '~> 1.7.0'
15
+
16
+ spec.add_development_dependency 'pry'
17
+ spec.add_development_dependency 'pry-doc'
18
+ spec.add_development_dependency 'rake'
19
+ spec.add_development_dependency 'rspec'
20
+ end
@@ -0,0 +1,9 @@
1
+ module Rip
2
+ module Parser
3
+ module About
4
+ def self.version
5
+ '0.1.0'
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,36 @@
1
+ module Rip::Parser
2
+ class Error < StandardError
3
+ attr_reader :code
4
+
5
+ def initialize(message)
6
+ super
7
+ @code = 10
8
+ end
9
+ end
10
+
11
+ class SyntaxError < Error
12
+ attr_reader :location
13
+ attr_reader :cause
14
+
15
+ def initialize(message, location, cause)
16
+ super(message)
17
+
18
+ @location = location
19
+ @cause = cause
20
+ @code = 11
21
+ end
22
+ end
23
+
24
+ class NormalizeError < Error
25
+ attr_reader :origin
26
+ attr_reader :tree
27
+
28
+ def initialize(message, origin, tree = nil)
29
+ super(message)
30
+
31
+ @origin = origin
32
+ @tree = tree
33
+ @code = 12
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,23 @@
1
+ require 'parslet'
2
+
3
+ require_relative './rules'
4
+
5
+ module Rip::Parser
6
+ class Grammar
7
+ include Rip::Parser::Rules::Module
8
+
9
+ def self.parse(origin, source_code)
10
+ begin
11
+ raw_tree = new.module.parse(source_code)
12
+ Rip::Parser::Utilities::Normalizer.apply(origin, raw_tree)
13
+ rescue Parslet::ParseFailed => e
14
+ match = /\A.+ at line (\d+) char (\d+)\.\z/.match(e.message)
15
+ line, column = match ? match.values_at(1, 2).map(&:to_i) : [ 0, 0 ]
16
+ location = Rip::Parser::Location.new(origin, e.cause.pos.charpos, line, column)
17
+ raise Rip::Parser::SyntaxError.new(e.message, location, e.cause)
18
+ end
19
+ end
20
+ end
21
+ end
22
+
23
+ require_relative './utilities/normalizer'
@@ -0,0 +1,84 @@
1
+ module Rip::Parser
2
+ class Keyword
3
+ attr_reader :name
4
+ attr_reader :source_text
5
+
6
+ def initialize(name, source_text = name)
7
+ @name = name.to_sym
8
+ @source_text = source_text.to_s
9
+ end
10
+
11
+ def ==(other)
12
+ name == other.name
13
+ end
14
+
15
+ def to_debug
16
+ name
17
+ end
18
+
19
+ def self.[](name)
20
+ Keywords.all.detect do |keyword|
21
+ keyword.name == name
22
+ end.tap do |keyword|
23
+ raise "Unknown keyword: `#{name}`" if keyword.nil?
24
+ end
25
+ end
26
+ end
27
+
28
+ module Keywords
29
+ def self.all
30
+ [
31
+ conditional,
32
+ dependency,
33
+ exceptional,
34
+ object,
35
+ pseudo,
36
+ query,
37
+ transfer
38
+ ].inject(&:+)
39
+ end
40
+
41
+ def self.conditional
42
+ make_keywords(:if, :switch, :case, :else)
43
+ end
44
+
45
+ def self.dependency
46
+ make_keywords(:import)
47
+ end
48
+
49
+ def self.exceptional
50
+ make_keywords(:try, :catch, :finally)
51
+ end
52
+
53
+ def self.object
54
+ [
55
+ *make_keywords(:class, :enum, :interface),
56
+ Keyword.new(:swerve_rocket, '~>'),
57
+ Keyword.new(:dash_rocket, '->'),
58
+ Keyword.new(:fat_rocket, '=>')
59
+ ]
60
+ end
61
+
62
+ def self.pseudo
63
+ [
64
+ Keyword.new(:class_self, 'self'),
65
+ Keyword.new(:class_prototype, '@'),
66
+ Keyword.new(:lambda_receiver, '@')
67
+ ]
68
+ end
69
+
70
+ def self.query
71
+ make_keywords(:from, :as, :join, :union, :on, :where, :order, :select, :limit, :take)
72
+ end
73
+
74
+ def self.transfer
75
+ make_keywords(:exit, :return, :throw)
76
+ end
77
+
78
+ protected
79
+
80
+ def self.make_keywords(*names)
81
+ names.map { |name| Keyword.new(name) }
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,47 @@
1
+ module Rip::Parser
2
+ class Location
3
+ attr_reader :origin # label where source code is coming from
4
+ attr_reader :offset # zero-based offset from begining of file
5
+ attr_reader :line # one-based line number
6
+ attr_reader :column # one-based character on line
7
+ attr_reader :length # how many characters are covered
8
+
9
+ def initialize(origin, offset, line, column, length = 0)
10
+ @origin = origin
11
+ @offset = offset
12
+ @line = line
13
+ @column = column
14
+ @length = length
15
+ end
16
+
17
+ def ==(other)
18
+ (origin == other.origin) &&
19
+ (offset == other.offset)
20
+ end
21
+
22
+ def add_character(count = 1)
23
+ self.class.new(origin, offset + count, line, column + count, length)
24
+ end
25
+
26
+ def add_line(count = 1)
27
+ self.class.new(origin, offset + count, line + count, 1, length)
28
+ end
29
+
30
+ def inspect
31
+ "#<#{self.class.name} #{self}>"
32
+ end
33
+
34
+ def to_s
35
+ "#{origin}:#{to_debug}"
36
+ end
37
+
38
+ def to_debug
39
+ offset_length = length.zero? ? offset : (offset..(offset + length - 1))
40
+ "#{line}:#{column}(#{offset_length})"
41
+ end
42
+
43
+ def self.from_slice(origin, slice, length = slice.length)
44
+ new(origin, slice.offset, *slice.line_and_column, length)
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,115 @@
1
+ module Rip::Parser
2
+ class Node
3
+ include Enumerable
4
+
5
+ attr_reader :location
6
+ attr_reader :type
7
+ attr_reader :extra
8
+
9
+ def initialize(location:, type:, **extra)
10
+ @location = location
11
+ @type = type
12
+ @extra = extra.inject({}) do |memo, (key, value)|
13
+ memo.merge(key => self.class.try_convert(value))
14
+ end
15
+ end
16
+
17
+ def ==(other)
18
+ to_h == other.to_h
19
+ end
20
+
21
+ def [](key)
22
+ case key.to_sym
23
+ when :location then location
24
+ when :type then type
25
+ else extra[key.to_sym]
26
+ end
27
+ end
28
+
29
+ def each(&block)
30
+ to_h.each(&block)
31
+ end
32
+
33
+ def key?(key)
34
+ extra.key?(key.to_sym)
35
+ end
36
+
37
+ def keys
38
+ extra.keys
39
+ end
40
+
41
+ def length
42
+ location.length
43
+ end
44
+
45
+ def merge(other)
46
+ self.class.new(extra.merge(other.to_h).merge(location: location, type: other[:type] || type))
47
+ end
48
+
49
+ def s_expression
50
+ _extra = extra.map do |key, value|
51
+ [ key, self.class.try_convert_s_expression(value) ]
52
+ end.to_h
53
+
54
+ { type: type }.merge(_extra)
55
+ end
56
+
57
+ def to_h
58
+ _extra = extra.map do |key, value|
59
+ [ key, self.class.try_convert_to_h(value) ]
60
+ end.to_h
61
+
62
+ { location: location, type: type }.merge(_extra)
63
+ end
64
+
65
+ private
66
+
67
+ def method_missing(missing_method, *args, &block)
68
+ case
69
+ when key?(missing_method)
70
+ extra[missing_method]
71
+ when missing_method.to_s.end_with?('?')
72
+ missing_method.to_s.sub(/\?\z/, '').to_sym == type
73
+ else
74
+ super
75
+ end
76
+ end
77
+
78
+ def respond_to_missing?(name, include_all)
79
+ key?(name) || name.to_s.end_with?('?')
80
+ end
81
+
82
+ def self.try_convert(value)
83
+ case value
84
+ when Array
85
+ value.map(&method(:try_convert))
86
+ when Hash
87
+ new(value)
88
+ else
89
+ value
90
+ end
91
+ end
92
+
93
+ def self.try_convert_to_h(value)
94
+ case value
95
+ when Array
96
+ value.map(&method(:try_convert_to_h))
97
+ when self
98
+ value.to_h
99
+ else
100
+ value
101
+ end
102
+ end
103
+
104
+ def self.try_convert_s_expression(value)
105
+ case value
106
+ when Array
107
+ value.map(&method(:try_convert_s_expression))
108
+ when self
109
+ value.s_expression
110
+ else
111
+ value
112
+ end
113
+ end
114
+ end
115
+ end
@@ -0,0 +1,23 @@
1
+ require 'parslet'
2
+
3
+ require_relative './common'
4
+ require_relative './expression'
5
+ require_relative './property'
6
+ require_relative './reference'
7
+
8
+ module Rip::Parser::Rules
9
+ module Assignment
10
+ include ::Parslet
11
+
12
+ include Rip::Parser::Rules::Common
13
+ include Rip::Parser::Rules::Expression
14
+ include Rip::Parser::Rules::Property
15
+ include Rip::Parser::Rules::Reference
16
+
17
+ rule(:reference_assignment) { reference.as(:lhs) >> assignment_rhs }
18
+
19
+ rule(:property_assignment) { (reference.as(:object) >> property).as(:lhs) >> assignment_rhs }
20
+
21
+ rule(:assignment_rhs) { spaces >> equals.as(:location) >> whitespaces >> expression.as(:rhs) }
22
+ end
23
+ end
@@ -0,0 +1,24 @@
1
+ require 'parslet'
2
+
3
+ require_relative './common'
4
+ require_relative './lambda'
5
+ require_relative './keyword'
6
+
7
+ module Rip::Parser::Rules
8
+ module BinaryCondition
9
+ include ::Parslet
10
+
11
+ include Rip::Parser::Rules::Common
12
+ include Rip::Parser::Rules::Lambda
13
+ include Rip::Parser::Rules::Keyword
14
+
15
+ rule(:binary_condition) do
16
+ keyword(:if) >> whitespaces? >>
17
+ parenthesis_open >> whitespaces? >>
18
+ expression.as(:condition) >>
19
+ parenthesis_close >> whitespaces? >>
20
+ block_body(:consequence) >> whitespaces? >>
21
+ keyword(:else) >> whitespaces? >> block_body(:alternative)
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,40 @@
1
+ require 'parslet'
2
+
3
+ require_relative './common'
4
+ require_relative './number'
5
+ require_relative './reference'
6
+
7
+ module Rip::Parser::Rules
8
+ module Character
9
+ include ::Parslet
10
+
11
+ include Rip::Parser::Rules::Common
12
+ include Rip::Parser::Rules::Number
13
+ include Rip::Parser::Rules::Reference
14
+
15
+ SPECIAL_ESCAPES = {
16
+ quote_single: "'",
17
+ quote_double: '"',
18
+ backslash: '\\',
19
+ bell: 'a',
20
+ backspace: 'b',
21
+ form_feed: 'f',
22
+ new_line: 'n',
23
+ carriage_return: 'r',
24
+ tab_horizontal: 't',
25
+ tab_vertical: 'v'
26
+ }
27
+
28
+ rule(:character) { backtick.as(:location) >> (escape_sequence | character_legal.as(:character)) }
29
+
30
+ rule(:character_legal) { digit | word_legal }
31
+
32
+ rule(:backtick) { str('`') }
33
+
34
+ rule(:escape_sequence) { slash_back.as(:escape_location) >> (escape_sequence_unicode | escape_sequence_special | escape_sequence_any) }
35
+
36
+ rule(:escape_sequence_unicode) { str('u') >> match['0-9a-f'].repeat(4, 4).as(:escape_unicode) }
37
+ rule(:escape_sequence_special) { SPECIAL_ESCAPES.values.map(&method(:str)).inject(&:|).as(:escape_special) }
38
+ rule(:escape_sequence_any) { match['\S'].as(:escape_any) }
39
+ end
40
+ end
@@ -0,0 +1,60 @@
1
+ require 'parslet'
2
+
3
+ require_relative './common'
4
+ require_relative './keyword'
5
+ require_relative './lambda'
6
+ require_relative './property'
7
+ require_relative './reference'
8
+
9
+ module Rip::Parser::Rules
10
+ module Class
11
+ include ::Parslet
12
+
13
+ include Rip::Parser::Rules::Common
14
+ include Rip::Parser::Rules::Keyword
15
+ include Rip::Parser::Rules::Lambda
16
+ include Rip::Parser::Rules::Property
17
+ include Rip::Parser::Rules::Reference
18
+
19
+ rule(:class_block) do
20
+ keyword(:class) >> spaces? >> class_ancestors.maybe >> whitespaces? >> brace_open >>
21
+ class_body.maybe.as(:body) >>
22
+ whitespaces? >> brace_close
23
+ end
24
+
25
+ rule(:class_ancestors) do
26
+ parenthesis_open >> whitespaces? >>
27
+ csv(reference).as(:ancestors) >>
28
+ whitespaces? >> parenthesis_close
29
+ end
30
+
31
+ rule(:class_body) do
32
+ whitespaces? >> class_property_assignment >> spaces? >> (
33
+ (semicolon | line_break) >> whitespaces? >> class_body
34
+ ).repeat(0) >> whitespaces?
35
+ end
36
+
37
+ rule(:class_property_assignment) do
38
+ class_property.as(:property) >> spaces >>
39
+ equals.as(:location) >> whitespaces >>
40
+ property_value.as(:property_value)
41
+ end
42
+
43
+ rule(:class_property) do
44
+ keyword(:class_prototype) >> property |
45
+ keyword(:class_self) >> property |
46
+ word.as(:property_name)
47
+ end
48
+
49
+ rule(:property_value) do
50
+ import |
51
+ class_block |
52
+ lambda_block |
53
+ overload_block |
54
+ property_block |
55
+ expression
56
+ end
57
+
58
+ rule(:property_block) { keyword(:swerve_rocket) >> whitespaces? >> block_body }
59
+ end
60
+ end
@@ -0,0 +1,47 @@
1
+ require 'parslet'
2
+
3
+ module Rip::Parser::Rules
4
+ module Common
5
+ include ::Parslet
6
+
7
+ rule(:whitespace) { space | line_break | comment }
8
+ rule(:whitespaces) { whitespace.repeat(1) }
9
+ rule(:whitespaces?) { whitespaces.maybe }
10
+
11
+ rule(:space) { str(' ') | str("\t") }
12
+ rule(:spaces) { space.repeat(1) }
13
+ rule(:spaces?) { spaces.maybe }
14
+
15
+ rule(:line_break) { str("\r\n") | str("\n") | str("\r") }
16
+ rule(:line_breaks) { line_break.repeat(1) }
17
+ rule(:line_breaks?) { line_breaks.maybe }
18
+
19
+ rule(:comment) { pound >> (line_break.absent? >> any).repeat >> (line_break | eof) }
20
+
21
+ rule(:eof) { any.absent? }
22
+
23
+ rule(:dot) { str('.') }
24
+ rule(:comma) { str(',') }
25
+ rule(:semicolon) { str(';') }
26
+ rule(:colon) { str(':') }
27
+ rule(:pound) { str('#') }
28
+ rule(:dash) { str('-') }
29
+ rule(:underscore) { str('_') }
30
+ rule(:equals) { str('=') }
31
+
32
+ rule(:slash_back) { str('\\') }
33
+ rule(:slash_forward) { str('/') }
34
+
35
+ rule(:angled_open) { str('<') }
36
+ rule(:angled_close) { str('>') }
37
+
38
+ rule(:brace_open) { str('{') }
39
+ rule(:brace_close) { str('}') }
40
+
41
+ rule(:bracket_open) { str('[') }
42
+ rule(:bracket_close) { str(']') }
43
+
44
+ rule(:parenthesis_open) { str('(') }
45
+ rule(:parenthesis_close) { str(')') }
46
+ end
47
+ end
@@ -0,0 +1,31 @@
1
+ require 'parslet'
2
+
3
+ require_relative './common'
4
+ require_relative './number'
5
+
6
+ module Rip::Parser::Rules
7
+ module DateTime
8
+ include ::Parslet
9
+
10
+ include Rip::Parser::Rules::Common
11
+ include Rip::Parser::Rules::Number
12
+
13
+ rule(:date_time) { date.as(:date) >> str('T') >> time.as(:time) }
14
+
15
+ rule(:date) do
16
+ digit.repeat(4, 4).as(:year) >> dash >>
17
+ digit.repeat(2, 2).as(:month) >> dash >>
18
+ digit.repeat(2, 2).as(:day)
19
+ end
20
+
21
+ rule(:time) do
22
+ digit.repeat(2, 2).as(:hour) >> colon >>
23
+ digit.repeat(2, 2).as(:minute) >> colon >>
24
+ digit.repeat(2, 2).as(:second) >>
25
+ (dot >> digits.as(:sub_second)).maybe >>
26
+ (
27
+ sign >> digit.repeat(2, 2).as(:hour) >> digit.repeat(2, 2).as(:minute)
28
+ ).as(:offset).maybe
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,122 @@
1
+ require 'parslet'
2
+
3
+ require_relative './binary_condition'
4
+ require_relative './class'
5
+ require_relative './character'
6
+ require_relative './common'
7
+ require_relative './date_time'
8
+ require_relative './import'
9
+ require_relative './invocation'
10
+ require_relative './invocation_index'
11
+ require_relative './keyword'
12
+ require_relative './lambda'
13
+ require_relative './list'
14
+ require_relative './map'
15
+ require_relative './number'
16
+ require_relative './pair'
17
+ require_relative './property'
18
+ require_relative './range'
19
+ require_relative './reference'
20
+ require_relative './string'
21
+ require_relative './unit'
22
+
23
+ module Rip::Parser::Rules
24
+ module Expression
25
+ include ::Parslet
26
+
27
+ include Rip::Parser::Rules::BinaryCondition
28
+
29
+ include Rip::Parser::Rules::Common
30
+
31
+ include Rip::Parser::Rules::Class
32
+
33
+ include Rip::Parser::Rules::DateTime
34
+
35
+ include Rip::Parser::Rules::Number
36
+
37
+ include Rip::Parser::Rules::Character
38
+ include Rip::Parser::Rules::String
39
+
40
+ include Rip::Parser::Rules::Lambda
41
+
42
+ include Rip::Parser::Rules::List
43
+
44
+ include Rip::Parser::Rules::Keyword
45
+
46
+ include Rip::Parser::Rules::Import
47
+
48
+ include Rip::Parser::Rules::Invocation
49
+ include Rip::Parser::Rules::InvocationIndex
50
+
51
+ include Rip::Parser::Rules::Map
52
+
53
+ include Rip::Parser::Rules::Pair
54
+
55
+ include Rip::Parser::Rules::Property
56
+
57
+ include Rip::Parser::Rules::Range
58
+
59
+ include Rip::Parser::Rules::Reference
60
+
61
+ include Rip::Parser::Rules::Unit
62
+
63
+ rule(:expression) { expression_chain }
64
+
65
+ rule(:expression_chain) do
66
+ (
67
+ (
68
+ expression_base |
69
+ (parenthesis_open >> whitespaces? >> expression_chain >> whitespaces? >> parenthesis_close)
70
+ ) >> expression_link.repeat
71
+ ).as(:expression_chain)
72
+ end
73
+
74
+ rule(:expression_base) do
75
+ import |
76
+
77
+ class_block |
78
+
79
+ lambda_block |
80
+ overload_block |
81
+
82
+ # enum_block |
83
+
84
+ binary_condition |
85
+
86
+ # switch_block |
87
+
88
+ # exception_block_sequence |
89
+
90
+ date_time |
91
+ date |
92
+ time |
93
+
94
+ unit |
95
+
96
+ # version | # maybe
97
+
98
+ number |
99
+
100
+ character |
101
+
102
+ string |
103
+ regular_expression |
104
+
105
+ # markup_fragment |
106
+
107
+ list |
108
+
109
+ map |
110
+
111
+ reference
112
+ end
113
+
114
+ rule(:expression_link) do
115
+ property |
116
+ pair_value |
117
+ range_end |
118
+ invocation |
119
+ invocation_index
120
+ end
121
+ end
122
+ end