docs: def parse(input_: Union[str, FileStream], default_base: Optional[str]=None) -> Optional[Schema]:
      """
      Parse the text in infile and return the resulting schema
      :param input_: text or input stream to parse
      :param default_base_: base URI for relative URI's in schema
      :return: ShExJ Schema object.  None if error.
      """
  
      # Step 1: Tokenize the input stream
      error_listener = ParseErrorListener()
      if not isinstance(input_, FileStream):
          input_ = InputStream(input_)
      lexer = ShExDocLexer(input_)
      lexer.addErrorListener(error_listener)
      tokens = CommonTokenStream(lexer)
      tokens.fill()
      if error_listener.n_errors:         # Lexer prints errors directly
          return None
  
      # Step 2: Generate the parse tree
      parser = ShExDocParser(tokens)
      parser.addErrorListener(error_listener)
      parse_tree = parser.shExDoc()
      if error_listener.n_errors:
          print('\n'.join(error_listener.errors), file=sys.stderr)
          return None
  
      # Step 3: Transform the results the results
      parser = ShexDocParser(default_base=default_base)
      parser.visit(parse_tree)
  
      return parser.context.schema