Skip to content

Commit 0ca8d56

Browse files
committed
Add basic AstNode structure
1 parent 0d318c7 commit 0ca8d56

1 file changed

Lines changed: 159 additions & 0 deletions

File tree

libraries/rushell/src/AstNode.ts

Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
2+
// See LICENSE in the project root for license information.
3+
4+
import { Token } from './Tokenizer';
5+
6+
export enum AstKind {
7+
Script,
8+
AndIf,
9+
Command,
10+
CompoundWord,
11+
VariableExpansion,
12+
Text
13+
}
14+
15+
/**
16+
* Base class for all AST nodes.
17+
*/
18+
export abstract class AstNode {
19+
public abstract get kind(): AstKind;
20+
21+
/**
22+
* Returns a diagnostic dump of the tree, showing the prefix/suffix/separator for
23+
* each node.
24+
*/
25+
public getDump(indent: string = ''): string {
26+
let result: string = indent + AstKind[this.kind];
27+
28+
const dumpText: string | undefined = this.getDumpText();
29+
if (dumpText) {
30+
result += '=' + JSON.stringify(dumpText);
31+
}
32+
33+
const childNodes: AstNode[] = this.getChildNodes();
34+
if (childNodes.length === 0) {
35+
result += '\n';
36+
} else {
37+
result += ':\n';
38+
for (const child of this.getChildNodes()) {
39+
result += child.getDump(indent + ' ');
40+
}
41+
}
42+
43+
return result;
44+
}
45+
46+
public getChildNodes(): AstNode[] {
47+
const nodes: AstNode[] = [];
48+
this.pushChildNodes(nodes);
49+
return nodes;
50+
}
51+
52+
protected abstract pushChildNodes(nodes: AstNode[]): void;
53+
54+
protected getDumpText(): string | undefined{
55+
return undefined;
56+
}
57+
}
58+
59+
export class AstScript extends AstNode {
60+
public body: AstNode | undefined;
61+
62+
public get kind(): AstKind {
63+
return AstKind.Script;
64+
}
65+
66+
/** @override */
67+
protected pushChildNodes(nodes: AstNode[]): void {
68+
if (this.body) {
69+
nodes.push(this.body);
70+
}
71+
}
72+
}
73+
74+
export class AstAndIf extends AstNode {
75+
/**
76+
* The command that executes first, and always.
77+
*/
78+
public firstCommand: AstCommand | undefined;
79+
80+
/**
81+
* The command that executes second, and only if the first one succeeds.
82+
*/
83+
public secondCommand: AstCommand | undefined;
84+
85+
public get kind(): AstKind {
86+
return AstKind.AndIf;
87+
}
88+
89+
/** @override */
90+
protected pushChildNodes(nodes: AstNode[]): void {
91+
if (this.firstCommand) {
92+
nodes.push(this.firstCommand);
93+
}
94+
if (this.secondCommand) {
95+
nodes.push(this.secondCommand);
96+
}
97+
}
98+
}
99+
100+
export class AstCommand extends AstNode {
101+
public commandPath: AstCompoundWord | undefined;
102+
public arguments: AstCompoundWord[] = [];
103+
104+
public get kind(): AstKind {
105+
return AstKind.Command;
106+
}
107+
108+
/** @override */
109+
protected pushChildNodes(nodes: AstNode[]): void {
110+
if (this.commandPath) {
111+
nodes.push(this.commandPath);
112+
}
113+
nodes.push(...this.arguments);
114+
}
115+
}
116+
117+
export class AstCompoundWord extends AstNode {
118+
public readonly parts: AstNode[] = [];
119+
120+
public get kind(): AstKind {
121+
return AstKind.CompoundWord;
122+
}
123+
124+
/** @override */
125+
protected pushChildNodes(nodes: AstNode[]): void {
126+
nodes.push(...this.parts);
127+
}
128+
}
129+
130+
export class AstVariableExpansion extends AstNode {
131+
public get kind(): AstKind {
132+
return AstKind.VariableExpansion;
133+
}
134+
135+
/** @override */
136+
protected pushChildNodes(nodes: AstNode[]): void {
137+
// no children
138+
}
139+
}
140+
141+
export class AstText extends AstNode {
142+
public token: Token | undefined;
143+
public get kind(): AstKind {
144+
return AstKind.Text;
145+
}
146+
147+
/** @override */
148+
protected pushChildNodes(nodes: AstNode[]): void {
149+
// no children
150+
}
151+
152+
/** @override */
153+
protected getDumpText(): string | undefined{
154+
if (this.token) {
155+
return this.token.text;
156+
}
157+
return undefined;
158+
}
159+
}

0 commit comments

Comments
 (0)