@@ -2,6 +2,8 @@ import type * as Model from '../data-model/types.js';
22import { MessageSyntaxError } from '../errors.js' ;
33import type * as CST from './cst-types.js' ;
44
5+ export const cst = Symbol . for ( 'CST' ) ;
6+
57/**
68 * Convert a CST message structure into its data model representation.
79 *
@@ -17,18 +19,21 @@ export function asDataModel(msg: CST.Message): Model.Message {
1719 type : 'select' ,
1820 declarations,
1921 selectors : msg . selectors . map ( sel => asExpression ( sel , false ) ) ,
20- variants : msg . variants . map ( cst => ( {
21- keys : cst . keys . map ( key =>
22- key . type === '*' ? { type : '*' } : asValue ( key )
22+ variants : msg . variants . map ( variant => ( {
23+ keys : variant . keys . map ( key =>
24+ key . type === '*' ? { type : '*' , [ cst ] : key } : asValue ( key )
2325 ) ,
24- value : asPattern ( cst . value )
25- } ) )
26+ value : asPattern ( variant . value ) ,
27+ [ cst ] : variant
28+ } ) ) ,
29+ [ cst ] : msg
2630 } ;
2731 } else {
2832 return {
2933 type : 'message' ,
3034 declarations,
31- pattern : asPattern ( msg . pattern )
35+ pattern : asPattern ( msg . pattern ) ,
36+ [ cst ] : msg
3237 } ;
3338 }
3439}
@@ -44,131 +49,138 @@ function asDeclaration(decl: CST.Declaration): Model.Declaration {
4449 return {
4550 type : 'input' ,
4651 name : value . arg . name ,
47- value : value as Model . Expression < Model . VariableRef >
52+ value : value as Model . Expression < Model . VariableRef > ,
53+ [ cst ] : decl
4854 } ;
4955 }
5056 case 'local' :
5157 return {
5258 type : 'local' ,
5359 name : asValue ( decl . target ) . name ,
54- value : asExpression ( decl . value , false )
60+ value : asExpression ( decl . value , false ) ,
61+ [ cst ] : decl
5562 } ;
5663 default :
5764 return {
5865 type : 'unsupported-statement' ,
5966 keyword : ( decl . keyword ?. value ?? '' ) . substring ( 1 ) ,
6067 body : decl . body ?. value || undefined ,
61- expressions : decl . values ?. map ( dv => asExpression ( dv , true ) ) ?? [ ]
68+ expressions : decl . values ?. map ( dv => asExpression ( dv , true ) ) ?? [ ] ,
69+ [ cst ] : decl
6270 } ;
6371 }
6472}
6573
66- function asPattern ( cst : CST . Pattern ) : Model . Pattern {
67- const body : Model . Pattern [ 'body' ] = cst . body . map ( el =>
74+ function asPattern ( pattern : CST . Pattern ) : Model . Pattern {
75+ const body : Model . Pattern [ 'body' ] = pattern . body . map ( el =>
6876 el . type === 'text' ? el . value : asExpression ( el , true )
6977 ) ;
7078 return { body } ;
7179}
7280
7381function asExpression (
74- cst : CST . Expression | CST . Junk ,
82+ exp : CST . Expression | CST . Junk ,
7583 allowMarkup : false
7684) : Model . Expression ;
7785function asExpression (
78- cst : CST . Expression | CST . Junk ,
86+ exp : CST . Expression | CST . Junk ,
7987 allowMarkup : true
8088) : Model . Expression | Model . Markup ;
8189function asExpression (
82- cst : CST . Expression | CST . Junk ,
90+ exp : CST . Expression | CST . Junk ,
8391 allowMarkup : boolean
8492) : Model . Expression | Model . Markup {
85- if ( cst . type === 'expression' ) {
86- if ( allowMarkup && cst . markup ) {
87- const cm = cst . markup ;
93+ if ( exp . type === 'expression' ) {
94+ if ( allowMarkup && exp . markup ) {
95+ const cm = exp . markup ;
8896 const name = asName ( cm . name ) ;
8997 if ( cm . type === 'markup-close' ) {
90- return { type : 'markup' , kind : 'close' , name } ;
98+ return { type : 'markup' , kind : 'close' , name, [ cst ] : exp } ;
9199 }
92100 const markup : Model . MarkupOpen | Model . MarkupStandalone = {
93101 type : 'markup' ,
94102 kind : cm . close ? 'standalone' : 'open' ,
95- name
103+ name,
104+ [ cst ] : exp
96105 } ;
97106 if ( cm . options . length > 0 ) markup . options = cm . options . map ( asOption ) ;
98107 return markup ;
99108 }
100109
101- const arg = cst . arg ? asValue ( cst . arg ) : undefined ;
110+ const arg = exp . arg ? asValue ( exp . arg ) : undefined ;
102111 let annotation :
103112 | Model . FunctionAnnotation
104113 | Model . UnsupportedAnnotation
105114 | undefined ;
106115
107- const ca = cst . annotation ;
116+ const ca = exp . annotation ;
108117 if ( ca ) {
109118 switch ( ca . type ) {
110119 case 'function' :
111- annotation = { type : 'function' , name : asName ( ca . name ) } ;
120+ annotation = { type : 'function' , name : asName ( ca . name ) , [ cst ] : ca } ;
112121 if ( ca . options . length > 0 ) {
113122 annotation . options = ca . options . map ( asOption ) ;
114123 }
124+
115125 break ;
116126 case 'reserved-annotation' :
117127 annotation = {
118128 type : 'unsupported-annotation' ,
119129 sigil : ca . sigil ,
120- source : ca . source . value
130+ source : ca . source . value ,
131+ [ cst ] : ca
121132 } ;
122133 break ;
123134 default :
124- throw new MessageSyntaxError ( 'parse-error' , cst . start , cst . end ) ;
135+ throw new MessageSyntaxError ( 'parse-error' , exp . start , exp . end ) ;
125136 }
126137 }
127138 if ( arg ) {
128139 return annotation
129- ? { type : 'expression' , arg, annotation }
130- : { type : 'expression' , arg } ;
140+ ? { type : 'expression' , arg, annotation, [ cst ] : exp }
141+ : { type : 'expression' , arg, [ cst ] : exp } ;
131142 } else if ( annotation ) {
132- return { type : 'expression' , annotation } ;
143+ return { type : 'expression' , annotation, [ cst ] : exp } ;
133144 }
134145 }
135- throw new MessageSyntaxError ( 'parse-error' , cst . start , cst . end ) ;
146+ throw new MessageSyntaxError ( 'parse-error' , exp . start , exp . end ) ;
136147}
137148
138- const asOption = ( cst : CST . Option ) : Model . Option => ( {
139- name : asName ( cst . name ) ,
140- value : asValue ( cst . value )
149+ const asOption = ( option : CST . Option ) : Model . Option => ( {
150+ name : asName ( option . name ) ,
151+ value : asValue ( option . value ) ,
152+ [ cst ] : option
141153} ) ;
142154
143- function asName ( cst : CST . Identifier ) : string {
144- switch ( cst . length ) {
155+ function asName ( id : CST . Identifier ) : string {
156+ switch ( id . length ) {
145157 case 1 :
146- return cst [ 0 ] . value ;
158+ return id [ 0 ] . value ;
147159 case 3 :
148- return `${ cst [ 0 ] . value } :${ cst [ 2 ] . value } ` ;
160+ return `${ id [ 0 ] . value } :${ id [ 2 ] . value } ` ;
149161 default :
150162 throw new MessageSyntaxError (
151163 'parse-error' ,
152- cst [ 0 ] ?. start ?? - 1 ,
153- cst . at ( - 1 ) ?. end ?? - 1
164+ id [ 0 ] ?. start ?? - 1 ,
165+ id . at ( - 1 ) ?. end ?? - 1
154166 ) ;
155167 }
156168}
157169
158- function asValue ( cst : CST . Literal | CST . Junk ) : Model . Literal ;
159- function asValue ( cst : CST . VariableRef | CST . Junk ) : Model . VariableRef ;
170+ function asValue ( value : CST . Literal | CST . Junk ) : Model . Literal ;
171+ function asValue ( value : CST . VariableRef | CST . Junk ) : Model . VariableRef ;
160172function asValue (
161- cst : CST . Literal | CST . VariableRef | CST . Junk
173+ value : CST . Literal | CST . VariableRef | CST . Junk
162174) : Model . Literal | Model . VariableRef ;
163175function asValue (
164- cst : CST . Literal | CST . VariableRef | CST . Junk
176+ value : CST . Literal | CST . VariableRef | CST . Junk
165177) : Model . Literal | Model . VariableRef {
166- switch ( cst . type ) {
178+ switch ( value . type ) {
167179 case 'literal' :
168- return { type : 'literal' , value : cst . value } ;
180+ return { type : 'literal' , value : value . value , [ cst ] : value } ;
169181 case 'variable' :
170- return { type : 'variable' , name : cst . name } ;
182+ return { type : 'variable' , name : value . name , [ cst ] : value } ;
171183 default :
172- throw new MessageSyntaxError ( 'parse-error' , cst . start , cst . end ) ;
184+ throw new MessageSyntaxError ( 'parse-error' , value . start , value . end ) ;
173185 }
174186}
0 commit comments