1515# specific language governing permissions and limitations
1616# under the License.
1717
18- """CLI entry point for the FDL compiler."""
18+ """CLI entry point for the Fory IDL compiler."""
1919
2020import argparse
2121import sys
2222from pathlib import Path
2323from typing import Dict , List , Optional , Set
2424
25- from fory_compiler .parser .lexer import Lexer , LexerError
26- from fory_compiler .parser .parser import Parser , ParseError
27- from fory_compiler .parser .ast import Schema
25+ from fory_compiler .frontend .base import FrontendError
26+ from fory_compiler .frontend .fdl import FDLFrontend
27+ from fory_compiler .frontend .proto import ProtoFrontend
28+ from fory_compiler .ir .ast import Schema
29+ from fory_compiler .ir .emitter import FDLEmitter
2830from fory_compiler .generators .base import GeneratorOptions
2931from fory_compiler .generators import GENERATORS
3032
@@ -35,13 +37,19 @@ class ImportError(Exception):
3537 pass
3638
3739
38- def parse_fdl_file (file_path : Path ) -> Schema :
39- """Parse a single FDL file and return its schema."""
40- source = file_path .read_text ()
41- lexer = Lexer (source , str (file_path ))
42- tokens = lexer .tokenize ()
43- parser = Parser (tokens )
44- return parser .parse ()
40+ def get_frontend (file_path : Path ):
41+ """Select the correct frontend for a file."""
42+ frontends = [FDLFrontend (), ProtoFrontend ()]
43+ for frontend in frontends :
44+ if frontend .supports_file (file_path ):
45+ return frontend
46+ raise ValueError (f"Unsupported file extension: { file_path .suffix } " )
47+
48+
49+ def parse_idl_file (file_path : Path ) -> Schema :
50+ """Parse a single IDL file and return its schema."""
51+ frontend = get_frontend (file_path )
52+ return frontend .parse_file (file_path )
4553
4654
4755def resolve_import_path (
@@ -117,7 +125,7 @@ def resolve_imports(
117125 visited .add (file_path )
118126
119127 # Parse the file
120- schema = parse_fdl_file (file_path )
128+ schema = parse_idl_file (file_path )
121129
122130 # Process imports
123131 imported_enums = []
@@ -152,6 +160,9 @@ def resolve_imports(
152160 imports = schema .imports ,
153161 enums = imported_enums + schema .enums ,
154162 messages = imported_messages + schema .messages ,
163+ options = schema .options ,
164+ source_file = schema .source_file ,
165+ source_format = schema .source_format ,
155166 )
156167
157168 cache [file_path ] = merged_schema
@@ -162,23 +173,23 @@ def parse_args(args: Optional[List[str]] = None) -> argparse.Namespace:
162173 """Parse command line arguments."""
163174 parser = argparse .ArgumentParser (
164175 prog = "fory" ,
165- description = "FDL ( Fory Definition Language) compiler" ,
176+ description = "Fory IDL compiler" ,
166177 )
167178
168179 subparsers = parser .add_subparsers (dest = "command" , help = "Available commands" )
169180
170181 # compile command
171182 compile_parser = subparsers .add_parser (
172183 "compile" ,
173- help = "Compile FDL files to language-specific code" ,
184+ help = "Compile IDL files (.fdl, .proto) to language-specific code" ,
174185 )
175186
176187 compile_parser .add_argument (
177188 "files" ,
178189 nargs = "+" ,
179190 type = Path ,
180191 metavar = "FILE" ,
181- help = "FDL files to compile" ,
192+ help = "IDL files to compile" ,
182193 )
183194
184195 compile_parser .add_argument (
@@ -264,6 +275,19 @@ def parse_args(args: Optional[List[str]] = None) -> argparse.Namespace:
264275 help = "Go nested type naming style: camelcase or underscore (default)" ,
265276 )
266277
278+ compile_parser .add_argument (
279+ "--emit-fdl" ,
280+ action = "store_true" ,
281+ help = "Emit translated FDL (for non-FDL inputs) for debugging" ,
282+ )
283+
284+ compile_parser .add_argument (
285+ "--emit-fdl-path" ,
286+ type = Path ,
287+ default = None ,
288+ help = "Write translated FDL to this path (file or directory)" ,
289+ )
290+
267291 return parser .parse_args (args )
268292
269293
@@ -290,11 +314,13 @@ def compile_file(
290314 package_override : Optional [str ] = None ,
291315 import_paths : Optional [List [Path ]] = None ,
292316 go_nested_type_style : Optional [str ] = None ,
317+ emit_fdl : bool = False ,
318+ emit_fdl_path : Optional [Path ] = None ,
293319) -> bool :
294- """Compile a single FDL file with import resolution.
320+ """Compile a single IDL file with import resolution.
295321
296322 Args:
297- file_path: Path to the FDL file
323+ file_path: Path to the IDL file
298324 lang_output_dirs: Dictionary mapping language name to output directory
299325 package_override: Optional package name override
300326 import_paths: List of import search paths
@@ -307,7 +333,7 @@ def compile_file(
307333 except OSError as e :
308334 print (f"Error reading { file_path } : { e } " , file = sys .stderr )
309335 return False
310- except (LexerError , ParseError ) as e :
336+ except (FrontendError , ValueError ) as e :
311337 print (f"Error: { e } " , file = sys .stderr )
312338 return False
313339 except ImportError as e :
@@ -318,6 +344,24 @@ def compile_file(
318344 if schema .imports :
319345 print (f" Resolved { len (schema .imports )} import(s)" )
320346
347+ if emit_fdl :
348+ emitter = FDLEmitter (schema )
349+ fdl_content = emitter .emit ()
350+ if emit_fdl_path :
351+ target = emit_fdl_path
352+ if target .exists () and target .is_dir ():
353+ target = target / f"{ file_path .stem } .fdl"
354+ elif str (target ).endswith ("/" ) or str (target ).endswith ("\\ " ):
355+ target .mkdir (parents = True , exist_ok = True )
356+ target = target / f"{ file_path .stem } .fdl"
357+ target .parent .mkdir (parents = True , exist_ok = True )
358+ target .write_text (fdl_content )
359+ print (f" Emitted FDL: { target } " )
360+ else :
361+ print ("=== Translated FDL ===" )
362+ print (fdl_content .rstrip ())
363+ print ("======================" )
364+
321365 # Validate merged schema
322366 errors = schema .validate ()
323367 if errors :
@@ -417,6 +461,8 @@ def cmd_compile(args: argparse.Namespace) -> int:
417461 args .package ,
418462 import_paths ,
419463 args .go_nested_type_style ,
464+ args .emit_fdl ,
465+ args .emit_fdl_path ,
420466 ):
421467 success = False
422468
0 commit comments