1+ use std:: io:: Write ;
12use std:: { fs, path:: PathBuf } ;
23
34pub mod codegen;
@@ -47,17 +48,23 @@ fn to_lower_snake_case(s: &str) -> String {
4748 buf
4849}
4950
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+
5158 for node in & grammar. enums {
5259 let super_classses = if let Some ( cls) = super_types. get ( & node. name ) {
5360 let super_classes: Vec < String > = cls. iter ( ) . map ( |x| class_name ( x) ) . collect ( ) ;
5461 super_classes. join ( "," )
5562 } else {
5663 "AstNode" . to_owned ( )
5764 } ;
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 , "" ) ? ;
6168 }
6269 for node in & grammar. nodes {
6370 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>
6673 } else {
6774 "AstNode" . to_owned ( )
6875 } ;
69- println ! ( "class {}({}):" , class_name( & node. name) , super_classses) ;
76+ writeln ! ( buf , "class {}({}):" , class_name( & node. name) , super_classses) ? ;
7077 let mut empty = true ;
7178 for field in get_fields ( node) {
7279 if field. tp == "SyntaxToken" {
@@ -75,31 +82,34 @@ fn print_schema(grammar: &AstSrc, super_types: BTreeMap<String, BTreeSet<String>
7582
7683 empty = false ;
7784 if field. tp == "string" {
78- println ! (
85+ writeln ! (
86+ buf,
7987 " {}: optional[string]" ,
8088 property_name( & node. name, & field. name) ,
81- ) ;
89+ ) ? ;
8290 } else {
8391 let list = field. is_many ;
8492 let ( o, c) = if list {
8593 ( "list[" , "]" )
8694 } else {
8795 ( "optional[" , "]" )
8896 } ;
89- println ! (
97+ writeln ! (
98+ buf,
9099 " {}: {}\" {}\" {} | child" ,
91100 property_name( & node. name, & field. name) ,
92101 o,
93102 class_name( & field. tp) ,
94103 c
95- ) ;
104+ ) ? ;
96105 } ;
97106 }
98107 if empty {
99- println ! ( " pass" ) ;
108+ writeln ! ( buf , " pass" ) ? ;
100109 }
101- println ! ( "" ) ;
110+ writeln ! ( buf , "" ) ? ;
102111 }
112+ Ok ( String :: from_utf8_lossy ( & buf) . to_string ( ) )
103113}
104114
105115struct FieldInfo {
@@ -390,40 +400,45 @@ fn get_fields(node: &AstNodeSrc) -> Vec<FieldInfo> {
390400 result
391401}
392402
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+
394406 for node in & grammar. enums {
395407 let type_name = & node. name ;
396408 let class_name = class_name ( & node. name ) ;
397409
398- println ! (
410+ writeln ! (
411+ buf,
399412 " fn emit_{}(&mut self, node: ast::{}) -> Label<generated::{}> {{" ,
400413 to_lower_snake_case( type_name) ,
401414 type_name,
402415 class_name
403- ) ;
404- println ! ( " match node {{" ) ;
416+ ) ? ;
417+ writeln ! ( buf , " match node {{" ) ? ;
405418 for variant in & node. variants {
406- println ! (
419+ writeln ! (
420+ buf,
407421 " ast::{}::{}(inner) => self.emit_{}(inner).into()," ,
408422 type_name,
409423 variant,
410424 to_lower_snake_case( variant)
411- ) ;
425+ ) ? ;
412426 }
413- println ! ( " }}" ) ;
414- println ! ( " }}\n " ) ;
427+ writeln ! ( buf , " }}" ) ? ;
428+ writeln ! ( buf , " }}\n " ) ? ;
415429 }
416430
417431 for node in & grammar. nodes {
418432 let type_name = & node. name ;
419433 let class_name = class_name ( & node. name ) ;
420434
421- println ! (
435+ writeln ! (
436+ buf,
422437 " fn emit_{}(&mut self, node: ast::{}) -> Label<generated::{}> {{" ,
423438 to_lower_snake_case( type_name) ,
424439 type_name,
425440 class_name
426- ) ;
441+ ) ? ;
427442 for field in get_fields ( & node) {
428443 if & field. tp == "SyntaxToken" {
429444 continue ;
@@ -433,45 +448,53 @@ fn print_extractor(grammar: &AstSrc) {
433448 let struct_field_name = & field. name ;
434449 let class_field_name = property_name ( & node. name , & field. name ) ;
435450 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+ ) ?;
437456 } else if field. is_many {
438- println ! (
457+ writeln ! (
458+ buf,
439459 " let {} = node.{}().map(|x| self.emit_{}(x)).collect();" ,
440460 class_field_name,
441461 struct_field_name,
442462 to_lower_snake_case( type_name)
443- ) ;
463+ ) ? ;
444464 } else {
445- println ! (
465+ writeln ! (
466+ buf,
446467 " let {} = node.{}().map(|x| self.emit_{}(x));" ,
447468 class_field_name,
448469 struct_field_name,
449470 to_lower_snake_case( type_name)
450- ) ;
471+ ) ? ;
451472 }
452473 }
453- println ! (
474+ writeln ! (
475+ buf,
454476 " let label = self.trap.emit(generated::{} {{" ,
455477 class_name
456- ) ;
457- println ! ( " id: TrapId::Star," ) ;
478+ ) ? ;
479+ writeln ! ( buf , " id: TrapId::Star," ) ? ;
458480 for field in get_fields ( & node) {
459481 if field. tp == "SyntaxToken" {
460482 continue ;
461483 }
462484
463485 let class_field_name: String = property_name ( & node. name , & field. name ) ;
464- println ! ( " {}," , class_field_name) ;
486+ writeln ! ( buf , " {}," , class_field_name) ? ;
465487 }
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" ) ? ;
469491
470- println ! ( " }}\n " ) ;
492+ writeln ! ( buf , " }}\n " ) ? ;
471493 }
494+ Ok ( String :: from_utf8_lossy ( & buf) . into_owned ( ) )
472495}
473496
474- fn main ( ) {
497+ fn main ( ) -> std :: io :: Result < ( ) > {
475498 let grammar: Grammar = fs:: read_to_string ( project_root ( ) . join ( "generate-schema/rust.ungram" ) )
476499 . unwrap ( )
477500 . parse ( )
@@ -498,6 +521,15 @@ fn main() {
498521 let super_class_y = super_types. get ( & y. name ) . into_iter ( ) . flatten ( ) . max ( ) ;
499522 super_class_x. cmp ( & super_class_y) . then ( x. name . cmp ( & y. name ) )
500523 } ) ;
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 ( ( ) )
503535}
0 commit comments