44import { Token } from './Tokenizer' ;
55
66export enum AstKind {
7+ None ,
78 Script ,
89 AndIf ,
910 Command ,
@@ -15,8 +16,8 @@ export enum AstKind {
1516/**
1617 * Base class for all AST nodes.
1718 */
18- export abstract class AstNode {
19- public abstract get kind ( ) : AstKind ;
19+ export abstract class AstBaseNode {
20+ public readonly kind : AstKind = AstKind . None ;
2021
2122 /**
2223 * Returns a diagnostic dump of the tree, showing the prefix/suffix/separator for
@@ -30,7 +31,7 @@ export abstract class AstNode {
3031 result += '=' + JSON . stringify ( dumpText ) ;
3132 }
3233
33- const childNodes : AstNode [ ] = this . getChildNodes ( ) ;
34+ const childNodes : AstBaseNode [ ] = this . getChildNodes ( ) ;
3435 if ( childNodes . length === 0 ) {
3536 result += '\n' ;
3637 } else {
@@ -43,35 +44,41 @@ export abstract class AstNode {
4344 return result ;
4445 }
4546
46- public getChildNodes ( ) : AstNode [ ] {
47- const nodes : AstNode [ ] = [ ] ;
47+ public getChildNodes ( ) : AstBaseNode [ ] {
48+ const nodes : AstBaseNode [ ] = [ ] ;
4849 this . collectChildNodesInto ( nodes ) ;
4950 return nodes ;
5051 }
5152
52- protected abstract collectChildNodesInto ( nodes : AstNode [ ] ) : void ;
53+ protected abstract collectChildNodesInto ( nodes : AstBaseNode [ ] ) : void ;
5354
5455 protected getDumpText ( ) : string | undefined {
5556 return undefined ;
5657 }
5758}
5859
59- export class AstScript extends AstNode {
60- public body : AstNode | undefined ;
60+ /**
61+ * Represents a complete script that can be executed.
62+ */
63+ export class AstScript extends AstBaseNode {
64+ public readonly kind : AstKind . Script = AstKind . Script ;
6165
62- public get kind ( ) : AstKind {
63- return AstKind . Script ;
64- }
66+ public body : AstNode | undefined ;
6567
6668 /** @override */
67- protected collectChildNodesInto ( nodes : AstNode [ ] ) : void {
69+ protected collectChildNodesInto ( nodes : AstBaseNode [ ] ) : void {
6870 if ( this . body ) {
6971 nodes . push ( this . body ) ;
7072 }
7173 }
7274}
7375
74- export class AstAndIf extends AstNode {
76+ /**
77+ * Represents the "&&" operator, which is used to join two individual commands.
78+ */
79+ export class AstAndIf extends AstBaseNode {
80+ public readonly kind : AstKind . AndIf = AstKind . AndIf ;
81+
7582 /**
7683 * The command that executes first, and always.
7784 */
@@ -82,12 +89,8 @@ export class AstAndIf extends AstNode {
8289 */
8390 public secondCommand : AstCommand | undefined ;
8491
85- public get kind ( ) : AstKind {
86- return AstKind . AndIf ;
87- }
88-
8992 /** @override */
90- protected collectChildNodesInto ( nodes : AstNode [ ] ) : void {
93+ protected collectChildNodesInto ( nodes : AstBaseNode [ ] ) : void {
9194 if ( this . firstCommand ) {
9295 nodes . push ( this . firstCommand ) ;
9396 }
@@ -97,55 +100,60 @@ export class AstAndIf extends AstNode {
97100 }
98101}
99102
100- export class AstCommand extends AstNode {
103+ /**
104+ * Represents a command. For example, the name of an executable to be started.
105+ */
106+ export class AstCommand extends AstBaseNode {
107+ public readonly kind : AstKind . Command = AstKind . Command ;
108+
101109 public commandPath : AstCompoundWord | undefined ;
102110 public arguments : AstCompoundWord [ ] = [ ] ;
103111
104- public get kind ( ) : AstKind {
105- return AstKind . Command ;
106- }
107-
108112 /** @override */
109- protected collectChildNodesInto ( nodes : AstNode [ ] ) : void {
113+ protected collectChildNodesInto ( nodes : AstBaseNode [ ] ) : void {
110114 if ( this . commandPath ) {
111115 nodes . push ( this . commandPath ) ;
112116 }
113117 nodes . push ( ...this . arguments ) ;
114118 }
115119}
116120
117- export class AstCompoundWord extends AstNode {
118- public readonly parts : AstNode [ ] = [ ] ;
121+ /**
122+ * Represents a compound word, e.g. "--the-thing" or "./the/thing".
123+ */
124+ export class AstCompoundWord extends AstBaseNode {
125+ public readonly kind : AstKind . CompoundWord = AstKind . CompoundWord ;
119126
120- public get kind ( ) : AstKind {
121- return AstKind . CompoundWord ;
122- }
127+ public readonly parts : AstBaseNode [ ] = [ ] ;
123128
124129 /** @override */
125- protected collectChildNodesInto ( nodes : AstNode [ ] ) : void {
130+ protected collectChildNodesInto ( nodes : AstBaseNode [ ] ) : void {
126131 nodes . push ( ...this . parts ) ;
127132 }
128133}
129134
130- export class AstVariableExpansion extends AstNode {
131- public get kind ( ) : AstKind {
132- return AstKind . VariableExpansion ;
133- }
135+ /**
136+ * Represents an environment variable expansion expression, e.g. "${VARIABLE}"
137+ */
138+ export class AstVariableExpansion extends AstBaseNode {
139+ public readonly kind : AstKind . VariableExpansion = AstKind . VariableExpansion ;
134140
135141 /** @override */
136- protected collectChildNodesInto ( nodes : AstNode [ ] ) : void {
142+ protected collectChildNodesInto ( nodes : AstBaseNode [ ] ) : void {
137143 // no children
138144 }
139145}
140146
141- export class AstText extends AstNode {
147+ /**
148+ * Represents some plain text.
149+ */
150+ export class AstText extends AstBaseNode {
151+ public readonly kind : AstKind . Text = AstKind . Text ;
152+
142153 public token : Token | undefined ;
143- public get kind ( ) : AstKind {
144- return AstKind . Text ;
145- }
146154
147155 /** @override */
148- protected collectChildNodesInto ( nodes : AstNode [ ] ) : void {
156+ protected collectChildNodesInto ( nodes : AstBaseNode [ ] ) : void {
149157 // no children
150158 }
151159
@@ -157,3 +165,5 @@ export class AstText extends AstNode {
157165 return undefined ;
158166 }
159167}
168+
169+ export type AstNode = AstScript | AstAndIf | AstCommand | AstCompoundWord | AstVariableExpansion | AstText ;
0 commit comments