From 3c39153ed5700b1064aa64b9311ce0d205c9ced7 Mon Sep 17 00:00:00 2001 From: "Sandeep.C.R" Date: Thu, 7 Sep 2023 13:56:16 +0530 Subject: [PATCH 1/2] MIR: Update parser to return an AST --- contrib/mir/src/ast.rs | 36 +++++++++++++++++ contrib/mir/src/parser.rs | 7 +++- contrib/mir/src/syntax.lalrpop | 72 +++++++++++++++++++++++----------- 3 files changed, 90 insertions(+), 25 deletions(-) create mode 100644 contrib/mir/src/ast.rs diff --git a/contrib/mir/src/ast.rs b/contrib/mir/src/ast.rs new file mode 100644 index 000000000000..4fc66b37b375 --- /dev/null +++ b/contrib/mir/src/ast.rs @@ -0,0 +1,36 @@ +/******************************************************************************/ +/* */ +/* SPDX-License-Identifier: MIT */ +/* Copyright (c) [2023] Serokell */ +/* */ +/******************************************************************************/ + +#[derive(Debug)] +pub enum Type { + Nat, + Int, +} + +#[derive(Debug)] +pub enum Value { + NumberValue(i32), +} + +pub type InstructionBlock = Vec; + +#[derive(Debug)] +pub enum Instruction { + Add, + Dip(InstructionBlock), + DipN(usize, InstructionBlock), + Drop, + DropN(usize), + Dup, + DupN(usize), + Gt, + If(InstructionBlock, InstructionBlock), + Int, + Loop(InstructionBlock), + Push(Type, Value), + Swap, +} diff --git a/contrib/mir/src/parser.rs b/contrib/mir/src/parser.rs index c43bff97a4d3..46326d930b5d 100644 --- a/contrib/mir/src/parser.rs +++ b/contrib/mir/src/parser.rs @@ -5,8 +5,11 @@ /* */ /******************************************************************************/ +use crate::ast::*; use crate::syntax; +use lalrpop_util::ParseError; +use lalrpop_util::lexer::Token; -pub fn parse(src: &str) -> bool { - Result::is_ok(&syntax::instructionBlockParser::new().parse(src)) +pub fn parse(src: &str) -> Result, &'static str>> { + syntax::instructionBlockParser::new().parse(src) } diff --git a/contrib/mir/src/syntax.lalrpop b/contrib/mir/src/syntax.lalrpop index 1acf1668528b..f04786d80e3d 100644 --- a/contrib/mir/src/syntax.lalrpop +++ b/contrib/mir/src/syntax.lalrpop @@ -7,6 +7,9 @@ #![allow(dead_code)] use std::str::FromStr; +use lalrpop_util::ParseError; + +use crate::ast::*; grammar; @@ -15,37 +18,60 @@ match { _ } -number: i32 = => i32::from_str(s).unwrap(); +number: i32 = =>? i32::from_str(s) + .map_err(|_| ParseError::User { error : "parsing of numeric literal failed." } ); + +usize: usize = { + =>? usize::try_from(n) + .map_err(|_| ParseError::User { error : "argument is out of range." } ) +} -type_: () = { - "int" => (), - "nat" => () +type_: Type = { + "int" => Type::Int, + "nat" => Type::Nat, } -value: () = { - => () +use Value::*; +value: Value = { + => NumberValue(n) } -instruction: () = { - "PUSH" => (), - "INT" => (), - "GT" => (), - "LOOP" => (), - "DIP" => (), - "ADD" => (), - "DROP" => (), - "SWAP" => (), - "IF" => (), - "DUP" => () +use Instruction::*; +instruction: Instruction = { + "PUSH" => Push(t, v), + "INT" => Int, + "GT" => Gt, + "LOOP" => Loop(ib), + "DIP" => DipN(n, ib), + "DIP" => Dip(ib), + "ADD" => Add, + "DROP" => DropN(n), + "DROP" => Drop, + "SWAP" => Swap, + "IF" => If(t, f), + "DUP" => DupN(n), + "DUP" => Dup } -instructionSeq: () = { - <(";")*> => () +instructionSeq: Vec = { + ";")*> => { // A sequence of instruction-followed-by-a-semicolon matched by - // `(";")*`, which can be optionally followed by a - // single trailing instruction, matched by `. + // `(";")*` resulting in `Vec` and bound to `ib`, + // which can be optionally followed by a single trailing instruction, + // matched by `. + + match i { + Some(instr) => { + ib.push(instr); + ib + }, + None => { + ib + } + } + } } -pub instructionBlock: () = { - "{" "}" => () +pub instructionBlock: InstructionBlock = { + "{" "}" => is, } -- GitLab From 36fefefd2a2d38c8d56c1073dc9ad569a2f2c03e Mon Sep 17 00:00:00 2001 From: "Sandeep.C.R" Date: Thu, 7 Sep 2023 13:57:22 +0530 Subject: [PATCH 2/2] MIR: Amend tests to check the result from parser --- contrib/mir/src/main.rs | 83 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 81 insertions(+), 2 deletions(-) diff --git a/contrib/mir/src/main.rs b/contrib/mir/src/main.rs index e24154ae5745..6a6b2cad3fd8 100644 --- a/contrib/mir/src/main.rs +++ b/contrib/mir/src/main.rs @@ -5,6 +5,7 @@ /* */ /******************************************************************************/ +mod ast; mod parser; mod syntax; @@ -25,7 +26,8 @@ mod tests { DIP { DROP 2 } } { DIP { DROP } } }"; - assert!(parser::parse(&src)); + // use built in pretty printer to validate the expected AST. + assert_eq!(format!("{:#?}", parser::parse(&src).unwrap()), EXPECTATION); } #[test] @@ -39,6 +41,83 @@ mod tests { DIP { DROP 2 } } { DIP { DROP } } }"; - assert!(!parser::parse(&src)); + assert_eq!(&parser::parse(&src).unwrap_err().to_string(), "Unrecognized token `GT` found at 129:131\nExpected one of \";\" or \"}\""); } + const EXPECTATION: &str = "[ + Int, + Push( + Int, + NumberValue( + 0, + ), + ), + DupN( + 2, + ), + Gt, + If( + [ + Dip( + [ + Push( + Int, + NumberValue( + -1, + ), + ), + Add, + ], + ), + Push( + Int, + NumberValue( + 1, + ), + ), + DupN( + 3, + ), + Gt, + Loop( + [ + Swap, + DupN( + 2, + ), + Add, + DipN( + 2, + [ + Push( + Int, + NumberValue( + -1, + ), + ), + Add, + ], + ), + DupN( + 3, + ), + Gt, + ], + ), + Dip( + [ + DropN( + 2, + ), + ], + ), + ], + [ + Dip( + [ + Drop, + ], + ), + ], + ), +]"; } -- GitLab