Adds AST JSON generator

This commit is contained in:
howardwu 2020-07-28 22:26:28 -07:00
parent 47bfd2e096
commit d3894ff546
5 changed files with 67 additions and 14 deletions

View File

@ -4,6 +4,10 @@ version = "0.1.0"
authors = ["The Aleo Team <hello@aleo.org>"] authors = ["The Aleo Team <hello@aleo.org>"]
edition = "2018" edition = "2018"
[[bin]]
name = "leo_ast"
path = "src/main.rs"
[dependencies] [dependencies]
from-pest = { version = "0.3.1" } from-pest = { version = "0.3.1" }
lazy_static = { version = "1.3.0" } lazy_static = { version = "1.3.0" }

View File

@ -11,6 +11,9 @@ pub enum ParserError {
#[error("Cannot read from the provided file path - {:?}", _0)] #[error("Cannot read from the provided file path - {:?}", _0)]
FileReadError(PathBuf), FileReadError(PathBuf),
#[error("{}", _0)]
JsonError(#[from] serde_json::error::Error),
#[error("{}", _0)] #[error("{}", _0)]
SyntaxError(#[from] SyntaxError), SyntaxError(#[from] SyntaxError),

View File

@ -32,16 +32,16 @@ use std::{fs, path::PathBuf};
pub struct LeoParser; pub struct LeoParser;
impl LeoParser { impl LeoParser {
/// Reads in the given file path into a string. /// Loads the Leo code as a string from the given file path.
pub fn load_file(file_path: &PathBuf) -> Result<String, ParserError> { pub fn load_file(file_path: &PathBuf) -> Result<String, ParserError> {
Ok(fs::read_to_string(file_path).map_err(|_| ParserError::FileReadError(file_path.clone()))?) Ok(fs::read_to_string(file_path).map_err(|_| ParserError::FileReadError(file_path.clone()))?)
} }
/// Parses the input file and constructs a syntax tree. /// Parses the Leo program string and constructs an abstract syntax tree.
pub fn parse_file<'a>(file_path: &'a PathBuf, input_file: &'a str) -> Result<files::File<'a>, ParserError> { pub fn parse_file<'a>(file_path: &'a PathBuf, program_string: &'a str) -> Result<files::File<'a>, ParserError> {
// Parse the file using leo.pest // Parse the file using leo.pest
let mut file = let mut file = ast::parse(program_string)
ast::parse(input_file).map_err(|error| ParserError::from(error.with_path(file_path.to_str().unwrap())))?; .map_err(|error| ParserError::from(error.with_path(file_path.to_str().unwrap())))?;
// Build the abstract syntax tree // Build the abstract syntax tree
let syntax_tree = files::File::from_pest(&mut file).map_err(|_| ParserError::SyntaxTreeError)?; let syntax_tree = files::File::from_pest(&mut file).map_err(|_| ParserError::SyntaxTreeError)?;
@ -50,13 +50,8 @@ impl LeoParser {
Ok(syntax_tree) Ok(syntax_tree)
} }
/// Serializes and stores a given syntax tree in the output file. /// Serializes a given abstract syntax tree into a JSON string.
pub fn store_syntax_tree<'a>(syntax_tree: files::File<'a>, output_file: &'a str) -> Result<(), ParserError> { pub fn to_json_string(syntax_tree: &files::File) -> Result<String, ParserError> {
// Serialize and store the syntax tree to the given filepath. Ok(serde_json::to_string_pretty(syntax_tree)?)
let serialized_syntax_tree = serde_json::to_string(&syntax_tree).unwrap();
println!("serialized = {}", serialized_syntax_tree);
fs::write(output_file, serialized_syntax_tree)?;
Ok(())
} }
} }

50
ast/src/main.rs Normal file
View File

@ -0,0 +1,50 @@
use leo_ast::{LeoParser, ParserError};
use std::{env, fs, path::Path};
fn to_leo_ast(filepath: &Path) -> Result<String, ParserError> {
// Loads the Leo code as a string from the given file path.
let program_filepath = filepath.to_path_buf();
let program_string = LeoParser::load_file(&program_filepath)?;
// Parses the Leo program string and constructs an abstract syntax tree.
let abstract_syntax_tree = LeoParser::parse_file(&program_filepath, &program_string)?;
// Serializes the abstract syntax tree into JSON format.
let serialized_ast = LeoParser::to_json_string(&abstract_syntax_tree)?;
Ok(serialized_ast)
}
fn main() -> Result<(), ParserError> {
// Parse the command-line arguments as strings.
let cli_arguments = env::args().collect::<Vec<String>>();
// Check that the correct number of command-line arguments were passed in.
if cli_arguments.len() < 2 || cli_arguments.len() > 3 {
eprintln!("Error - invalid number of command-line arguments");
println!("\nCommand-line usage:\n\n\tleo_ast {{input_filename}}.leo {{optional_output_filepath}}\n");
return Ok(()); // Exit innocently
}
// Create the input filepath.
let input_filepath = Path::new(&cli_arguments[1]);
// Create the serialized abstract syntax tree.
let serialized_ast = to_leo_ast(&input_filepath)?;
println!("{}", serialized_ast);
// Create the output filepath.
let output_filepath = match cli_arguments.len() == 3 {
true => format!(
"{}/{}.json",
cli_arguments[2],
input_filepath.file_stem().unwrap().to_str().unwrap()
),
false => format!("./{}.json", input_filepath.file_stem().unwrap().to_str().unwrap()),
};
// Write the serialized abstract syntax tree to the output filepath.
fs::write(Path::new(&output_filepath), serialized_ast)?;
Ok(())
}

View File

@ -94,11 +94,12 @@ impl<F: Field + PrimeField, G: GroupType<F>> Compiler<F, G> {
generate_test_constraints::<F, G>(cs, self.program, &self.imported_programs) generate_test_constraints::<F, G>(cs, self.program, &self.imported_programs)
} }
/// Loads the Leo code as a string from the given file path.
fn load_program(&mut self) -> Result<String, CompilerError> { fn load_program(&mut self) -> Result<String, CompilerError> {
// Load the program syntax tree from the file path
Ok(LeoParser::load_file(&self.main_file_path)?) Ok(LeoParser::load_file(&self.main_file_path)?)
} }
/// Parses the Leo program string, constructs a syntax tree, and generates a program.
pub fn parse_program(&mut self, program_string: &str) -> Result<(), CompilerError> { pub fn parse_program(&mut self, program_string: &str) -> Result<(), CompilerError> {
// Parse the program syntax tree // Parse the program syntax tree
let syntax_tree = LeoParser::parse_file(&self.main_file_path, program_string)?; let syntax_tree = LeoParser::parse_file(&self.main_file_path, program_string)?;