validate!

in thrift/compiler/generate/templates/cpp2/validate.rb [148:234]


  def validate!
    tokens = @tokens

    cond_stack = []

    while tokens.any?
      tok = tokens.shift
      case tok.type
      when :comment then
        while true
          src_or_close = tokens.shift
          unless [:source, :close].include?(src_or_close.type)
            raise(
              "expected closing delim or non-delimieter in "+
              "comment starting with #{tok.to_loc_and_val_s}"
            )
          end
          if src_or_close.type == :close
            break
          end
        end
      when :echo, :cond, :inv_cond, :end_cond then
        ident = tokens.shift
        unless ident
          raise(
            "expected identifier after opening delim " +
            tok.to_loc_and_val_s
          )
        end
        if !ident || ident.type != :source
          raise(
            "expected identifier after #{tok.type} token, "+
            "got #{ident.to_loc_and_val_s}"
          )
        end
        close = tokens.shift
        unless close
          raise(
            "expected closing delim after #{ident.to_loc_and_val_s}"
          )
        end
        if close.type != :close
          raise(
            "expected closing delim after ident token, "+
            "got #{close.to_loc_and_val_s}"
          )
        end

        if [:cond, :inv_cond].include?(tok.type)
          puts "opening condition/scope -> #{ident}" if debug_conditions?
          cond_stack.push ident
        end

        if :end_cond == tok.type
          puts "closing condition/scope -> #{ident}" if debug_conditions?
          opening_cond = cond_stack.pop
          if !opening_cond
            raise(
              "no matching opening condition for closing condition "+
              "#{ident.to_loc_and_val_s}"
            )
          end
          if ident.value.strip != opening_cond.value.strip
            raise(
              "opening condition #{opening_cond.to_loc_and_val_s} "+
              " was closed with #{ident.to_loc_and_val_s}"
            )
          end
        end

      when :close then
        raise("unexpected closing token at #{tok.to_loc_and_val_s}")
      when :source then
        
      else
        raise "unexpected token #{tok}"
      end
    end

    if cond_stack.any?
      c = cond_stack.shift
      raise(
        "no matching closing delimiter for #{c.to_loc_and_val_s}, got EOF"
      )
    end
  end