@@ -39,6 +39,7 @@ fn main() {
3939 "codegen" => cmd_codegen ( & args[ 2 ..] ) ,
4040 "sysml2" => cmd_sysml2 ( & args[ 2 ..] ) ,
4141 "extract" => cmd_sysml2_extract ( & args[ 2 ..] ) ,
42+ "generate" => cmd_sysml2_generate ( & args[ 2 ..] ) ,
4243 "lsp" => cmd_lsp ( ) ,
4344 other => {
4445 eprintln ! ( "Unknown command: {other}" ) ;
@@ -1830,6 +1831,78 @@ fn cmd_sysml2_extract(args: &[String]) {
18301831 }
18311832}
18321833
1834+ fn cmd_sysml2_generate ( args : & [ String ] ) {
1835+ let mut output_path: Option < String > = None ;
1836+ let mut files = Vec :: new ( ) ;
1837+ let mut from_rivet = false ;
1838+
1839+ let mut i = 0 ;
1840+ while i < args. len ( ) {
1841+ match args[ i] . as_str ( ) {
1842+ "--from-rivet" => {
1843+ from_rivet = true ;
1844+ }
1845+ "-o" | "--output" => {
1846+ i += 1 ;
1847+ if i < args. len ( ) {
1848+ output_path = Some ( args[ i] . clone ( ) ) ;
1849+ } else {
1850+ eprintln ! ( "-o requires a value" ) ;
1851+ process:: exit ( 1 ) ;
1852+ }
1853+ }
1854+ s if s. starts_with ( '-' ) => {
1855+ eprintln ! ( "Unknown option: {s}" ) ;
1856+ process:: exit ( 1 ) ;
1857+ }
1858+ s => files. push ( s. to_string ( ) ) ,
1859+ }
1860+ i += 1 ;
1861+ }
1862+
1863+ if !from_rivet {
1864+ eprintln ! ( "Usage: spar sysml2 generate --from-rivet <rivet-yaml-file> [-o output.sysml]" ) ;
1865+ process:: exit ( 1 ) ;
1866+ }
1867+
1868+ if files. is_empty ( ) {
1869+ eprintln ! ( "Missing rivet YAML file argument" ) ;
1870+ process:: exit ( 1 ) ;
1871+ }
1872+
1873+ // Read and parse rivet YAML
1874+ let mut all_yaml = String :: new ( ) ;
1875+ for file_path in & files {
1876+ let source = read_file ( file_path) ;
1877+ all_yaml. push_str ( & source) ;
1878+ all_yaml. push ( '\n' ) ;
1879+ }
1880+
1881+ let artifacts = spar_sysml2:: generate:: parse_rivet_yaml ( & all_yaml) ;
1882+ if artifacts. is_empty ( ) {
1883+ eprintln ! ( "No artifacts found in rivet YAML" ) ;
1884+ process:: exit ( 1 ) ;
1885+ }
1886+
1887+ let sysml = spar_sysml2:: generate:: generate_sysml2 ( & artifacts) ;
1888+
1889+ match output_path {
1890+ Some ( path) => {
1891+ fs:: write ( & path, & sysml) . unwrap_or_else ( |e| {
1892+ eprintln ! ( "Cannot write {path}: {e}" ) ;
1893+ process:: exit ( 1 ) ;
1894+ } ) ;
1895+ eprintln ! (
1896+ "Generated SysML v2 from {} artifacts → {path}" ,
1897+ artifacts. len( )
1898+ ) ;
1899+ }
1900+ None => {
1901+ print ! ( "{sysml}" ) ;
1902+ }
1903+ }
1904+ }
1905+
18331906fn cmd_sysml2 ( args : & [ String ] ) {
18341907 if args. is_empty ( ) {
18351908 eprintln ! ( "Usage: spar sysml2 <subcommand> [options] <file>" ) ;
@@ -1838,13 +1911,15 @@ fn cmd_sysml2(args: &[String]) {
18381911 eprintln ! ( " parse Parse a SysML v2 file and show the syntax tree" ) ;
18391912 eprintln ! ( " lower Lower SysML v2 to AADL" ) ;
18401913 eprintln ! ( " extract Extract requirements to rivet YAML" ) ;
1914+ eprintln ! ( " generate Generate SysML v2 from rivet YAML (--from-rivet)" ) ;
18411915 process:: exit ( 1 ) ;
18421916 }
18431917
18441918 match args[ 0 ] . as_str ( ) {
18451919 "parse" => cmd_sysml2_parse ( & args[ 1 ..] ) ,
18461920 "lower" => cmd_sysml2_lower ( & args[ 1 ..] ) ,
18471921 "extract" => cmd_sysml2_extract ( & args[ 1 ..] ) ,
1922+ "generate" => cmd_sysml2_generate ( & args[ 1 ..] ) ,
18481923 other => {
18491924 eprintln ! ( "Unknown sysml2 subcommand: {other}" ) ;
18501925 process:: exit ( 1 ) ;
0 commit comments