parse.cpp 3.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. // Part of the Carbon Language project, under the Apache License v2.0 with LLVM
  2. // Exceptions. See /LICENSE for license information.
  3. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. #include "explorer/syntax/parse.h"
  5. #include "common/check.h"
  6. #include "common/error.h"
  7. #include "explorer/base/error_builders.h"
  8. #include "explorer/syntax/lexer.h"
  9. #include "explorer/syntax/parse_and_lex_context.h"
  10. #include "explorer/syntax/parser.h"
  11. namespace Carbon {
  12. static auto ParseImpl(yyscan_t scanner, Nonnull<Arena*> arena,
  13. std::string_view input_file_name, FileKind file_kind,
  14. bool parser_debug) -> ErrorOr<AST> {
  15. // Prepare other parser arguments.
  16. std::optional<AST> ast = std::nullopt;
  17. ParseAndLexContext context(arena->New<std::string>(input_file_name),
  18. file_kind, parser_debug);
  19. // Do the parse.
  20. Parser parser(arena, scanner, context, &ast);
  21. if (parser_debug) {
  22. parser.set_debug_level(1);
  23. }
  24. if (auto syntax_error_code = parser(); syntax_error_code != 0) {
  25. auto errors = context.take_errors();
  26. if (errors.empty()) {
  27. return Error("Unknown parser erroor");
  28. }
  29. return std::move(errors.front());
  30. }
  31. // Return parse results.
  32. CARBON_CHECK(ast != std::nullopt,
  33. "parser validated syntax yet didn't produce an AST.");
  34. return *ast;
  35. }
  36. auto Parse(llvm::vfs::FileSystem& fs, Nonnull<Arena*> arena,
  37. std::string_view input_file_name, FileKind file_kind,
  38. bool parser_debug) -> ErrorOr<AST> {
  39. llvm::ErrorOr<std::unique_ptr<llvm::vfs::File>> input_file =
  40. fs.openFileForRead(input_file_name);
  41. if (input_file.getError()) {
  42. return ProgramError(SourceLocation(input_file_name, 0, file_kind))
  43. << "Error opening file: " << input_file.getError().message();
  44. }
  45. llvm::ErrorOr<llvm::vfs::Status> status = (*input_file)->status();
  46. if (status.getError()) {
  47. return Error(status.getError().message());
  48. }
  49. auto size = status->getSize();
  50. if (size >= std::numeric_limits<int32_t>::max()) {
  51. return ProgramError(SourceLocation(input_file_name, 0, file_kind))
  52. << "File is over the 2GiB input limit.";
  53. }
  54. llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> buffer =
  55. (*input_file)
  56. ->getBuffer(input_file_name, size, /*RequiresNullTerminator=*/false);
  57. if (buffer.getError()) {
  58. return Error(buffer.getError().message());
  59. }
  60. return ParseFromString(arena, input_file_name, file_kind,
  61. (*buffer)->getBuffer(), parser_debug);
  62. }
  63. auto ParseFromString(Nonnull<Arena*> arena, std::string_view input_file_name,
  64. FileKind file_kind, std::string_view file_contents,
  65. bool parser_debug) -> ErrorOr<AST> {
  66. // Prepare the lexer.
  67. yyscan_t scanner;
  68. yylex_init(&scanner);
  69. auto* buffer =
  70. yy_scan_bytes(file_contents.data(), file_contents.size(), scanner);
  71. yy_switch_to_buffer(buffer, scanner);
  72. ErrorOr<AST> result =
  73. ParseImpl(scanner, arena, input_file_name, file_kind, parser_debug);
  74. // Clean up the lexer.
  75. yy_delete_buffer(buffer, scanner);
  76. yylex_destroy(scanner);
  77. return result;
  78. }
  79. } // namespace Carbon