Class: HeadMusic::Notation::LilyPond::ParsePreflight
- Inherits:
-
Object
- Object
- HeadMusic::Notation::LilyPond::ParsePreflight
- Defined in:
- lib/head_music/notation/lily_pond/parse_preflight.rb
Overview
Boundary checks the Parser runs before it reads a document, so a caller never receives a reference to a partially built flow. Each check raises on the first problem it finds and is otherwise a no-op.
Constant Summary collapse
- OPENERS =
{open_brace: :close_brace, open_parallel: :close_parallel, open_chord: :close_chord}.freeze
- LEXEMES =
{ open_brace: "{", close_brace: "}", open_parallel: "<<", close_parallel: ">>", open_chord: "<", close_chord: ">" }.freeze
Class Method Summary collapse
-
.ensure_balanced_delimiters(tokens) ⇒ Object
Braces, << >>, and chord brackets must nest; an unmatched opener is reported at its own line, since that is where the author must look.
-
.ensure_input_present(lily_pond_string) ⇒ Object
Checked on the raw bytes: String#strip raises on invalid UTF-8, and that case belongs to the Lexer's encoding guard.
- .unbalanced_error(token, adjective) ⇒ Object private
Class Method Details
.ensure_balanced_delimiters(tokens) ⇒ Object
Braces, << >>, and chord brackets must nest; an unmatched opener is reported at its own line, since that is where the author must look.
24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
# File 'lib/head_music/notation/lily_pond/parse_preflight.rb', line 24 def self.ensure_balanced_delimiters(tokens) open = [] tokens.each do |token| if OPENERS.key?(token.type) open << token elsif OPENERS.value?(token.type) opener = open.pop unless opener && OPENERS[opener.type] == token.type raise unbalanced_error(token, "Unexpected") end end end raise unbalanced_error(open.last, "Unclosed") if open.any? end |
.ensure_input_present(lily_pond_string) ⇒ Object
Checked on the raw bytes: String#strip raises on invalid UTF-8, and that case belongs to the Lexer's encoding guard.
16 17 18 19 20 |
# File 'lib/head_music/notation/lily_pond/parse_preflight.rb', line 16 def self.ensure_input_present(lily_pond_string) return unless lily_pond_string.to_s.b.strip.empty? raise ParseError, "LilyPond input is blank" end |
.unbalanced_error(token, adjective) ⇒ Object (private)
39 40 41 42 43 44 45 |
# File 'lib/head_music/notation/lily_pond/parse_preflight.rb', line 39 def self.unbalanced_error(token, adjective) lexeme = LEXEMES.fetch(token.type) ParseError.new( %(#{adjective} "#{lexeme}"), line_number: token.line, column: token.column, snippet: lexeme ) end |