1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
// Copyright (C) 2019-2020 Aleo Systems Inc.
// This file is part of the Leo library.

// The Leo library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// The Leo library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.

//! The pest abstract syntax tree (ast) for a Leo program.
//!
//! This module contains the [`Grammar`] type, a wrapper around the [`File`] type in this module.
//! The [`Grammar`] type is the datatype generated by the pest parser using grammar from `leo.pest`.
//! The [`Grammar`] type is intended to be parsed into a [`Ast`]. It should not be parsed by
//! any other pass of the compiler.

#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate pest_derive;
#[macro_use]
extern crate thiserror;

pub mod ast;

pub mod access;
pub mod annotations;
pub mod circuits;
pub mod common;
pub mod console;
pub mod definitions;
pub mod expressions;
pub mod files;
pub mod functions;
pub mod imports;
pub mod operations;
pub mod statements;
pub mod types;
pub mod values;

pub mod errors;
pub use errors::*;

pub(crate) mod span;
pub(crate) use span::*;

use from_pest::FromPest;
use std::{fs, path::Path};

/// The pest abstract syntax tree (ast) for a Leo program.
///
/// The [`Grammar`] type represents a Leo program as a series of recursive data types.
/// These data types form a tree that begins from a [`File`] type root.
///
/// A new [`Grammar`] type can be created from a `*.leo` file at a [`Path`].
/// A [`Grammar`] type can be used to create a new [`Ast`] type.
pub struct Grammar<'ast> {
    ast: files::File<'ast>,
}

impl<'ast> Grammar<'ast> {
    /// Creates a new abstract syntax tree given the file path.
    pub fn new(file_path: &'ast Path, program_string: &'ast str) -> Result<Self, ParserError> {
        // TODO (howardwu): Turn this check back on after fixing the testing module.
        // assert_eq!(program_string, fs::read_to_string(file_path).map_err(|_| ParserError::FileReadError(file_path.clone()))?);

        // Parse the file using leo.pest
        let file = &mut ast::parse(&program_string)
            .map_err(|error| ParserError::from(error.with_path(file_path.to_str().unwrap())))?;

        // Builds the abstract syntax tree using pest derivation.
        let ast = files::File::<'ast>::from_pest(file).map_err(|_| ParserError::SyntaxTreeError)?;
        tracing::debug!("{:#?}", ast);

        Ok(Self { ast })
    }

    // TODO (howardwu): Remove this in favor of a dedicated file loader to verify checksums
    //  and maintain a global cache of program strings during the compilation process.
    /// Loads the Leo code as a string from the given file path.
    pub fn load_file(file_path: &'ast Path) -> Result<String, ParserError> {
        Ok(fs::read_to_string(file_path).map_err(|_| ParserError::FileReadError(file_path.to_owned()))?)
    }

    /// Returns a reference to the inner abstract syntax tree representation.
    pub fn as_repr(&self) -> &files::File<'ast> {
        &self.ast
    }

    /// Serializes the abstract syntax tree into a JSON string.
    pub fn to_json_string(&self) -> Result<String, ParserError> {
        Ok(serde_json::to_string_pretty(&self.ast)?)
    }
}