1
+ use std:: io:: Write ;
1
2
use std:: { fs, path:: PathBuf } ;
2
3
3
4
pub mod codegen;
@@ -47,17 +48,23 @@ fn to_lower_snake_case(s: &str) -> String {
47
48
buf
48
49
}
49
50
50
- fn print_schema ( grammar : & AstSrc , super_types : BTreeMap < String , BTreeSet < String > > ) {
51
+ fn write_schema (
52
+ grammar : & AstSrc ,
53
+ super_types : BTreeMap < String , BTreeSet < String > > ,
54
+ ) -> std:: io:: Result < String > {
55
+ let mut buf: Vec < u8 > = Vec :: new ( ) ;
56
+ writeln ! ( buf, "from .prelude import *\n " ) ?;
57
+
51
58
for node in & grammar. enums {
52
59
let super_classses = if let Some ( cls) = super_types. get ( & node. name ) {
53
60
let super_classes: Vec < String > = cls. iter ( ) . map ( |x| class_name ( x) ) . collect ( ) ;
54
61
super_classes. join ( "," )
55
62
} else {
56
63
"AstNode" . to_owned ( )
57
64
} ;
58
- println ! ( "class {}({}):" , class_name( & node. name) , super_classses) ;
59
- println ! ( " pass" ) ;
60
- println ! ( "" ) ;
65
+ writeln ! ( buf , "class {}({}):" , class_name( & node. name) , super_classses) ? ;
66
+ writeln ! ( buf , " pass" ) ? ;
67
+ writeln ! ( buf , "" ) ? ;
61
68
}
62
69
for node in & grammar. nodes {
63
70
let super_classses = if let Some ( cls) = super_types. get ( & node. name ) {
@@ -66,7 +73,7 @@ fn print_schema(grammar: &AstSrc, super_types: BTreeMap<String, BTreeSet<String>
66
73
} else {
67
74
"AstNode" . to_owned ( )
68
75
} ;
69
- println ! ( "class {}({}):" , class_name( & node. name) , super_classses) ;
76
+ writeln ! ( buf , "class {}({}):" , class_name( & node. name) , super_classses) ? ;
70
77
let mut empty = true ;
71
78
for field in get_fields ( node) {
72
79
if field. tp == "SyntaxToken" {
@@ -75,31 +82,34 @@ fn print_schema(grammar: &AstSrc, super_types: BTreeMap<String, BTreeSet<String>
75
82
76
83
empty = false ;
77
84
if field. tp == "string" {
78
- println ! (
85
+ writeln ! (
86
+ buf,
79
87
" {}: optional[string]" ,
80
88
property_name( & node. name, & field. name) ,
81
- ) ;
89
+ ) ? ;
82
90
} else {
83
91
let list = field. is_many ;
84
92
let ( o, c) = if list {
85
93
( "list[" , "]" )
86
94
} else {
87
95
( "optional[" , "]" )
88
96
} ;
89
- println ! (
97
+ writeln ! (
98
+ buf,
90
99
" {}: {}\" {}\" {} | child" ,
91
100
property_name( & node. name, & field. name) ,
92
101
o,
93
102
class_name( & field. tp) ,
94
103
c
95
- ) ;
104
+ ) ? ;
96
105
} ;
97
106
}
98
107
if empty {
99
- println ! ( " pass" ) ;
108
+ writeln ! ( buf , " pass" ) ? ;
100
109
}
101
- println ! ( "" ) ;
110
+ writeln ! ( buf , "" ) ? ;
102
111
}
112
+ Ok ( String :: from_utf8_lossy ( & buf) . to_string ( ) )
103
113
}
104
114
105
115
struct FieldInfo {
@@ -390,40 +400,45 @@ fn get_fields(node: &AstNodeSrc) -> Vec<FieldInfo> {
390
400
result
391
401
}
392
402
393
- fn print_extractor ( grammar : & AstSrc ) {
403
+ fn write_extractor ( grammar : & AstSrc ) -> std:: io:: Result < String > {
404
+ let mut buf: Vec < u8 > = Vec :: new ( ) ;
405
+
394
406
for node in & grammar. enums {
395
407
let type_name = & node. name ;
396
408
let class_name = class_name ( & node. name ) ;
397
409
398
- println ! (
410
+ writeln ! (
411
+ buf,
399
412
" fn emit_{}(&mut self, node: ast::{}) -> Label<generated::{}> {{" ,
400
413
to_lower_snake_case( type_name) ,
401
414
type_name,
402
415
class_name
403
- ) ;
404
- println ! ( " match node {{" ) ;
416
+ ) ? ;
417
+ writeln ! ( buf , " match node {{" ) ? ;
405
418
for variant in & node. variants {
406
- println ! (
419
+ writeln ! (
420
+ buf,
407
421
" ast::{}::{}(inner) => self.emit_{}(inner).into()," ,
408
422
type_name,
409
423
variant,
410
424
to_lower_snake_case( variant)
411
- ) ;
425
+ ) ? ;
412
426
}
413
- println ! ( " }}" ) ;
414
- println ! ( " }}\n " ) ;
427
+ writeln ! ( buf , " }}" ) ? ;
428
+ writeln ! ( buf , " }}\n " ) ? ;
415
429
}
416
430
417
431
for node in & grammar. nodes {
418
432
let type_name = & node. name ;
419
433
let class_name = class_name ( & node. name ) ;
420
434
421
- println ! (
435
+ writeln ! (
436
+ buf,
422
437
" fn emit_{}(&mut self, node: ast::{}) -> Label<generated::{}> {{" ,
423
438
to_lower_snake_case( type_name) ,
424
439
type_name,
425
440
class_name
426
- ) ;
441
+ ) ? ;
427
442
for field in get_fields ( & node) {
428
443
if & field. tp == "SyntaxToken" {
429
444
continue ;
@@ -433,45 +448,53 @@ fn print_extractor(grammar: &AstSrc) {
433
448
let struct_field_name = & field. name ;
434
449
let class_field_name = property_name ( & node. name , & field. name ) ;
435
450
if field. tp == "string" {
436
- println ! ( " let {} = node.try_get_text();" , class_field_name, ) ;
451
+ writeln ! (
452
+ buf,
453
+ " let {} = node.try_get_text();" ,
454
+ class_field_name,
455
+ ) ?;
437
456
} else if field. is_many {
438
- println ! (
457
+ writeln ! (
458
+ buf,
439
459
" let {} = node.{}().map(|x| self.emit_{}(x)).collect();" ,
440
460
class_field_name,
441
461
struct_field_name,
442
462
to_lower_snake_case( type_name)
443
- ) ;
463
+ ) ? ;
444
464
} else {
445
- println ! (
465
+ writeln ! (
466
+ buf,
446
467
" let {} = node.{}().map(|x| self.emit_{}(x));" ,
447
468
class_field_name,
448
469
struct_field_name,
449
470
to_lower_snake_case( type_name)
450
- ) ;
471
+ ) ? ;
451
472
}
452
473
}
453
- println ! (
474
+ writeln ! (
475
+ buf,
454
476
" let label = self.trap.emit(generated::{} {{" ,
455
477
class_name
456
- ) ;
457
- println ! ( " id: TrapId::Star," ) ;
478
+ ) ? ;
479
+ writeln ! ( buf , " id: TrapId::Star," ) ? ;
458
480
for field in get_fields ( & node) {
459
481
if field. tp == "SyntaxToken" {
460
482
continue ;
461
483
}
462
484
463
485
let class_field_name: String = property_name ( & node. name , & field. name ) ;
464
- println ! ( " {}," , class_field_name) ;
486
+ writeln ! ( buf , " {}," , class_field_name) ? ;
465
487
}
466
- println ! ( " }});" ) ;
467
- println ! ( " self.emit_location(label, node);" ) ;
468
- println ! ( " label" ) ;
488
+ writeln ! ( buf , " }});" ) ? ;
489
+ writeln ! ( buf , " self.emit_location(label, node);" ) ? ;
490
+ writeln ! ( buf , " label" ) ? ;
469
491
470
- println ! ( " }}\n " ) ;
492
+ writeln ! ( buf , " }}\n " ) ? ;
471
493
}
494
+ Ok ( String :: from_utf8_lossy ( & buf) . into_owned ( ) )
472
495
}
473
496
474
- fn main ( ) {
497
+ fn main ( ) -> std :: io :: Result < ( ) > {
475
498
let grammar: Grammar = fs:: read_to_string ( project_root ( ) . join ( "generate-schema/rust.ungram" ) )
476
499
. unwrap ( )
477
500
. parse ( )
@@ -498,6 +521,15 @@ fn main() {
498
521
let super_class_y = super_types. get ( & y. name ) . into_iter ( ) . flatten ( ) . max ( ) ;
499
522
super_class_x. cmp ( & super_class_y) . then ( x. name . cmp ( & y. name ) )
500
523
} ) ;
501
- //print_schema(&grammar, super_types);
502
- print_extractor ( & grammar) ;
524
+ let schema = write_schema ( & grammar, super_types) ?;
525
+ let schema_path = PathBuf :: from ( "../schema/ast.py" ) ;
526
+ let extractor = write_extractor ( & grammar) ?;
527
+ print ! ( "{}" , extractor) ;
528
+ codegen:: ensure_file_contents (
529
+ crate :: flags:: CodegenType :: Grammar ,
530
+ & schema_path,
531
+ & schema,
532
+ false ,
533
+ ) ;
534
+ Ok ( ( ) )
503
535
}
0 commit comments