mirror of
https://github.com/RGBCube/serenity
synced 2025-05-14 08:04:57 +00:00
JSSpecCompiler: Parse method headers
This commit is contained in:
parent
a35a751f9e
commit
4d8f74c149
7 changed files with 85 additions and 12 deletions
|
@ -239,7 +239,7 @@ NonnullOwnPtr<SpecificationClause> SpecificationClause::create(SpecificationPars
|
||||||
[&](AK::Empty const&) {
|
[&](AK::Empty const&) {
|
||||||
result = make<SpecificationClause>(move(specification_clause));
|
result = make<SpecificationClause>(move(specification_clause));
|
||||||
},
|
},
|
||||||
[&](OneOf<ClauseHeader::AbstractOperation, ClauseHeader::Accessor> auto const&) {
|
[&](OneOf<ClauseHeader::AbstractOperation, ClauseHeader::Accessor, ClauseHeader::Method> auto const&) {
|
||||||
result = make<SpecFunction>(move(specification_clause));
|
result = make<SpecFunction>(move(specification_clause));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -269,7 +269,7 @@ Optional<FailedTextParseDiagnostic> SpecificationClause::parse_header(XML::Node
|
||||||
auto const& tokens = maybe_tokens.release_value();
|
auto const& tokens = maybe_tokens.release_value();
|
||||||
|
|
||||||
TextParser parser(ctx, tokens, element);
|
TextParser parser(ctx, tokens, element);
|
||||||
auto parse_result = parser.parse_clause_header();
|
auto parse_result = parser.parse_clause_header(m_clause_has_aoid_attribute);
|
||||||
if (parse_result.is_error()) {
|
if (parse_result.is_error()) {
|
||||||
// Still try to at least scavenge section number.
|
// Still try to at least scavenge section number.
|
||||||
if (tokens.size() && tokens[0].type == TokenType::SectionNumber)
|
if (tokens.size() && tokens[0].type == TokenType::SectionNumber)
|
||||||
|
@ -291,6 +291,10 @@ void SpecificationClause::parse(XML::Node const* element)
|
||||||
bool node_ignored_warning_issued = false;
|
bool node_ignored_warning_issued = false;
|
||||||
Optional<FailedTextParseDiagnostic> header_parse_error;
|
Optional<FailedTextParseDiagnostic> header_parse_error;
|
||||||
|
|
||||||
|
m_clause_has_aoid_attribute = element->as_element().attributes.get("aoid").has_value()
|
||||||
|
? TextParser::ClauseHasAoidAttribute::Yes
|
||||||
|
: TextParser::ClauseHasAoidAttribute::No;
|
||||||
|
|
||||||
for (auto const& child : element->as_element().children) {
|
for (auto const& child : element->as_element().children) {
|
||||||
child->content.visit(
|
child->content.visit(
|
||||||
[&](XML::Node::Element const& element) {
|
[&](XML::Node::Element const& element) {
|
||||||
|
@ -363,6 +367,10 @@ bool SpecFunction::post_initialize(XML::Node const* element)
|
||||||
[&](ClauseHeader::Accessor const& accessor) {
|
[&](ClauseHeader::Accessor const& accessor) {
|
||||||
m_name = MUST(String::formatted("%get {}%", MUST(String::join("."sv, accessor.qualified_name))));
|
m_name = MUST(String::formatted("%get {}%", MUST(String::join("."sv, accessor.qualified_name))));
|
||||||
},
|
},
|
||||||
|
[&](ClauseHeader::Method const& method) {
|
||||||
|
m_name = MUST(String::formatted("%{}%", MUST(String::join("."sv, method.qualified_name))));
|
||||||
|
m_arguments = method.arguments;
|
||||||
|
},
|
||||||
[&](auto const&) {
|
[&](auto const&) {
|
||||||
VERIFY_NOT_REACHED();
|
VERIFY_NOT_REACHED();
|
||||||
});
|
});
|
||||||
|
|
|
@ -116,6 +116,7 @@ private:
|
||||||
Optional<FailedTextParseDiagnostic> parse_header(XML::Node const* element);
|
Optional<FailedTextParseDiagnostic> parse_header(XML::Node const* element);
|
||||||
void parse(XML::Node const* element);
|
void parse(XML::Node const* element);
|
||||||
|
|
||||||
|
TextParser::ClauseHasAoidAttribute m_clause_has_aoid_attribute;
|
||||||
SpecificationParsingContext* m_ctx_pointer;
|
SpecificationParsingContext* m_ctx_pointer;
|
||||||
Vector<NonnullOwnPtr<SpecificationClause>> m_subclauses;
|
Vector<NonnullOwnPtr<SpecificationClause>> m_subclauses;
|
||||||
};
|
};
|
||||||
|
|
|
@ -722,23 +722,42 @@ TextParseErrorOr<ClauseHeader::Accessor> TextParser::parse_accessor_declaration(
|
||||||
return accessor;
|
return accessor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TextParseErrorOr<ClauseHeader::Method> TextParser::parse_method_declaration()
|
||||||
|
{
|
||||||
|
auto rollback = rollback_point();
|
||||||
|
|
||||||
|
ClauseHeader::Method method;
|
||||||
|
method.qualified_name = TRY(parse_qualified_name());
|
||||||
|
method.arguments = TRY(parse_function_arguments_in_declaration());
|
||||||
|
TRY(expect_eof());
|
||||||
|
|
||||||
|
rollback.disarm();
|
||||||
|
return method;
|
||||||
|
}
|
||||||
|
|
||||||
// <clause_header> :== <section_number> <ao_declaration> | <accessor_declaration>
|
// <clause_header> :== <section_number> <ao_declaration> | <accessor_declaration>
|
||||||
TextParseErrorOr<ClauseHeader> TextParser::parse_clause_header()
|
TextParseErrorOr<ClauseHeader> TextParser::parse_clause_header(ClauseHasAoidAttribute clause_has_aoid_attribute)
|
||||||
{
|
{
|
||||||
ClauseHeader result;
|
ClauseHeader result;
|
||||||
|
|
||||||
auto section_number_token = TRY(consume_token_with_type(TokenType::SectionNumber));
|
auto section_number_token = TRY(consume_token_with_type(TokenType::SectionNumber));
|
||||||
result.section_number = section_number_token.data;
|
result.section_number = section_number_token.data;
|
||||||
|
|
||||||
if (auto ao_declaration = parse_abstract_operation_declaration(); !ao_declaration.is_error()) {
|
if (clause_has_aoid_attribute == ClauseHasAoidAttribute::Yes) {
|
||||||
result.header = ao_declaration.release_value();
|
if (auto ao_declaration = parse_abstract_operation_declaration(); !ao_declaration.is_error()) {
|
||||||
} else if (auto accessor = parse_accessor_declaration(); !accessor.is_error()) {
|
result.header = ao_declaration.release_value();
|
||||||
result.header = accessor.release_value();
|
return result;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return TextParseError {};
|
if (auto accessor = parse_accessor_declaration(); !accessor.is_error()) {
|
||||||
|
result.header = accessor.release_value();
|
||||||
|
return result;
|
||||||
|
} else if (auto method = parse_method_declaration(); !method.is_error()) {
|
||||||
|
result.header = method.release_value();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return TextParseError {};
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FailedTextParseDiagnostic TextParser::get_diagnostic() const
|
FailedTextParseDiagnostic TextParser::get_diagnostic() const
|
||||||
|
|
|
@ -22,8 +22,13 @@ struct ClauseHeader {
|
||||||
Vector<StringView> qualified_name;
|
Vector<StringView> qualified_name;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct Method {
|
||||||
|
Vector<StringView> qualified_name;
|
||||||
|
Vector<FunctionArgument> arguments;
|
||||||
|
};
|
||||||
|
|
||||||
StringView section_number;
|
StringView section_number;
|
||||||
Variant<AK::Empty, AbstractOperation, Accessor> header;
|
Variant<AK::Empty, AbstractOperation, Accessor, Method> header;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TextParseError { };
|
struct TextParseError { };
|
||||||
|
@ -38,6 +43,11 @@ using TextParseErrorOr = ErrorOr<T, TextParseError>;
|
||||||
|
|
||||||
class TextParser {
|
class TextParser {
|
||||||
public:
|
public:
|
||||||
|
enum class ClauseHasAoidAttribute {
|
||||||
|
No,
|
||||||
|
Yes,
|
||||||
|
};
|
||||||
|
|
||||||
TextParser(SpecificationParsingContext& ctx, Vector<Token> const& tokens, XML::Node const* node)
|
TextParser(SpecificationParsingContext& ctx, Vector<Token> const& tokens, XML::Node const* node)
|
||||||
: m_ctx(ctx)
|
: m_ctx(ctx)
|
||||||
, m_tokens(tokens)
|
, m_tokens(tokens)
|
||||||
|
@ -45,7 +55,7 @@ public:
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
TextParseErrorOr<ClauseHeader> parse_clause_header();
|
TextParseErrorOr<ClauseHeader> parse_clause_header(ClauseHasAoidAttribute clause_has_aoid_attribute);
|
||||||
TextParseErrorOr<Tree> parse_step_without_substeps();
|
TextParseErrorOr<Tree> parse_step_without_substeps();
|
||||||
TextParseErrorOr<Tree> parse_step_with_substeps(Tree substeps);
|
TextParseErrorOr<Tree> parse_step_with_substeps(Tree substeps);
|
||||||
|
|
||||||
|
@ -95,6 +105,7 @@ private:
|
||||||
TextParseErrorOr<Vector<StringView>> parse_qualified_name();
|
TextParseErrorOr<Vector<StringView>> parse_qualified_name();
|
||||||
TextParseErrorOr<Vector<FunctionArgument>> parse_function_arguments_in_declaration();
|
TextParseErrorOr<Vector<FunctionArgument>> parse_function_arguments_in_declaration();
|
||||||
TextParseErrorOr<ClauseHeader::AbstractOperation> parse_abstract_operation_declaration();
|
TextParseErrorOr<ClauseHeader::AbstractOperation> parse_abstract_operation_declaration();
|
||||||
|
TextParseErrorOr<ClauseHeader::Method> parse_method_declaration();
|
||||||
TextParseErrorOr<ClauseHeader::Accessor> parse_accessor_declaration();
|
TextParseErrorOr<ClauseHeader::Accessor> parse_accessor_declaration();
|
||||||
|
|
||||||
SpecificationParsingContext& m_ctx;
|
SpecificationParsingContext& m_ctx;
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
<!DOCTYPE inline_dtd[<!ENTITY nbsp " ">]>
|
||||||
|
<specification>
|
||||||
|
<emu-clause id="1">
|
||||||
|
<h1><span class="secnum">1</span> get Foo.Bar.baz</h1>
|
||||||
|
<emu-alg><ol><li>Return <emu-const>unused</emu-const>.</li></ol></emu-alg>
|
||||||
|
</emu-clause>
|
||||||
|
|
||||||
|
<emu-clause id="2" aoid="TestAbstractOperation">
|
||||||
|
<h1><span class="secnum">2</span> TestAbstractOperation ( <var>a</var> )</h1>
|
||||||
|
<emu-alg><ol><li>Return <emu-const>unused</emu-const>.</li></ol></emu-alg>
|
||||||
|
</emu-clause>
|
||||||
|
|
||||||
|
<emu-clause id="3">
|
||||||
|
<h1><span class="secnum">3</span> Foo.Bar.foo ( <var>a</var> )</h1>
|
||||||
|
<emu-alg><ol><li>Return <emu-const>unused</emu-const>.</li></ol></emu-alg>
|
||||||
|
</emu-clause>
|
||||||
|
</specification>
|
|
@ -0,0 +1,16 @@
|
||||||
|
===== AST after reference-resolving =====
|
||||||
|
%get Foo.Bar.baz%():
|
||||||
|
TreeList
|
||||||
|
ReturnNode
|
||||||
|
Enumerator unused
|
||||||
|
|
||||||
|
TestAbstractOperation(a):
|
||||||
|
TreeList
|
||||||
|
ReturnNode
|
||||||
|
Enumerator unused
|
||||||
|
|
||||||
|
%Foo.Bar.foo%(a):
|
||||||
|
TreeList
|
||||||
|
ReturnNode
|
||||||
|
Enumerator unused
|
||||||
|
|
|
@ -49,6 +49,7 @@ const Array regression_tests = {
|
||||||
},
|
},
|
||||||
TestDescription {
|
TestDescription {
|
||||||
.sources = {
|
.sources = {
|
||||||
|
"spec-headers.xml"sv,
|
||||||
"spec-no-new-line-after-dot.xml"sv,
|
"spec-no-new-line-after-dot.xml"sv,
|
||||||
"spec-optional-arguments.xml"sv,
|
"spec-optional-arguments.xml"sv,
|
||||||
"spec-parsing.xml"sv,
|
"spec-parsing.xml"sv,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue