Enable parser support for program scope

This commit is contained in:
Pranav Gaddamadugu 2022-10-05 09:57:16 -07:00
parent bd4b7be8cf
commit 9da6d7735f
5 changed files with 69 additions and 30 deletions

View File

@ -19,7 +19,6 @@ use crate::parse_ast;
use leo_errors::{CompilerError, ParserError, ParserWarning, Result};
use leo_span::source_map::FileName;
use leo_span::symbol::with_session_globals;
use leo_span::{sym, Symbol};
use std::fs;
@ -27,9 +26,7 @@ impl ParserContext<'_> {
/// Returns a [`Program`] AST if all tokens can be consumed and represent a valid Leo program.
pub fn parse_program(&mut self) -> Result<Program> {
let mut imports = IndexMap::new();
let mut functions = IndexMap::new();
let mut structs = IndexMap::new();
let mut mappings = IndexMap::new();
let mut program_scopes = IndexMap::new();
// TODO: Condense logic
while self.has_next() {
@ -38,36 +35,16 @@ impl ParserContext<'_> {
let (id, import) = self.parse_import()?;
imports.insert(id, import);
}
// TODO: Error for circuit token
Token::Struct | Token::Record => {
let (id, struct_) = self.parse_struct()?;
structs.insert(id, struct_);
Token::Program => {
let program_scope = self.parse_program_scope()?;
program_scopes.insert((program_scope.name, program_scope.network), program_scope);
}
Token::Mapping => {
let (id, mapping) = self.parse_mapping()?;
mappings.insert(id, mapping);
}
Token::At => {
let (id, function) = self.parse_function()?;
functions.insert(id, function);
}
Token::Identifier(sym::test) => return Err(ParserError::test_function(self.token.span).into()),
Token::Function | Token::Transition => {
let (id, function) = self.parse_function()?;
functions.insert(id, function);
}
Token::Circuit => return Err(ParserError::circuit_is_deprecated(self.token.span).into()),
_ => return Err(Self::unexpected_item(&self.token).into()),
}
}
Ok(Program {
name: String::new(),
network: String::new(),
expected_input: Vec::new(),
imports,
functions,
structs,
mappings,
program_scopes,
})
}
@ -129,6 +106,59 @@ impl ParserContext<'_> {
Ok((import_name, program_ast.into_repr()))
}
/// Parsers a program scope `program foo.aleo { ... }`.
fn parse_program_scope(&mut self) -> Result<ProgramScope> {
// Parse `program` keyword.
let _start = self.expect(&Token::Program)?;
// Parse the program name.
let name = self.expect_identifier()?;
// Parse the program network.
self.expect(&Token::Dot)?;
let network = self.expect_identifier()?;
// Parse `{`.
let _open = self.expect(&Token::OpenBrace)?;
// Parse the body of the program scope.
let mut functions = IndexMap::new();
let mut structs = IndexMap::new();
let mut mappings = IndexMap::new();
while self.has_next() {
match &self.token.token {
Token::Struct | Token::Record => {
let (id, struct_) = self.parse_struct()?;
structs.insert(id, struct_);
}
Token::Mapping => {
let (id, mapping) = self.parse_mapping()?;
mappings.insert(id, mapping);
}
Token::At | Token::Function | Token::Transition => {
let (id, function) = self.parse_function()?;
functions.insert(id, function);
}
Token::Circuit => return Err(ParserError::circuit_is_deprecated(self.token.span).into()),
Token::CloseBrace => break,
_ => return Err(Self::unexpected_item(&self.token).into()),
}
}
// Parse `}`.
let _close = self.expect(&Token::CloseBrace)?;
Ok(ProgramScope {
name,
network,
functions,
structs,
mappings,
})
}
/// Returns a [`Vec<Member>`] AST node if the next tokens represent a struct member.
fn parse_struct_members(&mut self) -> Result<(Vec<Member>, Span)> {
let mut members = Vec::new();
@ -421,3 +451,5 @@ impl ParserContext<'_> {
))
}
}
use leo_span::{sym, Symbol};

View File

@ -420,6 +420,7 @@ impl Token {
"let" => Token::Let,
"leo" => Token::Leo,
"mapping" => Token::Mapping,
"program" => Token::Program,
"public" => Token::Public,
"record" => Token::Record,
"return" => Token::Return,

View File

@ -103,6 +103,7 @@ mod tests {
input
let
mut
program
return
scalar
self
@ -160,7 +161,7 @@ mod tests {
assert_eq!(
output,
r#""test" "test{}test" "test{}" "{}test" "test{" "test}" "test{test" "test}test" "te{{}}" test_ident 12345 address async bool const else false field finalize for function group i128 i64 i32 i16 i8 if in input let mut return scalar self string struct test transition true u128 u64 u32 u16 u8 console ! != && ( ) * ** + , - -> => _ . .. / : ; < <= = == > >= [ ] { { } } || ? @ // test
r#""test" "test{}test" "test{}" "{}test" "test{" "test}" "test{test" "test}test" "te{{}}" test_ident 12345 address async bool const else false field finalize for function group i128 i64 i32 i16 i8 if in input let mut program return scalar self string struct test transition true u128 u64 u32 u16 u8 console ! != && ( ) * ** + , - -> => _ . .. / : ; < <= = == > >= [ ] { { } } || ? @ // test
/* test */ // "#
);
});

View File

@ -126,6 +126,7 @@ pub enum Token {
Increment,
Let,
Mapping,
Program,
// For public inputs.
Public,
Return,
@ -170,6 +171,7 @@ pub const KEYWORD_TOKENS: &[Token] = &[
Token::Increment,
Token::Let,
Token::Mapping,
Token::Program,
Token::Public,
Token::Record,
Token::Return,
@ -222,6 +224,7 @@ impl Token {
Token::Let => sym::Let,
Token::Leo => sym::leo,
Token::Mapping => sym::mapping,
Token::Program => sym::program,
Token::Public => sym::Public,
Token::Record => sym::record,
Token::Return => sym::Return,
@ -342,9 +345,10 @@ impl fmt::Display for Token {
Increment => write!(f, "increment"),
Let => write!(f, "let"),
Mapping => write!(f, "mapping"),
SelfLower => write!(f, "self"),
Program => write!(f, "program"),
Public => write!(f, "public"),
Return => write!(f, "return"),
SelfLower => write!(f, "self"),
Static => write!(f, "static"),
Struct => write!(f, "struct"),
Transition => write!(f, "transition"),

View File

@ -218,6 +218,7 @@ symbols! {
transition,
Type: "type",
aleo,
public,
private,
owner,