Skip to content

Commit 98d24b7

Browse files
committed
Parse subscript designators
1 parent 5a9a8e4 commit 98d24b7

File tree

9 files changed

+137
-53
lines changed

9 files changed

+137
-53
lines changed

packages/cxx-gen-ast/src/new_ast_rewriter.ts

Lines changed: 14 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
#!/usr/bin/env node
2-
31
// Copyright (c) 2025 Roberto Raggi <[email protected]>
42
//
53
// Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -25,12 +23,9 @@ import * as path from "path";
2523
import * as process from "process";
2624
import * as child_process from "child_process";
2725
import { parseAST } from "./parseAST.ts";
28-
29-
import { hideBin } from "yargs/helpers";
30-
import yargs from "yargs";
31-
3226
import { new_ast_rewriter_h } from "./new_ast_rewriter_h.ts";
3327
import { new_ast_rewriter_cc } from "./new_ast_rewriter_cc.ts";
28+
import { parseArgs } from "node:util";
3429

3530
const toSnakeName = (name: string) => {
3631
const r = name
@@ -40,12 +35,7 @@ const toSnakeName = (name: string) => {
4035
return r.startsWith("_") ? r.slice(1) : r;
4136
};
4237

43-
interface MainArgs {
44-
name: string;
45-
}
46-
47-
function main(args: MainArgs) {
48-
const opName = args.name;
38+
function main({ opName }: { opName: string }) {
4939
const baseFileName = toSnakeName(opName);
5040

5141
const outdir = process.cwd();
@@ -78,11 +68,15 @@ function main(args: MainArgs) {
7868
);
7969
}
8070

81-
yargs(hideBin(process.argv))
82-
.option("name", {
83-
alias: "n",
84-
type: "string",
85-
default: "ASTRewriter",
86-
description: "Name of the new rewriter",
87-
})
88-
.command("$0", "generate a new rewriter", () => {}, main).argv;
71+
const { values } = parseArgs({
72+
options: {
73+
name: {
74+
short: "n",
75+
type: "string",
76+
default: "ASTRewriter",
77+
description: "Name of the new rewriter",
78+
},
79+
},
80+
});
81+
82+
main({ opName: values.name });

src/parser/cxx/ast_rewriter.cc

Lines changed: 51 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,22 @@ struct ASTRewriter::ExpressionVisitor {
380380
[[nodiscard]] auto operator()(ParenInitializerAST* ast) -> ExpressionAST*;
381381
};
382382

383+
struct ASTRewriter::DesignatorVisitor {
384+
ASTRewriter& rewrite;
385+
[[nodiscard]] auto translationUnit() const -> TranslationUnit* {
386+
return rewrite.unit_;
387+
}
388+
389+
[[nodiscard]] auto control() const -> Control* { return rewrite.control(); }
390+
[[nodiscard]] auto arena() const -> Arena* { return rewrite.arena(); }
391+
[[nodiscard]] auto rewriter() const -> ASTRewriter* { return &rewrite; }
392+
[[nodiscard]] auto binder() const -> Binder* { return &rewrite.binder_; }
393+
394+
[[nodiscard]] auto operator()(DotDesignatorAST* ast) -> DesignatorAST*;
395+
396+
[[nodiscard]] auto operator()(SubscriptDesignatorAST* ast) -> DesignatorAST*;
397+
};
398+
383399
struct ASTRewriter::TemplateParameterVisitor {
384400
ASTRewriter& rewrite;
385401
[[nodiscard]] auto translationUnit() const -> TranslationUnit* {
@@ -832,6 +848,11 @@ auto ASTRewriter::operator()(ExpressionAST* ast) -> ExpressionAST* {
832848
return expr;
833849
}
834850

851+
auto ASTRewriter::operator()(DesignatorAST* ast) -> DesignatorAST* {
852+
if (!ast) return {};
853+
return visit(DesignatorVisitor{*this}, ast);
854+
}
855+
835856
auto ASTRewriter::operator()(TemplateParameterAST* ast)
836857
-> TemplateParameterAST* {
837858
if (!ast) return {};
@@ -3191,9 +3212,14 @@ auto ASTRewriter::ExpressionVisitor::operator()(
31913212

31923213
copy->valueCategory = ast->valueCategory;
31933214
copy->type = ast->type;
3194-
copy->dotLoc = ast->dotLoc;
3195-
copy->identifierLoc = ast->identifierLoc;
3196-
copy->identifier = ast->identifier;
3215+
3216+
for (auto designatorList = &copy->designatorList;
3217+
auto node : ListView{ast->designatorList}) {
3218+
auto value = rewrite(node);
3219+
*designatorList = make_list_node(arena(), value);
3220+
designatorList = &(*designatorList)->next;
3221+
}
3222+
31973223
copy->initializer = rewrite(ast->initializer);
31983224

31993225
return copy;
@@ -3309,6 +3335,28 @@ auto ASTRewriter::ExpressionVisitor::operator()(ParenInitializerAST* ast)
33093335
return copy;
33103336
}
33113337

3338+
auto ASTRewriter::DesignatorVisitor::operator()(DotDesignatorAST* ast)
3339+
-> DesignatorAST* {
3340+
auto copy = make_node<DotDesignatorAST>(arena());
3341+
3342+
copy->dotLoc = ast->dotLoc;
3343+
copy->identifierLoc = ast->identifierLoc;
3344+
copy->identifier = ast->identifier;
3345+
3346+
return copy;
3347+
}
3348+
3349+
auto ASTRewriter::DesignatorVisitor::operator()(SubscriptDesignatorAST* ast)
3350+
-> DesignatorAST* {
3351+
auto copy = make_node<SubscriptDesignatorAST>(arena());
3352+
3353+
copy->lbracketLoc = ast->lbracketLoc;
3354+
copy->expression = rewrite(ast->expression);
3355+
copy->rbracketLoc = ast->rbracketLoc;
3356+
3357+
return copy;
3358+
}
3359+
33123360
auto ASTRewriter::TemplateParameterVisitor::operator()(
33133361
TemplateTypeParameterAST* ast) -> TemplateParameterAST* {
33143362
auto copy = make_node<TemplateTypeParameterAST>(arena());

src/parser/cxx/ast_rewriter.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ class ASTRewriter {
6464
[[nodiscard]] auto operator()(DeclarationAST* ast) -> DeclarationAST*;
6565
[[nodiscard]] auto operator()(StatementAST* ast) -> StatementAST*;
6666
[[nodiscard]] auto operator()(ExpressionAST* ast) -> ExpressionAST*;
67+
[[nodiscard]] auto operator()(DesignatorAST* ast) -> DesignatorAST*;
6768
[[nodiscard]] auto operator()(TemplateParameterAST* ast)
6869
-> TemplateParameterAST*;
6970
[[nodiscard]] auto operator()(SpecifierAST* ast) -> SpecifierAST*;
@@ -130,6 +131,7 @@ class ASTRewriter {
130131
struct DeclarationVisitor;
131132
struct StatementVisitor;
132133
struct ExpressionVisitor;
134+
struct DesignatorVisitor;
133135
struct TemplateParameterVisitor;
134136
struct SpecifierVisitor;
135137
struct PtrOperatorVisitor;

src/parser/cxx/parser.cc

Lines changed: 51 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -5922,7 +5922,7 @@ auto Parser::parse_braced_init_list(BracedInitListAST*& ast,
59225922

59235923
ast->lbraceLoc = lbraceLoc;
59245924

5925-
if (lookat(TokenKind::T_DOT)) {
5925+
if (lookat_designator()) {
59265926
auto it = &ast->expressionList;
59275927

59285928
DesignatedInitializerClauseAST* designatedInitializerClause = nullptr;
@@ -6018,43 +6018,67 @@ auto Parser::parse_initializer_list(List<ExpressionAST*>*& yyast,
60186018
return true;
60196019
}
60206020

6021+
auto Parser::lookat_designator() -> bool {
6022+
if (lookat(TokenKind::T_DOT)) return true;
6023+
6024+
if (unit->language() == LanguageKind::kCXX) return false;
6025+
6026+
if (lookat(TokenKind::T_LBRACKET)) return true;
6027+
6028+
return false;
6029+
}
6030+
6031+
void Parser::parse_designator(DesignatorAST*& yyast) {
6032+
if (lookat(TokenKind::T_DOT)) {
6033+
parse_dot_designator(yyast);
6034+
} else if (lookat(TokenKind::T_LBRACKET)) {
6035+
parse_subscript_designator(yyast);
6036+
}
6037+
}
6038+
6039+
void Parser::parse_dot_designator(DesignatorAST*& yyast) {
6040+
auto ast = make_node<DotDesignatorAST>(pool_);
6041+
yyast = ast;
6042+
6043+
expect(TokenKind::T_DOT, ast->dotLoc);
6044+
expect(TokenKind::T_IDENTIFIER, ast->identifierLoc);
6045+
ast->identifier = unit->identifier(ast->identifierLoc);
6046+
}
6047+
6048+
void Parser::parse_subscript_designator(DesignatorAST*& yyast) {
6049+
auto ast = make_node<SubscriptDesignatorAST>(pool_);
6050+
yyast = ast;
6051+
6052+
expect(TokenKind::T_LBRACKET, ast->lbracketLoc);
6053+
6054+
std::optional<ConstValue> index;
6055+
if (!parse_constant_expression(ast->expression, index)) {
6056+
parse_error("expected expression after '['");
6057+
}
6058+
6059+
expect(TokenKind::T_RBRACKET, ast->rbracketLoc);
6060+
}
6061+
60216062
auto Parser::parse_designated_initializer_clause(
60226063
DesignatedInitializerClauseAST*& yyast) -> bool {
60236064
auto ast = make_node<DesignatedInitializerClauseAST>(pool_);
60246065
yyast = ast;
60256066

60266067
auto it = &ast->designatorList;
60276068

6028-
while (true) {
6029-
if (SourceLocation dotLoc; match(TokenKind::T_DOT, dotLoc)) {
6030-
auto designator = make_node<DotDesignatorAST>(pool_);
6031-
designator->dotLoc = dotLoc;
6069+
DesignatorAST* designator = nullptr;
6070+
parse_designator(designator);
60326071

6033-
if (lookat(TokenKind::T_IDENTIFIER)) {
6034-
expect(TokenKind::T_IDENTIFIER, designator->identifierLoc);
6035-
designator->identifier = unit->identifier(designator->identifierLoc);
6036-
} else {
6037-
parse_error("expected identifier after '.'");
6038-
}
6039-
6040-
*it = make_list_node<DesignatorAST>(pool_, designator);
6041-
it = &(*it)->next;
6042-
} else if (SourceLocation lbracketLoc;
6043-
match(TokenKind::T_LBRACKET, lbracketLoc)) {
6044-
auto designator = make_node<SubscriptDesignatorAST>(pool_);
6045-
designator->lbracketLoc = lbracketLoc;
6046-
6047-
std::optional<ConstValue> index;
6048-
if (!parse_constant_expression(designator->expression, index)) {
6049-
parse_error("expected expression after '['");
6050-
}
6072+
*it = make_list_node(pool_, designator);
6073+
it = &(*it)->next;
60516074

6052-
expect(TokenKind::T_RBRACKET, designator->rbracketLoc);
6075+
if (unit->language() == LanguageKind::kC) {
6076+
while (lookat_designator()) {
6077+
DesignatorAST* designator = nullptr;
6078+
parse_designator(designator);
60536079

6054-
*it = make_list_node<DesignatorAST>(pool_, designator);
6080+
*it = make_list_node(pool_, designator);
60556081
it = &(*it)->next;
6056-
} else {
6057-
break;
60586082
}
60596083
}
60606084

src/parser/cxx/parser.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -535,6 +535,10 @@ class Parser final {
535535
const ExprContext& ctx) -> bool;
536536
[[nodiscard]] auto parse_designated_initializer_clause(
537537
DesignatedInitializerClauseAST*& yyast) -> bool;
538+
[[nodiscard]] auto lookat_designator() -> bool;
539+
void parse_designator(DesignatorAST*& yyast);
540+
void parse_dot_designator(DesignatorAST*& yyast);
541+
void parse_subscript_designator(DesignatorAST*& yyast);
538542
void parse_expr_or_braced_init_list(ExpressionAST*& yyast,
539543
const ExprContext& ctx);
540544
void parse_virt_specifier_seq(FunctionDeclaratorChunkAST* functionDeclarator);

src/parser/cxx/translation_unit.cc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,10 @@ void TranslationUnit::parse(ParserConfiguration config) {
175175
parse(ast_);
176176
}
177177

178+
auto TranslationUnit::language() const -> LanguageKind {
179+
return preprocessor_->language();
180+
}
181+
178182
auto TranslationUnit::config() const -> const ParserConfiguration& {
179183
return config_;
180184
}

src/parser/cxx/translation_unit.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@ class TranslationUnit {
6666
return preprocessor_.get();
6767
}
6868

69+
[[nodiscard]] auto language() const -> LanguageKind;
70+
6971
void parse(ParserConfiguration config = {});
7072

7173
[[nodiscard]] auto config() const -> const ParserConfiguration&;

tests/unit_tests/ast/designated_initializer_01.cc

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,12 +57,16 @@ auto pair = Pair{
5757
// CHECK-NEXT: braced-init-list: braced-init-list
5858
// CHECK-NEXT: expression-list
5959
// CHECK-NEXT: designated-initializer-clause
60-
// CHECK-NEXT: identifier: first
60+
// CHECK-NEXT: designator-list
61+
// CHECK-NEXT: dot-designator
62+
// CHECK-NEXT: identifier: first
6163
// CHECK-NEXT: initializer: equal-initializer [prvalue int]
6264
// CHECK-NEXT: expression: int-literal-expression [prvalue int]
6365
// CHECK-NEXT: literal: 1
6466
// CHECK-NEXT: designated-initializer-clause
65-
// CHECK-NEXT: identifier: second
67+
// CHECK-NEXT: designator-list
68+
// CHECK-NEXT: dot-designator
69+
// CHECK-NEXT: identifier: second
6670
// CHECK-NEXT: initializer: equal-initializer [prvalue int]
6771
// CHECK-NEXT: expression: int-literal-expression [prvalue int]
6872
// CHECK-NEXT: literal: 2

tests/unit_tests/ast/reflect_02.cc

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,9 @@ auto main() -> int { return S{.x = 10}.[:^S::x:]; }
5555
// CHECK-NEXT: braced-init-list: braced-init-list
5656
// CHECK-NEXT: expression-list
5757
// CHECK-NEXT: designated-initializer-clause
58-
// CHECK-NEXT: identifier: x
58+
// CHECK-NEXT: designator-list
59+
// CHECK-NEXT: dot-designator
60+
// CHECK-NEXT: identifier: x
5961
// CHECK-NEXT: initializer: equal-initializer [prvalue int]
6062
// CHECK-NEXT: expression: int-literal-expression [prvalue int]
6163
// CHECK-NEXT: literal: 10

0 commit comments

Comments
 (0)