Files
carbon-lang/explorer/syntax/parse.cpp
T
Richard Smith 7a67715ac5 Error: track message and prefix/location separately. (#1529)
This allows us to combine multiple Errors together without repeating the prefix
information. Also fixes several cases where two "COMPILATION ERROR" prefixes
would be prepended to the same message when errors with prefixes and locations
were produced by the lexer and parser.
2022-07-26 15:08:19 -07:00

91 lines
2.6 KiB
C++

// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#include "explorer/syntax/parse.h"
#include "common/check.h"
#include "common/error.h"
#include "explorer/common/error_builders.h"
#include "explorer/syntax/lexer.h"
#include "explorer/syntax/parse_and_lex_context.h"
#include "explorer/syntax/parser.h"
#include "llvm/Support/Error.h"
namespace Carbon {
static auto ParseImpl(yyscan_t scanner, Nonnull<Arena*> arena,
std::string_view input_file_name, bool parser_debug)
-> ErrorOr<AST> {
// Prepare other parser arguments.
std::optional<AST> ast = std::nullopt;
ParseAndLexContext context(arena->New<std::string>(input_file_name),
parser_debug);
// Do the parse.
auto parser = Parser(arena, scanner, context, &ast);
if (parser_debug) {
parser.set_debug_level(1);
}
if (auto syntax_error_code = parser(); syntax_error_code != 0) {
auto errors = context.take_errors();
if (errors.empty()) {
return Error("Unknown parser erroor");
}
return std::move(errors.front());
}
// Return parse results.
CARBON_CHECK(ast != std::nullopt)
<< "parser validated syntax yet didn't produce an AST.";
return *ast;
}
auto Parse(Nonnull<Arena*> arena, std::string_view input_file_name,
bool parser_debug) -> ErrorOr<AST> {
std::string name_str(input_file_name);
FILE* input_file = fopen(name_str.c_str(), "r");
if (input_file == nullptr) {
return ProgramError(SourceLocation(name_str.c_str(), 0))
<< "Error opening file: " << std::strerror(errno);
}
// Prepare the lexer.
yyscan_t scanner;
yylex_init(&scanner);
auto buffer = yy_create_buffer(input_file, YY_BUF_SIZE, scanner);
yy_switch_to_buffer(buffer, scanner);
ErrorOr<AST> result =
ParseImpl(scanner, arena, input_file_name, parser_debug);
// Clean up the lexer.
yy_delete_buffer(buffer, scanner);
yylex_destroy(scanner);
fclose(input_file);
return result;
}
auto ParseFromString(Nonnull<Arena*> arena, std::string_view input_file_name,
std::string_view file_contents, bool parser_debug)
-> ErrorOr<AST> {
// Prepare the lexer.
yyscan_t scanner;
yylex_init(&scanner);
auto buffer =
yy_scan_bytes(file_contents.data(), file_contents.size(), scanner);
yy_switch_to_buffer(buffer, scanner);
ErrorOr<AST> result =
ParseImpl(scanner, arena, input_file_name, parser_debug);
// Clean up the lexer.
yy_delete_buffer(buffer, scanner);
yylex_destroy(scanner);
return result;
}
} // namespace Carbon