Class: RPrec::Prec
- Inherits:
-
Object
- Object
- RPrec::Prec
- Defined in:
- lib/rprec/prec.rb
Overview
Prec
is an operator precedence.
Instance Attribute Summary collapse
- #name ⇒ Symbol readonly
- #ops ⇒ Array<RPrec::Op> readonly
- #postfix_table ⇒ Hash{String => RPrec::Op} readonly private
- #prefix_table ⇒ Hash{String => RPrec::Op} readonly private
- #succs ⇒ Array<Symbol> readonly
Instance Method Summary collapse
-
#initialize(name, succs, ops) ⇒ Prec
constructor
A new instance of Prec.
- #inspect ⇒ String
- #parse(grammar, stream) ⇒ Object? private
- #setup(grammar) ⇒ void private
Constructor Details
#initialize(name, succs, ops) ⇒ Prec
Returns a new instance of Prec.
9 10 11 12 13 |
# File 'lib/rprec/prec.rb', line 9 def initialize(name, succs, ops) @name = name @succs = succs @ops = ops end |
Instance Attribute Details
#name ⇒ Symbol (readonly)
18 19 20 |
# File 'lib/rprec/prec.rb', line 18 def name @name end |
#postfix_table ⇒ Hash{String => RPrec::Op} (readonly)
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
29 30 31 |
# File 'lib/rprec/prec.rb', line 29 def postfix_table @postfix_table end |
#prefix_table ⇒ Hash{String => RPrec::Op} (readonly)
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
26 27 28 |
# File 'lib/rprec/prec.rb', line 26 def prefix_table @prefix_table end |
#succs ⇒ Array<Symbol> (readonly)
20 21 22 |
# File 'lib/rprec/prec.rb', line 20 def succs @succs end |
Instance Method Details
#inspect ⇒ String
202 203 204 205 206 207 208 209 210 211 212 213 |
# File 'lib/rprec/prec.rb', line 202 def inspect result = "prec #{name.inspect}" result << " => #{succs.inspect}" unless succs.empty? unless ops.empty? result << " do\n" ops.each do |op| result << " #{op.inspect}\n" end result << 'end' end result end |
#parse(grammar, stream) ⇒ Object?
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 |
# File 'lib/rprec/prec.rb', line 71 def parse(grammar, stream) op = @prefix_table[stream.current.type] if op key_token = stream.current stream.next case op.type when :prefix parts = grammar.parse_parts(op.parts, stream) return parse_prefix_and_right_assoc(grammar, stream, [[op, [key_token, *parts]]]) when :non_assoc_prefix parts = grammar.parse_parts(op.parts, stream) node = grammar.parse_precs(@succs, stream) return op.build(key_token, *parts, node) when :closed parts = grammar.parse_parts(op.parts, stream) return op.build(key_token, *parts) else raise ScriptError, 'Unreachable' end end stream.expected(@all_prefix_keys) node = grammar.parse_precs(@succs, stream) key_token = stream.current op = @postfix_table[key_token.type] unless op stream.expected(@all_postfix_keys) return node end stream.next case op.type when :postfix parts = grammar.parse_parts(op.parts, stream) node = op.build(node, key_token, *parts) parse_postfix_and_left_assoc(grammar, stream, node) when :non_assoc_postfix parts = grammar.parse_parts(op.parts, stream) op.build(node, key_token, *parts) when :left_assoc parts = grammar.parse_parts(op.parts, stream) right = grammar.parse_precs(@succs, stream) node = op.build(node, key_token, *parts, right) parse_postfix_and_left_assoc(grammar, stream, node) when :right_assoc parts = grammar.parse_parts(op.parts, stream) parse_prefix_and_right_assoc(grammar, stream, [[op, [node, key_token, *parts]]]) when :non_assoc parts = grammar.parse_parts(op.parts, stream) right = grammar.parse_precs(@succs, stream) op.build(node, key_token, *parts, right) else raise ScriptError, 'Unreachable' end end |
#setup(grammar) ⇒ void
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
This method returns an undefined value.
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
# File 'lib/rprec/prec.rb', line 34 def setup(grammar) return unless @prefix_table.nil? && @postfix_table.nil? @prefix_table = {} @postfix_table = {} @ops.each do |op| case op.type when :prefix, :non_assoc_prefix, :closed raise ArgumentError, "Conflict with the key token '#{op.key}'" if @prefix_table.include?(op.key) @prefix_table[op.key] = op when :postfix, :non_assoc_postfix, :left_assoc, :right_assoc, :non_assoc raise ArgumentError, "Conflict with the key token '#{op.key}'" if @postfix_table.include?(op.key) @postfix_table[op.key] = op end end grammar.setup(@succs) @ops.each do |op| parts = op.parts.filter_map { _1.is_a?(Symbol) ? _1 : nil } grammar.setup(parts) end @all_prefix_keys = @prefix_table.keys @all_postfix_keys = @postfix_table.keys @prefix_keys = @prefix_table.filter { |_, op| op.type == :prefix }.keys @right_assoc_keys = @postfix_table.filter { |_, op| op.type == :right_assoc }.keys @postfix_and_left_assoc_keys = @postfix_table.filter { |_, op| op.type == :postfix || op.type == :left_assoc }.keys end |