Class: Ibex::Runtime::CST::GreenBuilder
- Inherits:
-
Object
- Object
- Ibex::Runtime::CST::GreenBuilder
- Defined in:
- lib/json5/generated_parser.rb
Overview
LR bottom-up builder backed by a Green element stack. rubocop:disable Naming/PredicateMethod -- mutation methods report whether they found a target.
Constant Summary collapse
- EMPTY_TRIVIA =
empty_trivia.freeze
Instance Method Summary collapse
-
#absorb_into_error(pop_count, skipped: []) ⇒ Object
Preserve popped and discarded Green elements in one error node.
-
#append_to_last_error(skipped) ⇒ Object
Append discarded input to the most recent error node on the stack.
-
#append_trailing_to_last_token(trivia) ⇒ Object
Path-copy the right edge to attach balanced trailing trivia.
- #elements ⇒ Object
-
#finish_source_file(eof_token, incomplete: false) ⇒ Object
Wrap the completed start node and explicit EOF token.
-
#finish_synthetic_root(trailing = [], incomplete: false) ⇒ Object
Preserve every available fragment when parsing terminates without a start node.
-
#initialize(kinds:, cache: NodeCache.new) ⇒ GreenBuilder
constructor
A new instance of GreenBuilder.
- #lexical_error(text, leading: EMPTY_TRIVIA) ⇒ Object
-
#make_token(kind, text, leading: EMPTY_TRIVIA, trailing: EMPTY_TRIVIA, flags: 0) ⇒ Object
Construct an interned token without changing the builder stack.
- #missing(expected_kind) ⇒ Object
- #node(kind, arity, flags: 0) ⇒ Object
- #restore(elements) ⇒ Object
- #size ⇒ Object
- #snapshot ⇒ Object
-
#subtree(value) ⇒ Object
Push one already validated nonterminal without rebuilding its descendants.
- #token(kind, text, leading: EMPTY_TRIVIA, trailing: EMPTY_TRIVIA, flags: 0) ⇒ Object
Constructor Details
#initialize(kinds:, cache: NodeCache.new) ⇒ GreenBuilder
Returns a new instance of GreenBuilder.
650 651 652 653 654 |
# File 'lib/json5/generated_parser.rb', line 650 def initialize(kinds:, cache: NodeCache.new) @kinds = kinds @cache = cache @stack = [] end |
Instance Method Details
#absorb_into_error(pop_count, skipped: []) ⇒ Object
Preserve popped and discarded Green elements in one error node.
714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 |
# File 'lib/json5/generated_parser.rb', line 714 def absorb_into_error(pop_count, skipped: []) raise ArgumentError, "pop_count must be non-negative" if pop_count.negative? raise ArgumentError, "green stack underflow" if pop_count > @stack.length empty = [] #: Array[child] popped = pop_count.zero? ? empty : @stack.pop(pop_count) value = @cache.intern_node( GreenNode.new( kind: @kinds.fetch(:error_node), children: popped + skipped, flags: Flags::CONTAINS_ERROR ) ) @stack << value value end |
#append_to_last_error(skipped) ⇒ Object
Append discarded input to the most recent error node on the stack.
760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 |
# File 'lib/json5/generated_parser.rb', line 760 def append_to_last_error(skipped) index = @stack.rindex { |element| element.is_a?(GreenNode) && element.kind == @kinds.fetch(:error_node) } return false unless index error = @stack.fetch(index) return false unless error.is_a?(GreenNode) @stack[index] = @cache.intern_node( GreenNode.new( kind: error.kind, children: error.children + [skipped], flags: error.intrinsic_flags | Flags::CONTAINS_ERROR, annotations: error.annotations ) ) true end |
#append_trailing_to_last_token(trivia) ⇒ Object
Path-copy the right edge to attach balanced trailing trivia.
778 779 780 781 782 783 784 785 786 787 788 789 790 791 |
# File 'lib/json5/generated_parser.rb', line 778 def append_trailing_to_last_token(trivia) return false if trivia.empty? index = @stack.length - 1 while index >= 0 replacement = with_rightmost_trailing(@stack.fetch(index), trivia) if replacement @stack[index] = replacement return true end index -= 1 end false end |
#elements ⇒ Object
805 |
# File 'lib/json5/generated_parser.rb', line 805 def elements = @stack.dup.freeze |
#finish_source_file(eof_token, incomplete: false) ⇒ Object
Wrap the completed start node and explicit EOF token.
732 733 734 735 736 737 738 739 740 741 742 743 |
# File 'lib/json5/generated_parser.rb', line 732 def finish_source_file(eof_token, incomplete: false) raise ArgumentError, "expected one completed start node" unless @stack.one? flags = Flags::SYNTHETIC flags |= Flags::INCOMPLETE_INPUT if incomplete @cache.intern_node( GreenNode.new( kind: @kinds.fetch(:source_file), children: [@stack.fetch(0), eof_token], flags: flags ) ) end |
#finish_synthetic_root(trailing = [], incomplete: false) ⇒ Object
Preserve every available fragment when parsing terminates without a start node.
747 748 749 750 751 752 753 754 755 756 |
# File 'lib/json5/generated_parser.rb', line 747 def finish_synthetic_root(trailing = [], incomplete: false) flags = Flags::SYNTHETIC | Flags::CONTAINS_ERROR flags |= Flags::INCOMPLETE_INPUT if incomplete @cache.intern_node( GreenNode.new( kind: @kinds.fetch(:synthetic_root), children: @stack + trailing, flags: flags ) ) end |
#lexical_error(text, leading: EMPTY_TRIVIA) ⇒ Object
703 704 705 706 707 708 709 710 |
# File 'lib/json5/generated_parser.rb', line 703 def lexical_error(text, leading: EMPTY_TRIVIA) value = @cache.intern_token_fields( kind: @kinds.fetch(:lexical_error_token), text: text, leading: leading, flags: Flags::CONTAINS_ERROR ) @stack << value value end |
#make_token(kind, text, leading: EMPTY_TRIVIA, trailing: EMPTY_TRIVIA, flags: 0) ⇒ Object
Construct an interned token without changing the builder stack.
667 668 669 670 671 |
# File 'lib/json5/generated_parser.rb', line 667 def make_token(kind, text, leading: EMPTY_TRIVIA, trailing: EMPTY_TRIVIA, flags: 0) @cache.intern_token_fields( kind: kind, text: text, leading: leading, trailing: trailing, flags: flags ) end |
#missing(expected_kind) ⇒ Object
693 694 695 696 697 698 699 700 |
# File 'lib/json5/generated_parser.rb', line 693 def missing(expected_kind) value = @cache.intern_token_fields( kind: @kinds.fetch(:missing_token), text: "", expected_kind: expected_kind, flags: Flags::CONTAINS_MISSING | Flags::SYNTHETIC ) @stack << value value end |
#node(kind, arity, flags: 0) ⇒ Object
674 675 676 677 678 679 680 681 682 683 |
# File 'lib/json5/generated_parser.rb', line 674 def node(kind, arity, flags: 0) raise ArgumentError, "arity must be non-negative" if arity.negative? raise ArgumentError, "green stack underflow" if arity > @stack.length empty = [] #: Array[child] children = arity.zero? ? empty : @stack.pop(arity) value = @cache.intern_node(GreenNode.new(kind: kind, children: children, flags: flags)) @stack << value value end |
#restore(elements) ⇒ Object
797 798 799 |
# File 'lib/json5/generated_parser.rb', line 797 def restore(elements) @stack = elements.dup end |
#size ⇒ Object
802 |
# File 'lib/json5/generated_parser.rb', line 802 def size = @stack.length |
#snapshot ⇒ Object
794 |
# File 'lib/json5/generated_parser.rb', line 794 def snapshot = @stack.dup |
#subtree(value) ⇒ Object
Push one already validated nonterminal without rebuilding its descendants.
687 688 689 690 |
# File 'lib/json5/generated_parser.rb', line 687 def subtree(value) @stack << value value end |
#token(kind, text, leading: EMPTY_TRIVIA, trailing: EMPTY_TRIVIA, flags: 0) ⇒ Object
658 659 660 661 662 |
# File 'lib/json5/generated_parser.rb', line 658 def token(kind, text, leading: EMPTY_TRIVIA, trailing: EMPTY_TRIVIA, flags: 0) value = make_token(kind, text, leading: leading, trailing: trailing, flags: flags) @stack << value value end |