From f9ae59c77f206635e8d36d684b6fc06f7d518652 Mon Sep 17 00:00:00 2001 From: Pakin Date: Mon, 25 May 2026 09:05:39 +0700 Subject: [PATCH] feat: add codegen, vm executor Signed-off-by: Pakin --- build.rs | 3 + src/xml/ast/nodes.rs | 43 +- src/xml/codegen/java.rs | 144 ++ src/xml/codegen/javascript.rs | 133 ++ src/xml/codegen/mod.rs | 104 +- src/xml/codegen/python.rs | 137 ++ src/xml/codegen/rust.rs | 137 ++ src/xml/error/mod.rs | 121 +- src/xml/mod.rs | 13 + src/xml/parser/grammar.lalrpop | 159 +- src/xml/parser/grammar.rs | 3107 ++++++++++++++++++++++++++++++-- src/xml/parser/mod.rs | 169 +- src/xml/parser/mod.rs.bak | 59 - src/xml/vm/mod.rs | 636 +++++++ uniffi-bindgen.rs | 3 + 15 files changed, 4632 insertions(+), 336 deletions(-) create mode 100644 build.rs delete mode 100644 src/xml/parser/mod.rs.bak create mode 100644 src/xml/vm/mod.rs create mode 100644 uniffi-bindgen.rs diff --git a/build.rs b/build.rs new file mode 100644 index 0000000..7c4ed6d --- /dev/null +++ b/build.rs @@ -0,0 +1,3 @@ +fn main() { + lalrpop::process_root().unwrap(); +} \ No newline at end of file diff --git a/src/xml/ast/nodes.rs b/src/xml/ast/nodes.rs index b68c11f..73acb48 100644 --- a/src/xml/ast/nodes.rs +++ b/src/xml/ast/nodes.rs @@ -1,7 +1,9 @@ +#[derive(Clone, Debug, PartialEq)] pub struct Program { pub statements: Vec, } +#[derive(Clone, Debug, PartialEq)] pub enum Statement { VarDecl { name: String, @@ -14,7 +16,8 @@ pub enum Statement { else_branch: Vec, }, ForStmt { - condition: Expression, + variable: String, + iterable: Expression, body: Vec, }, ExprStmt { @@ -22,14 +25,15 @@ pub enum Statement { }, } +#[derive(Clone, Debug, PartialEq)] pub enum Expression { BinaryOp { left: Box, - op: BinaryOpKind, // Add, Sub, Mul, Div, Eq, Neq, Lt, Gt, Lte, Gte + op: BinaryOpKind, right: Box, }, UnaryOp { - op: UnaryOpKind, // Neg, Not + op: UnaryOpKind, operand: Box, }, Literal(LiteralValue), @@ -44,45 +48,48 @@ pub enum Expression { }, SpecialVar { name: String, - is_negative: bool, // For $- prefixed vars + is_negative: bool, }, AutoVarExpr { - variable: Box, // Changed from SpecialVar to Expression + variable: Box, }, FlagExpr { args: Vec, }, StringConcat { - // Special node for disambiguating + parts: Vec, }, } +#[derive(Clone, Debug, PartialEq)] pub enum LiteralValue { String(String), - Number(f64), // or i64/f64 distinction if needed + Number(f64), Bool(bool), } +#[derive(Clone, Copy, Debug, PartialEq)] pub enum BinaryOpKind { Add, Sub, Mul, Div, - Eq, // = - Neq, // != - Lt, // < - Gt, // > - Lte, // <= - Gte, // >= + Eq, + Neq, + Lt, + Gt, + Lte, + Gte, } +#[derive(Clone, Copy, Debug, PartialEq)] pub enum UnaryOpKind { - Neg, // - - Not, // ! + Neg, + Not, } +#[derive(Clone, Copy, Debug, PartialEq)] pub enum AssignmentType { - Equals, // = - NotAssigned, // !assigned -} + Equals, + NotAssigned, +} \ No newline at end of file diff --git a/src/xml/codegen/java.rs b/src/xml/codegen/java.rs index e69de29..2092d99 100644 --- a/src/xml/codegen/java.rs +++ b/src/xml/codegen/java.rs @@ -0,0 +1,144 @@ +use crate::xml::ast::nodes::{ + AssignmentType, BinaryOpKind, Expression, LiteralValue, Program, Statement, UnaryOpKind, +}; +use crate::xml::codegen::{walk_expression, walk_statement, CodeGen}; + +pub struct JavaCodeGen { + pub indent: usize, + pub class_name: String, +} + +impl JavaCodeGen { + pub fn new(class_name: &str) -> Self { + JavaCodeGen { + indent: 0, + class_name: class_name.to_string(), + } + } + + fn indent_str(&self) -> String { + " ".repeat(self.indent) + } +} + +impl CodeGen for JavaCodeGen { + fn generate(&self, program: &Program) -> String { + let stmts: Vec = program.statements.iter().map(|s| self.generate_statement(s)).collect(); + let mut result = format!("public class {} {{\n", self.class_name); + result.push_str(" public static void main(String[] args) {\n"); + for stmt in &stmts { + result.push_str(&format!(" {}\n", stmt.trim())); + } + result.push_str(" }\n"); + result.push_str("}\n"); + result + } + + fn generate_statement(&self, stmt: &Statement) -> String { + walk_statement(self, stmt) + } + + fn generate_expression(&self, expr: &Expression) -> String { + walk_expression(self, expr) + } + + fn generate_literal(&self, lit: &LiteralValue) -> String { + match lit { + LiteralValue::String(s) => format!("\"{}\"", s.replace('\\', "\\\\").replace('"', "\\\"")), + LiteralValue::Number(n) => format!("{}d", n), + LiteralValue::Bool(b) => format!("{}", b), + } + } + + fn generate_identifier(&self, name: &str) -> String { + name.to_string() + } + + fn generate_binary_op(&self, left: &str, op: BinaryOpKind, right: &str) -> String { + let op_str = match op { + BinaryOpKind::Add => "+", + BinaryOpKind::Sub => "-", + BinaryOpKind::Mul => "*", + BinaryOpKind::Div => "/", + BinaryOpKind::Eq => "==", + BinaryOpKind::Neq => "!=", + BinaryOpKind::Lt => "<", + BinaryOpKind::Gt => ">", + BinaryOpKind::Lte => "<=", + BinaryOpKind::Gte => ">=", + }; + format!("({} {} {})", left, op_str, right) + } + + fn generate_unary_op(&self, op: UnaryOpKind, operand: &str) -> String { + match op { + UnaryOpKind::Neg => format!("(-{})", operand), + UnaryOpKind::Not => format!("(!{})", operand), + } + } + + fn generate_special_var(&self, name: &str, is_negative: bool) -> String { + if is_negative { + format!("-var_{}", name) + } else { + format!("var_{}", name) + } + } + + fn generate_auto_var_expr(&self, variable: &str) -> String { + format!("auto_{}", variable) + } + + fn generate_function_call(&self, name: &str, args: &[String]) -> String { + format!("{}({})", name, args.join(", ")) + } + + fn generate_array_access(&self, name: &str, indices: &[String]) -> String { + let idx_str: String = indices.iter().map(|i| format!("[{}]", i)).collect(); + format!("{}{}", name, idx_str) + } + + fn generate_var_decl(&self, name: &str, value: Option<&str>, assignment_type: AssignmentType) -> String { + match assignment_type { + AssignmentType::Equals => { + match value { + Some(v) => format!("{}Object {} = {};", self.indent_str(), name, v), + None => format!("{}Object {} = null;", self.indent_str(), name), + } + } + AssignmentType::NotAssigned => format!("{}// {} is not assigned", self.indent_str(), name), + } + } + + fn generate_if_stmt(&self, condition: &str, then_body: &[String], else_body: &[String]) -> String { + let indent = self.indent_str(); + let mut result = format!("{}if ({}) {{\n", indent, condition); + for stmt in then_body { + result.push_str(&format!("{}\n", stmt)); + } + if else_body.is_empty() { + result.push_str(&format!("{}}}", indent)); + } else { + result.push_str(&format!("{}}} else {{\n", indent)); + for stmt in else_body { + result.push_str(&format!("{}\n", stmt)); + } + result.push_str(&format!("{}}}", indent)); + } + result + } + + fn generate_for_stmt(&self, variable: &str, iterable: &str, body: &[String]) -> String { + let indent = self.indent_str(); + let mut result = format!("{}for (Object {} : {}) {{\n", indent, variable, iterable); + for stmt in body { + result.push_str(&format!("{}\n", stmt)); + } + result.push_str(&format!("{}}}", indent)); + result + } + + fn generate_string_concat(&self, parts: &[String]) -> String { + parts.join(" + ") + } +} \ No newline at end of file diff --git a/src/xml/codegen/javascript.rs b/src/xml/codegen/javascript.rs index e69de29..b649d9a 100644 --- a/src/xml/codegen/javascript.rs +++ b/src/xml/codegen/javascript.rs @@ -0,0 +1,133 @@ +use crate::xml::ast::nodes::{ + AssignmentType, BinaryOpKind, Expression, LiteralValue, Program, Statement, UnaryOpKind, +}; +use crate::xml::codegen::{walk_expression, walk_statement, CodeGen}; + +pub struct JavaScriptCodeGen { + pub indent: usize, +} + +impl JavaScriptCodeGen { + pub fn new() -> Self { + JavaScriptCodeGen { indent: 0 } + } + + fn indent_str(&self) -> String { + " ".repeat(self.indent) + } +} + +impl CodeGen for JavaScriptCodeGen { + fn generate(&self, program: &Program) -> String { + let stmts: Vec = program.statements.iter().map(|s| self.generate_statement(s)).collect(); + stmts.join("\n") + } + + fn generate_statement(&self, stmt: &Statement) -> String { + walk_statement(self, stmt) + } + + fn generate_expression(&self, expr: &Expression) -> String { + walk_expression(self, expr) + } + + fn generate_literal(&self, lit: &LiteralValue) -> String { + match lit { + LiteralValue::String(s) => format!("\"{}\"", s.replace('\\', "\\\\").replace('"', "\\\"")), + LiteralValue::Number(n) => format!("{}", n), + LiteralValue::Bool(b) => format!("{}", b), + } + } + + fn generate_identifier(&self, name: &str) -> String { + name.to_string() + } + + fn generate_binary_op(&self, left: &str, op: BinaryOpKind, right: &str) -> String { + let op_str = match op { + BinaryOpKind::Add => "+", + BinaryOpKind::Sub => "-", + BinaryOpKind::Mul => "*", + BinaryOpKind::Div => "/", + BinaryOpKind::Eq => "===", + BinaryOpKind::Neq => "!==", + BinaryOpKind::Lt => "<", + BinaryOpKind::Gt => ">", + BinaryOpKind::Lte => "<=", + BinaryOpKind::Gte => ">=", + }; + format!("({} {} {})", left, op_str, right) + } + + fn generate_unary_op(&self, op: UnaryOpKind, operand: &str) -> String { + match op { + UnaryOpKind::Neg => format!("(-{})", operand), + UnaryOpKind::Not => format!("(!{})", operand), + } + } + + fn generate_special_var(&self, name: &str, is_negative: bool) -> String { + if is_negative { + format!("-var_{}", name) + } else { + format!("var_{}", name) + } + } + + fn generate_auto_var_expr(&self, variable: &str) -> String { + format!("auto_{}", variable) + } + + fn generate_function_call(&self, name: &str, args: &[String]) -> String { + format!("{}({})", name, args.join(", ")) + } + + fn generate_array_access(&self, name: &str, indices: &[String]) -> String { + let idx_str: String = indices.iter().map(|i| format!("[{}]", i)).collect(); + format!("{}{}", name, idx_str) + } + + fn generate_var_decl(&self, name: &str, value: Option<&str>, assignment_type: AssignmentType) -> String { + match assignment_type { + AssignmentType::Equals => { + match value { + Some(v) => format!("{}let {} = {};", self.indent_str(), name, v), + None => format!("{}let {} = null;", self.indent_str(), name), + } + } + AssignmentType::NotAssigned => format!("{}// {} is not assigned", self.indent_str(), name), + } + } + + fn generate_if_stmt(&self, condition: &str, then_body: &[String], else_body: &[String]) -> String { + let indent = self.indent_str(); + let mut result = format!("{}if ({}) {{\n", indent, condition); + for stmt in then_body { + result.push_str(&format!("{}\n", stmt)); + } + if else_body.is_empty() { + result.push_str(&format!("{}}}", indent)); + } else { + result.push_str(&format!("{}}} else {{\n", indent)); + for stmt in else_body { + result.push_str(&format!("{}\n", stmt)); + } + result.push_str(&format!("{}}}", indent)); + } + result + } + + fn generate_for_stmt(&self, variable: &str, iterable: &str, body: &[String]) -> String { + let indent = self.indent_str(); + let mut result = format!("{}for (let {} of {}) {{\n", indent, variable, iterable); + for stmt in body { + result.push_str(&format!("{}\n", stmt)); + } + result.push_str(&format!("{}}}", indent)); + result + } + + fn generate_string_concat(&self, parts: &[String]) -> String { + parts.join(" + ") + } +} \ No newline at end of file diff --git a/src/xml/codegen/mod.rs b/src/xml/codegen/mod.rs index 1edc54b..a2ee2b2 100644 --- a/src/xml/codegen/mod.rs +++ b/src/xml/codegen/mod.rs @@ -1,23 +1,87 @@ -use crate::xml::ast::nodes::{AssignmentType, BinaryOpKind, LiteralValue, Program, UnaryOpKind}; +pub mod rust; +pub mod python; +pub mod javascript; +pub mod java; -pub trait CodeGen { - fn generate_program(&self, program: &Program) -> T; +use crate::xml::ast::nodes::{ + AssignmentType, BinaryOpKind, Expression, LiteralValue, Program, Statement, UnaryOpKind, +}; - // Expression visitors - fn visit_binary_op(&self, left: &T, op: BinaryOpKind, right: &T) -> T; - fn visit_unary_op(&self, op: UnaryOpKind, operand: &T) -> T; - fn visit_literal(&self, lit: &LiteralValue) -> T; - fn visit_identifier(&self, name: &str) -> T; - fn visit_array_access(&self, name: &T, indices: &[T]) -> T; - fn visit_function_call(&self, name: &T, args: &[T]) -> T; - fn visit_special_var(&self, name: &str, is_negative: bool) -> T; - fn visit_auto_var_expr(&self, variable: &T) -> T; - fn visit_flag_expr(&self, args: &[T]) -> T; - fn visit_string_concat(&self, parts: &[T]) -> T; - - // Statement visitors - fn visit_var_decl(&self, name: &T, value: Option<&T>, assignment_type: AssignmentType) -> T; - fn visit_if_stmt(&self, condition: &T, then_body: &[T], else_body: &[T]) -> T; - fn visit_for_stmt(&self, condition: &T, body: &[T]) -> T; - fn visit_expr_stmt(&self, expr: &T) -> T; +pub trait CodeGen { + fn generate(&self, program: &Program) -> String; + fn generate_statement(&self, stmt: &Statement) -> String; + fn generate_expression(&self, expr: &Expression) -> String; + fn generate_literal(&self, lit: &LiteralValue) -> String; + fn generate_identifier(&self, name: &str) -> String; + fn generate_binary_op(&self, left: &str, op: BinaryOpKind, right: &str) -> String; + fn generate_unary_op(&self, op: UnaryOpKind, operand: &str) -> String; + fn generate_special_var(&self, name: &str, is_negative: bool) -> String; + fn generate_auto_var_expr(&self, variable: &str) -> String; + fn generate_function_call(&self, name: &str, args: &[String]) -> String; + fn generate_array_access(&self, name: &str, indices: &[String]) -> String; + fn generate_var_decl(&self, name: &str, value: Option<&str>, assignment_type: AssignmentType) -> String; + fn generate_if_stmt(&self, condition: &str, then_body: &[String], else_body: &[String]) -> String; + fn generate_for_stmt(&self, variable: &str, iterable: &str, body: &[String]) -> String; + fn generate_string_concat(&self, parts: &[String]) -> String; } + +fn walk_expression(codegen: &dyn CodeGen, expr: &Expression) -> String { + match expr { + Expression::BinaryOp { left, op, right } => { + let l = codegen.generate_expression(left); + let r = codegen.generate_expression(right); + codegen.generate_binary_op(&l, *op, &r) + } + Expression::UnaryOp { op, operand } => { + let o = codegen.generate_expression(operand); + codegen.generate_unary_op(*op, &o) + } + Expression::Literal(lit) => codegen.generate_literal(lit), + Expression::Identifier(name) => codegen.generate_identifier(name), + Expression::FunctionCall { name, args } => { + let rendered_args: Vec = args.iter().map(|a| codegen.generate_expression(a)).collect(); + codegen.generate_function_call(name, &rendered_args) + } + Expression::ArrayAccess { name, indices } => { + let rendered_indices: Vec = indices.iter().map(|i| codegen.generate_expression(i)).collect(); + codegen.generate_array_access(name, &rendered_indices) + } + Expression::SpecialVar { name, is_negative } => codegen.generate_special_var(name, *is_negative), + Expression::AutoVarExpr { variable } => { + let v = codegen.generate_expression(variable); + codegen.generate_auto_var_expr(&v) + } + Expression::FlagExpr { args } => { + let rendered_args: Vec = args.iter().map(|a| codegen.generate_expression(a)).collect(); + codegen.generate_function_call("flag", &rendered_args) + } + Expression::StringConcat { parts } => { + let rendered_parts: Vec = parts.iter().map(|p| codegen.generate_expression(p)).collect(); + codegen.generate_string_concat(&rendered_parts) + } + } +} + +fn walk_statement(codegen: &dyn CodeGen, stmt: &Statement) -> String { + match stmt { + Statement::VarDecl { name, value, assignment_type } => { + let v = value.as_ref().map(|e| codegen.generate_expression(e)); + codegen.generate_var_decl(name, v.as_deref(), *assignment_type) + } + Statement::IfStmt { condition, then_branch, else_branch } => { + let c = codegen.generate_expression(condition); + let then_body: Vec = then_branch.iter().map(|s| codegen.generate_statement(s)).collect(); + let else_body: Vec = else_branch.iter().map(|s| codegen.generate_statement(s)).collect(); + codegen.generate_if_stmt(&c, &then_body, &else_body) + } + Statement::ForStmt { variable, iterable, body } => { + let iter = codegen.generate_expression(iterable); + let b: Vec = body.iter().map(|s| codegen.generate_statement(s)).collect(); + codegen.generate_for_stmt(variable, &iter, &b) + } + Statement::ExprStmt { expression } => { + let e = codegen.generate_expression(expression); + codegen.generate_var_decl("_", Some(&e), AssignmentType::Equals) + } + } +} \ No newline at end of file diff --git a/src/xml/codegen/python.rs b/src/xml/codegen/python.rs index e69de29..b82bf0b 100644 --- a/src/xml/codegen/python.rs +++ b/src/xml/codegen/python.rs @@ -0,0 +1,137 @@ +use crate::xml::ast::nodes::{ + AssignmentType, BinaryOpKind, Expression, LiteralValue, Program, Statement, UnaryOpKind, +}; +use crate::xml::codegen::{walk_expression, walk_statement, CodeGen}; + +pub struct PythonCodeGen { + pub indent: usize, +} + +impl PythonCodeGen { + pub fn new() -> Self { + PythonCodeGen { indent: 0 } + } + + fn indent_str(&self) -> String { + " ".repeat(self.indent) + } +} + +impl CodeGen for PythonCodeGen { + fn generate(&self, program: &Program) -> String { + let stmts: Vec = program.statements.iter().map(|s| self.generate_statement(s)).collect(); + stmts.join("\n") + } + + fn generate_statement(&self, stmt: &Statement) -> String { + walk_statement(self, stmt) + } + + fn generate_expression(&self, expr: &Expression) -> String { + walk_expression(self, expr) + } + + fn generate_literal(&self, lit: &LiteralValue) -> String { + match lit { + LiteralValue::String(s) => format!("\"{}\"", s.replace('\\', "\\\\").replace('"', "\\\"")), + LiteralValue::Number(n) => format!("{}", n), + LiteralValue::Bool(b) => if *b { "True".to_string() } else { "False".to_string() }, + } + } + + fn generate_identifier(&self, name: &str) -> String { + name.to_string() + } + + fn generate_binary_op(&self, left: &str, op: BinaryOpKind, right: &str) -> String { + let op_str = match op { + BinaryOpKind::Add => "+", + BinaryOpKind::Sub => "-", + BinaryOpKind::Mul => "*", + BinaryOpKind::Div => "/", + BinaryOpKind::Eq => "==", + BinaryOpKind::Neq => "!=", + BinaryOpKind::Lt => "<", + BinaryOpKind::Gt => ">", + BinaryOpKind::Lte => "<=", + BinaryOpKind::Gte => ">=", + }; + format!("({} {} {})", left, op_str, right) + } + + fn generate_unary_op(&self, op: UnaryOpKind, operand: &str) -> String { + match op { + UnaryOpKind::Neg => format!("(-{})", operand), + UnaryOpKind::Not => format!("(not {})", operand), + } + } + + fn generate_special_var(&self, name: &str, is_negative: bool) -> String { + if is_negative { + format!("-var_{}", name) + } else { + format!("var_{}", name) + } + } + + fn generate_auto_var_expr(&self, variable: &str) -> String { + format!("auto_{}", variable) + } + + fn generate_function_call(&self, name: &str, args: &[String]) -> String { + format!("{}({})", name, args.join(", ")) + } + + fn generate_array_access(&self, name: &str, indices: &[String]) -> String { + let idx_str: String = indices.iter().map(|i| format!("[{}]", i)).collect(); + format!("{}{}", name, idx_str) + } + + fn generate_var_decl(&self, name: &str, value: Option<&str>, assignment_type: AssignmentType) -> String { + match assignment_type { + AssignmentType::Equals => { + match value { + Some(v) => format!("{}{} = {}", self.indent_str(), name, v), + None => format!("{}{} = None", self.indent_str(), name), + } + } + AssignmentType::NotAssigned => format!("{}# {} is not assigned", self.indent_str(), name), + } + } + + fn generate_if_stmt(&self, condition: &str, then_body: &[String], else_body: &[String]) -> String { + let indent = self.indent_str(); + let mut result = format!("{}if {}:\n", indent, condition); + if then_body.is_empty() { + result.push_str(&format!("{} pass\n", indent)); + } else { + for stmt in then_body { + result.push_str(&format!("{}\n", stmt)); + } + } + if !else_body.is_empty() { + result.push_str(&format!("{}else:\n", indent)); + for stmt in else_body { + result.push_str(&format!("{}\n", stmt)); + } + } + result + } + + fn generate_for_stmt(&self, variable: &str, iterable: &str, body: &[String]) -> String { + let indent = self.indent_str(); + let mut result = format!("{}for {} in {}:\n", indent, variable, iterable); + if body.is_empty() { + result.push_str(&format!("{} pass\n", indent)); + } else { + for stmt in body { + result.push_str(&format!("{}\n", stmt)); + } + } + result + } + + fn generate_string_concat(&self, parts: &[String]) -> String { + parts.join(" + ") + } +} \ No newline at end of file diff --git a/src/xml/codegen/rust.rs b/src/xml/codegen/rust.rs index e69de29..78a6dcd 100644 --- a/src/xml/codegen/rust.rs +++ b/src/xml/codegen/rust.rs @@ -0,0 +1,137 @@ +use crate::xml::ast::nodes::{ + AssignmentType, BinaryOpKind, Expression, LiteralValue, Program, Statement, UnaryOpKind, +}; +use crate::xml::codegen::{walk_expression, walk_statement, CodeGen}; + +pub struct RustCodeGen { + pub indent: usize, +} + +impl RustCodeGen { + pub fn new() -> Self { + RustCodeGen { indent: 0 } + } + + fn indent_str(&self) -> String { + " ".repeat(self.indent) + } + + fn format_block(&self, stmts: &[String]) -> String { + stmts.join("\n") + } +} + +impl CodeGen for RustCodeGen { + fn generate(&self, program: &Program) -> String { + let stmts: Vec = program.statements.iter().map(|s| self.generate_statement(s)).collect(); + stmts.join("\n") + } + + fn generate_statement(&self, stmt: &Statement) -> String { + walk_statement(self, stmt) + } + + fn generate_expression(&self, expr: &Expression) -> String { + walk_expression(self, expr) + } + + fn generate_literal(&self, lit: &LiteralValue) -> String { + match lit { + LiteralValue::String(s) => format!("\"{}\"", s.replace('\\', "\\\\").replace('"', "\\\"")), + LiteralValue::Number(n) => format!("{}", n), + LiteralValue::Bool(b) => format!("{}", b), + } + } + + fn generate_identifier(&self, name: &str) -> String { + name.to_string() + } + + fn generate_binary_op(&self, left: &str, op: BinaryOpKind, right: &str) -> String { + let op_str = match op { + BinaryOpKind::Add => "+", + BinaryOpKind::Sub => "-", + BinaryOpKind::Mul => "*", + BinaryOpKind::Div => "/", + BinaryOpKind::Eq => "==", + BinaryOpKind::Neq => "!=", + BinaryOpKind::Lt => "<", + BinaryOpKind::Gt => ">", + BinaryOpKind::Lte => "<=", + BinaryOpKind::Gte => ">=", + }; + format!("({} {} {})", left, op_str, right) + } + + fn generate_unary_op(&self, op: UnaryOpKind, operand: &str) -> String { + match op { + UnaryOpKind::Neg => format!("(-{})", operand), + UnaryOpKind::Not => format!("(!{})", operand), + } + } + + fn generate_special_var(&self, name: &str, is_negative: bool) -> String { + if is_negative { + format!("var_{}_neg", name) + } else { + format!("var_{}", name) + } + } + + fn generate_auto_var_expr(&self, variable: &str) -> String { + format!("auto_{}", variable) + } + + fn generate_function_call(&self, name: &str, args: &[String]) -> String { + format!("{}({})", name, args.join(", ")) + } + + fn generate_array_access(&self, name: &str, indices: &[String]) -> String { + let idx_str: String = indices.iter().map(|i| format!("[{}]", i)).collect(); + format!("{}{}", name, idx_str) + } + + fn generate_var_decl(&self, name: &str, value: Option<&str>, assignment_type: AssignmentType) -> String { + match assignment_type { + AssignmentType::Equals => { + match value { + Some(v) => format!("{}let {} = {};", self.indent_str(), name, v), + None => format!("{}let {} = Default::default();", self.indent_str(), name), + } + } + AssignmentType::NotAssigned => format!("{}// {} is not assigned", self.indent_str(), name), + } + } + + fn generate_if_stmt(&self, condition: &str, then_body: &[String], else_body: &[String]) -> String { + let indent = self.indent_str(); + let mut result = format!("{}if {} {{\n", indent, condition); + for stmt in then_body { + result.push_str(&format!("{}\n", stmt)); + } + if else_body.is_empty() { + result.push_str(&format!("{}}}", indent)); + } else { + result.push_str(&format!("{}}} else {{\n", indent)); + for stmt in else_body { + result.push_str(&format!("{}\n", stmt)); + } + result.push_str(&format!("{}}}", indent)); + } + result + } + + fn generate_for_stmt(&self, variable: &str, iterable: &str, body: &[String]) -> String { + let indent = self.indent_str(); + let mut result = format!("{}for {} in {} {{\n", indent, variable, iterable); + for stmt in body { + result.push_str(&format!("{}\n", stmt)); + } + result.push_str(&format!("{}}}", indent)); + result + } + + fn generate_string_concat(&self, parts: &[String]) -> String { + parts.join(" + ") + } +} \ No newline at end of file diff --git a/src/xml/error/mod.rs b/src/xml/error/mod.rs index 427e797..25e75c3 100644 --- a/src/xml/error/mod.rs +++ b/src/xml/error/mod.rs @@ -3,6 +3,7 @@ use crate::xml::parser::grammar::Token; pub type ParserResult = Result; +#[derive(Debug)] pub enum ParseError { LexerError { position: Position, @@ -19,66 +20,86 @@ pub enum ParseError { }, } +#[derive(Debug)] pub struct Position { pub line: usize, pub column: usize, - pub file: Option, // For tracking which XML file/script block + pub file: Option, } +impl std::fmt::Display for ParseError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + ParseError::LexerError { position, message } => { + write!(f, "Lexer error at {}:{}: {}", position.line, position.column, message) + } + ParseError::ParserError { position, message, expected } => { + write!(f, "Parser error at {}:{}: {} (expected one of: {:?})", position.line, position.column, message, expected) + } + ParseError::SemanticError { position, message } => { + write!(f, "Semantic error at {}:{}: {}", position.line, position.column, message) + } + } + } +} + +impl std::error::Error for ParseError {} + impl ParseError { pub fn from_lalrpop_error(source: &str, e: LalrpopParseError, &'static str>) -> Self { match e { + LalrpopParseError::InvalidToken { location } => { + let (line, col) = line_col_from_offset(source, location); + ParseError::LexerError { + position: Position { line, column: col, file: None }, + message: format!("Invalid token at location {}", location), + } + } + LalrpopParseError::UnrecognizedEof { location, expected } => { + let (line, col) = line_col_from_offset(source, location); + ParseError::ParserError { + position: Position { line, column: col, file: None }, + message: "Unexpected end of input".to_string(), + expected: expected.into_iter().map(|s| s.to_string()).collect(), + } + } + LalrpopParseError::UnrecognizedToken { token, expected } => { + let (line, col) = line_col_from_offset(source, token.0); + ParseError::ParserError { + position: Position { line, column: col, file: None }, + message: format!("Unrecognized token: {:?}", token.1), + expected: expected.into_iter().map(|s| s.to_string()).collect(), + } + } + LalrpopParseError::ExtraToken { token } => { + let (line, col) = line_col_from_offset(source, token.0); + ParseError::ParserError { + position: Position { line, column: col, file: None }, + message: format!("Extra token: {:?}", token.1), + expected: Vec::new(), + } + } LalrpopParseError::User { error } => ParseError::SemanticError { - position: Position { - line: 0, // TODO: improve position tracking - column: 0, - file: None, - }, - message: format!("User error: {}", error), - }, - LalrpopParseError::InvalidToken { location } => ParseError::LexerError { - position: Position { - line: 0, // TODO: improve position tracking - column: 0, - file: None, - }, - message: format!("Invalid token at location {}", location), - }, - LalrpopParseError::UnrecognizedEof { location, expected } => ParseError::ParserError { - position: Position { - line: 0, // TODO: improve position tracking - column: 0, - file: None, - }, - message: format!("Unexpected end of input, expected one of: {:?}", expected), - expected: expected.into_iter().map(|s| s.to_string()).collect(), - }, - LalrpopParseError::UnrecognizedToken { token, expected } => ParseError::ParserError { - position: Position { - line: 0, // TODO: improve position tracking - column: token.0, - file: None, - }, - message: format!("Unrecognized token: {:?}", token.1), - expected: expected.into_iter().map(|s| s.to_string()).collect(), - }, - LalrpopParseError::ExtraToken { token } => ParseError::ParserError { - position: Position { - line: 0, // TODO: improve position tracking - column: token.0, - file: None, - }, - message: format!("Extra token: {:?}", token.1), - expected: Vec::new(), - }, - LalrpopParseError::User { error: e } => ParseError::SemanticError { - position: Position { - line: 0, // TODO: improve position tracking - column: 0, - file: None, - }, - message: format!("User error: {}", e), + position: Position { line: 0, column: 0, file: None }, + message: error.to_string(), }, } } } + +fn line_col_from_offset(source: &str, offset: usize) -> (usize, usize) { + let mut line = 1; + let mut col = 1; + for (i, c) in source.chars().enumerate() { + if i >= offset { + break; + } + if c == '\n' { + line += 1; + col = 1; + } else { + col += 1; + } + } + (line, col) +} \ No newline at end of file diff --git a/src/xml/mod.rs b/src/xml/mod.rs index 81cbe50..6c9818f 100644 --- a/src/xml/mod.rs +++ b/src/xml/mod.rs @@ -4,3 +4,16 @@ pub mod error; pub mod ffi_node; pub mod node; pub mod parser; +pub mod vm; + +pub use error::ParserResult; +pub use parser::ScriptParser; +pub use ast::nodes::{ + AssignmentType, BinaryOpKind, Expression, LiteralValue, Program, Statement, UnaryOpKind, +}; +pub use codegen::CodeGen; +pub use codegen::rust::RustCodeGen; +pub use codegen::python::PythonCodeGen; +pub use codegen::javascript::JavaScriptCodeGen; +pub use codegen::java::JavaCodeGen; +pub use vm::{Vm, Value, VmError, Environment}; \ No newline at end of file diff --git a/src/xml/parser/grammar.lalrpop b/src/xml/parser/grammar.lalrpop index 297d4fe..bd6cbfd 100644 --- a/src/xml/parser/grammar.lalrpop +++ b/src/xml/parser/grammar.lalrpop @@ -1,9 +1,160 @@ +use crate::xml::ast::nodes::{AssignmentType, BinaryOpKind, Expression, LiteralValue, Program, Statement, UnaryOpKind}; + grammar; -pub Program: () = { - => () +pub Program: Program = { + => Program { statements: stmts } }; -Statement: () = { - "hello" => () +Stmt: Statement = { + "Var" "=" => Statement::VarDecl { + name, + value: Some(v), + assignment_type: AssignmentType::Equals, + }, + "Var" "!" "assigned" => Statement::VarDecl { + name, + value: None, + assignment_type: AssignmentType::NotAssigned, + }, + "If" "Then" "EndIf" => Statement::IfStmt { + condition: cond, + then_branch: then_body, + else_branch: vec![], + }, + "If" "Then" "Else" "EndIf" => Statement::IfStmt { + condition: cond, + then_branch: then_body, + else_branch: else_body, + }, + "For" "In" "EndFor" => Statement::ForStmt { + variable: var, + iterable: iter, + body, + }, }; + +Expr: Expression = { + OrExpr, +}; + +OrExpr: Expression = { + AndExpr, + "||" => Expression::BinaryOp { + left: Box::new(left), + op: BinaryOpKind::Add, + right: Box::new(right), + }, +}; + +AndExpr: Expression = { + CmpExpr, + "&&" => Expression::BinaryOp { + left: Box::new(left), + op: BinaryOpKind::Add, + right: Box::new(right), + }, +}; + +CmpExpr: Expression = { + AddExpr, + "==" => Expression::BinaryOp { left: Box::new(left), op: BinaryOpKind::Eq, right: Box::new(right) }, + "!=" => Expression::BinaryOp { left: Box::new(left), op: BinaryOpKind::Neq, right: Box::new(right) }, + "<=" => Expression::BinaryOp { left: Box::new(left), op: BinaryOpKind::Lte, right: Box::new(right) }, + ">=" => Expression::BinaryOp { left: Box::new(left), op: BinaryOpKind::Gte, right: Box::new(right) }, + "<" => Expression::BinaryOp { left: Box::new(left), op: BinaryOpKind::Lt, right: Box::new(right) }, + ">" => Expression::BinaryOp { left: Box::new(left), op: BinaryOpKind::Gt, right: Box::new(right) }, +}; + +AddExpr: Expression = { + MulExpr, + "+" => Expression::BinaryOp { left: Box::new(left), op: BinaryOpKind::Add, right: Box::new(right) }, + "-" => Expression::BinaryOp { left: Box::new(left), op: BinaryOpKind::Sub, right: Box::new(right) }, +}; + +MulExpr: Expression = { + UnExpr, + "*" => Expression::BinaryOp { left: Box::new(left), op: BinaryOpKind::Mul, right: Box::new(right) }, + "/" => Expression::BinaryOp { left: Box::new(left), op: BinaryOpKind::Div, right: Box::new(right) }, +}; + +UnExpr: Expression = { + AtomExpr, + "!" => Expression::UnaryOp { op: UnaryOpKind::Not, operand: Box::new(e) }, + "-" => Expression::UnaryOp { op: UnaryOpKind::Neg, operand: Box::new(e) }, +}; + +AtomExpr: Expression = { + => Expression::Literal(LiteralValue::String(s)), + => Expression::Literal(LiteralValue::Number(n)), + "True" => Expression::Literal(LiteralValue::Bool(true)), + "False" => Expression::Literal(LiteralValue::Bool(false)), + "(" ?> ")" => Expression::FunctionCall { name, args: args.unwrap_or_default() }, + "$" => Expression::SpecialVar { name, is_negative: false }, + "$" "-" => Expression::SpecialVar { name, is_negative: true }, + "@" => Expression::AutoVarExpr { variable: Box::new(Expression::SpecialVar { name, is_negative: false }) }, + => Expression::Identifier(name), + "(" ")" => e, +}; + +Comma: Vec = { + ",")*> => { + let mut v = v; + v.push(e); + v + } +}; + +Stmts: Vec = { + => stmts, +}; + +STRING: String = { + => s[1..s.len()-1].to_string() +}; + +NUM: f64 = { + => s.parse::().unwrap() +}; + +Ident: String = { + => s.to_string() +}; + +match { + r"\s+" => {}, + "Var", + "If", + "Then", + "Else", + "EndIf", + "For", + "In", + "EndFor", + "True", + "False", + "==", + "!=", + "<=", + ">=", + "&&", + "||", + "!", + "$", + "@", + "(", + ")", + ",", + "+", + "-", + "*", + "/", + "<", + ">", + "=", + "assigned", +} else { + r#""[^"]*""#, + r"[0-9]+(\.[0-9]+)?", + r"[a-zA-Z_][a-zA-Z0-9_]*", +} \ No newline at end of file diff --git a/src/xml/parser/grammar.rs b/src/xml/parser/grammar.rs index c41af73..72f64df 100644 --- a/src/xml/parser/grammar.rs +++ b/src/xml/parser/grammar.rs @@ -1,74 +1,500 @@ -// auto-generated: "lalrpop 0.20.0" -// sha3: ec3e9ad964a91b00df78376d9bb2e2c3df24aea537d87c1ca9bb028bad1ed06c +// auto-generated: "lalrpop 0.23.1" +// sha3: d5a4b6662094bf1eda39b3740e0d893d7038b0f7f33e762bdd01b0fb777990c3 +use crate::xml::ast::nodes::{AssignmentType, BinaryOpKind, Expression, LiteralValue, Program, Statement, UnaryOpKind}; #[allow(unused_extern_crates)] extern crate lalrpop_util as __lalrpop_util; #[allow(unused_imports)] use self::__lalrpop_util::state_machine as __state_machine; -extern crate core; +#[allow(unused_extern_crates)] extern crate alloc; #[rustfmt::skip] -#[allow(non_snake_case, non_camel_case_types, unused_mut, unused_variables, unused_imports, unused_parens, clippy::all)] +#[allow(explicit_outlives_requirements, non_snake_case, non_camel_case_types, unused_mut, unused_variables, unused_imports, unused_parens, clippy::needless_lifetimes, clippy::type_complexity, clippy::needless_return, clippy::too_many_arguments, clippy::match_single_binding, clippy::clone_on_copy, clippy::unit_arg)] mod __parse__Program { + use crate::xml::ast::nodes::{AssignmentType, BinaryOpKind, Expression, LiteralValue, Program, Statement, UnaryOpKind}; #[allow(unused_extern_crates)] extern crate lalrpop_util as __lalrpop_util; #[allow(unused_imports)] use self::__lalrpop_util::state_machine as __state_machine; - extern crate core; + #[allow(unused_extern_crates)] extern crate alloc; use self::__lalrpop_util::lexer::Token; #[allow(dead_code)] pub(crate) enum __Symbol<'input> { Variant0(&'input str), - Variant1(()), - Variant2(alloc::vec::Vec<()>), + Variant1(Expression), + Variant2(alloc::vec::Vec), + Variant3(Vec), + Variant4(Option>), + Variant5(String), + Variant6(f64), + Variant7(Program), + Variant8(Statement), + Variant9(alloc::vec::Vec), + Variant10(Vec), } const __ACTION: &[i8] = &[ // State 0 - 5, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 4, 0, 0, 0, 5, 0, 0, // State 1 - 5, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 4, 0, 0, 0, 5, 0, 0, // State 2 - 0, + 0, 0, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 3 - -6, + 50, 51, 36, 6, 0, 7, 0, 8, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 48, 0, 0, 0, 0, 49, 0, 0, 0, // State 4 - -3, + 0, 0, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // State 5 - -7, + 50, 51, 36, 6, 0, 7, 0, 8, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 48, 0, 0, 0, 0, 49, 0, 0, 0, + // State 6 + 0, 0, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + // State 7 + 50, 51, 36, 6, 0, 7, 0, 8, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 48, 0, 0, 0, 0, 49, 0, 0, 0, + // State 8 + 50, 51, 36, 6, 0, 7, 0, 8, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 48, 0, 0, 0, 0, 49, 0, 0, 0, + // State 9 + 0, 0, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + // State 10 + 50, 51, 36, 6, 0, 7, 0, 8, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 48, 0, 0, 0, 0, 49, 0, 0, 0, + // State 11 + 50, 51, 36, 6, 0, 7, 0, 8, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 48, 0, 0, 0, 0, 49, 0, 0, 0, + // State 12 + 50, 51, 36, 6, 0, 7, 0, 8, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 48, 0, 0, 0, 0, 49, 0, 0, 0, + // State 13 + 50, 51, 36, 6, 0, 7, 0, 8, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 48, 0, 0, 0, 0, 49, 0, 0, 0, + // State 14 + 50, 51, 36, 6, 0, 7, 0, 8, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 48, 0, 0, 0, 0, 49, 0, 0, 0, + // State 15 + 50, 51, 36, 6, 0, 7, 0, 8, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 48, 0, 0, 0, 0, 49, 0, 0, 0, + // State 16 + 50, 51, 36, 6, 0, 7, 0, 8, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 48, 0, 0, 0, 0, 49, 0, 0, 0, + // State 17 + 50, 51, 36, 6, 0, 7, 0, 8, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 48, 0, 0, 0, 0, 49, 0, 0, 0, + // State 18 + 50, 51, 36, 6, 0, 7, 0, 8, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 48, 0, 0, 0, 0, 49, 0, 0, 0, + // State 19 + 50, 51, 36, 6, 0, 7, 0, 8, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 48, 0, 0, 0, 0, 49, 0, 0, 0, + // State 20 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 4, 0, 0, 0, 5, 0, 0, + // State 21 + 50, 51, 36, 6, 0, 7, 0, 8, 71, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 48, 0, 0, 0, 0, 49, 0, 0, 0, + // State 22 + 50, 51, 36, 6, 0, 7, 0, 8, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 48, 0, 0, 0, 0, 49, 0, 0, 0, + // State 23 + 50, 51, 36, 6, 0, 7, 0, 8, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 48, 0, 0, 0, 0, 49, 0, 0, 0, + // State 24 + 50, 51, 36, 6, 0, 7, 0, 8, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 48, 0, 0, 0, 0, 49, 0, 0, 0, + // State 25 + 0, 0, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + // State 26 + 50, 51, 36, 6, 0, 7, 0, 8, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 48, 0, 0, 0, 0, 49, 0, 0, 0, + // State 27 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 4, 0, 0, 0, 5, 0, 0, + // State 28 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -53, -53, -53, 0, 3, 4, 0, 0, 0, 5, 0, 0, + // State 29 + 50, 51, 36, 6, 0, 7, 0, 8, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 48, 0, 0, 0, 0, 49, 0, 0, 0, + // State 30 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 4, 0, 0, 0, 5, 0, 0, + // State 31 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + // State 32 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -51, -51, -51, 0, -51, -51, 0, 0, 0, -51, 0, 0, + // State 33 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -52, -52, -52, 0, -52, -52, 0, 0, 0, -52, 0, 0, + // State 34 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, + // State 35 + 0, 0, 0, -34, -34, 0, -34, -34, -34, -34, -34, -34, -34, -34, -34, -34, -34, -34, -34, -34, 0, -34, -34, -34, 0, -34, -34, -34, -34, 0, -34, 0, -34, + // State 36 + 0, 0, 0, 0, -22, 0, -22, 0, -22, 0, 12, -22, 13, 0, -22, -22, 0, -22, -22, -22, 0, -22, -22, -22, 0, -22, -22, 0, -22, 0, -22, 0, -22, + // State 37 + 0, 0, 0, 0, 0, 0, 14, 0, -39, 0, 0, -39, 0, 0, 0, 0, 0, 0, 0, 0, 0, -39, -39, -39, 0, -39, -39, 0, -39, 0, -39, 0, -39, + // State 38 + 0, 0, 0, 0, -54, 0, -54, 0, -54, -54, -54, -54, -54, -54, -54, -54, 0, -54, -54, -54, 0, -54, -54, -54, 0, -54, -54, 0, -54, 0, -54, 0, -54, + // State 39 + 0, 0, 0, 0, 15, 0, -9, 0, -9, 0, 0, -9, 0, 0, 16, 17, 0, 18, 19, 20, 0, -9, -9, -9, 0, -9, -9, 0, -9, 0, -9, 0, -9, + // State 40 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, + // State 41 + 0, 0, 0, 0, -20, 0, -20, 22, -20, -20, -20, -20, -20, -20, -20, -20, 0, -20, -20, -20, 0, -20, -20, -20, 0, -20, -20, 0, -20, 0, -20, 0, -20, + // State 42 + 0, 0, 0, 0, -6, 0, -6, 0, -6, 23, -6, -6, -6, 24, -6, -6, 0, -6, -6, -6, 0, -6, -6, -6, 0, -6, -6, 0, -6, 0, -6, 0, -6, + // State 43 + 0, 0, 0, 0, -12, 0, -12, 0, -12, -12, -12, -12, -12, -12, -12, -12, 0, -12, -12, -12, 0, -12, -12, -12, 0, -12, -12, 0, -12, 0, -12, 0, -12, + // State 44 + 0, 0, 0, 0, 0, 0, 0, 0, -33, 0, 0, -33, 0, 0, 0, 0, 0, 0, 0, 0, 0, -33, -33, -33, 0, -33, -33, 0, -33, 0, -33, 0, 25, + // State 45 + 0, 0, 0, 0, -11, 0, -11, 0, -11, -11, -11, -11, -11, -11, -11, -11, 0, -11, -11, -11, 0, -11, -11, -11, 0, -11, -11, 0, -11, 0, -11, 0, -11, + // State 46 + 0, 0, 0, 0, -35, 0, -35, 0, -35, -35, -35, -35, -35, -35, -35, -35, 0, -35, -35, -35, 0, -35, -35, -35, 0, -35, -35, 0, -35, 0, -35, 0, -35, + // State 47 + 0, 0, 0, 0, -14, 0, -14, 0, -14, -14, -14, -14, -14, -14, -14, -14, 0, -14, -14, -14, 0, -14, -14, -14, 0, -14, -14, 0, -14, 0, -14, 0, -14, + // State 48 + 0, 0, 0, 0, -13, 0, -13, 0, -13, -13, -13, -13, -13, -13, -13, -13, 0, -13, -13, -13, 0, -13, -13, -13, 0, -13, -13, 0, -13, 0, -13, 0, -13, + // State 49 + 0, 0, 0, 0, -43, 0, -43, 0, -43, -43, -43, -43, -43, -43, -43, -43, 0, -43, -43, -43, 0, -43, -43, -43, 0, -43, -43, 0, -43, 0, -43, 0, -43, + // State 50 + 0, 0, 0, 0, -38, 0, -38, 0, -38, -38, -38, -38, -38, -38, -38, -38, 0, -38, -38, -38, 0, -38, -38, -38, 0, -38, -38, 0, -38, 0, -38, 0, -38, + // State 51 + 0, 0, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + // State 52 + 0, 0, 0, 0, -55, 0, -55, 0, -55, -55, -55, -55, -55, -55, -55, -55, 0, -55, -55, -55, 0, -55, -55, -55, 0, -55, -55, 0, -55, 0, -55, 0, -55, + // State 53 + 0, 0, 0, 0, -17, 0, -17, 0, -17, -17, -17, -17, -17, -17, -17, -17, 0, -17, -17, -17, 0, -17, -17, -17, 0, -17, -17, 0, -17, 0, -17, 0, -17, + // State 54 + 0, 0, 0, 0, 0, 0, 0, 0, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + // State 55 + 0, 0, 0, 0, -56, 0, -56, 0, -56, -56, -56, -56, -56, -56, -56, -56, 0, -56, -56, -56, 0, -56, -56, -56, 0, -56, -56, 0, -56, 0, -56, 0, -56, + // State 56 + 0, 0, 0, 0, -19, 0, -19, 0, -19, -19, -19, -19, -19, -19, -19, -19, 0, -19, -19, -19, 0, -19, -19, -19, 0, -19, -19, 0, -19, 0, -19, 0, -19, + // State 57 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 0, + // State 58 + 0, 0, 0, 0, -7, 0, -7, 0, -7, 23, -7, -7, -7, 24, -7, -7, 0, -7, -7, -7, 0, -7, -7, -7, 0, -7, -7, 0, -7, 0, -7, 0, -7, + // State 59 + 0, 0, 0, 0, -8, 0, -8, 0, -8, 23, -8, -8, -8, 24, -8, -8, 0, -8, -8, -8, 0, -8, -8, -8, 0, -8, -8, 0, -8, 0, -8, 0, -8, + // State 60 + 0, 0, 0, 0, 15, 0, -10, 0, -10, 0, 0, -10, 0, 0, 16, 17, 0, 18, 19, 20, 0, -10, -10, -10, 0, -10, -10, 0, -10, 0, -10, 0, -10, + // State 61 + 0, 0, 0, 0, -24, 0, -24, 0, -24, 0, 12, -24, 13, 0, -24, -24, 0, -24, -24, -24, 0, -24, -24, -24, 0, -24, -24, 0, -24, 0, -24, 0, -24, + // State 62 + 0, 0, 0, 0, -27, 0, -27, 0, -27, 0, 12, -27, 13, 0, -27, -27, 0, -27, -27, -27, 0, -27, -27, -27, 0, -27, -27, 0, -27, 0, -27, 0, -27, + // State 63 + 0, 0, 0, 0, -25, 0, -25, 0, -25, 0, 12, -25, 13, 0, -25, -25, 0, -25, -25, -25, 0, -25, -25, -25, 0, -25, -25, 0, -25, 0, -25, 0, -25, + // State 64 + 0, 0, 0, 0, -23, 0, -23, 0, -23, 0, 12, -23, 13, 0, -23, -23, 0, -23, -23, -23, 0, -23, -23, -23, 0, -23, -23, 0, -23, 0, -23, 0, -23, + // State 65 + 0, 0, 0, 0, -28, 0, -28, 0, -28, 0, 12, -28, 13, 0, -28, -28, 0, -28, -28, -28, 0, -28, -28, -28, 0, -28, -28, 0, -28, 0, -28, 0, -28, + // State 66 + 0, 0, 0, 0, -26, 0, -26, 0, -26, 0, 12, -26, 13, 0, -26, -26, 0, -26, -26, -26, 0, -26, -26, -26, 0, -26, -26, 0, -26, 0, -26, 0, -26, + // State 67 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 0, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, + // State 68 + 0, 0, 0, 0, 0, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + // State 69 + 0, 0, 0, 0, 0, 0, 0, 0, -29, 0, 0, 83, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + // State 70 + 0, 0, 0, 0, -16, 0, -16, 0, -16, -16, -16, -16, -16, -16, -16, -16, 0, -16, -16, -16, 0, -16, -16, -16, 0, -16, -16, 0, -16, 0, -16, 0, -16, + // State 71 + 0, 0, 0, 0, -36, 0, -36, 0, -36, -36, -36, -36, -36, -36, -36, -36, 0, -36, -36, -36, 0, -36, -36, -36, 0, -36, -36, 0, -36, 0, -36, 0, -36, + // State 72 + 0, 0, 0, 0, -37, 0, -37, 0, -37, -37, -37, -37, -37, -37, -37, -37, 0, -37, -37, -37, 0, -37, -37, -37, 0, -37, -37, 0, -37, 0, -37, 0, -37, + // State 73 + 0, 0, 0, 0, 0, 0, 14, 0, -40, 0, 0, -40, 0, 0, 0, 0, 0, 0, 0, 0, 0, -40, -40, -40, 0, -40, -40, 0, -40, 0, -40, 0, -40, + // State 74 + 0, 0, 0, 0, -18, 0, -18, 0, -18, -18, -18, -18, -18, -18, -18, -18, 0, -18, -18, -18, 0, -18, -18, -18, 0, -18, -18, 0, -18, 0, -18, 0, -18, + // State 75 + 0, 0, 0, 0, -21, 0, -21, 0, -21, -21, -21, -21, -21, -21, -21, -21, 0, -21, -21, -21, 0, -21, -21, -21, 0, -21, -21, 0, -21, 0, -21, 0, -21, + // State 76 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -45, -45, -45, 0, -45, -45, 0, 0, 0, -45, 0, 0, + // State 77 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -44, -44, -44, 0, -44, -44, 0, 0, 0, -44, 0, 0, + // State 78 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + // State 79 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -46, -46, -46, 0, -46, -46, 0, 0, 0, -46, 0, 0, + // State 80 + 0, 0, 0, 0, 0, 0, 0, 0, -30, 0, 0, 86, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + // State 81 + 0, 0, 0, 0, -15, 0, -15, 0, -15, -15, -15, -15, -15, -15, -15, -15, 0, -15, -15, -15, 0, -15, -15, -15, 0, -15, -15, 0, -15, 0, -15, 0, -15, + // State 82 + -4, -4, -4, -4, 0, -4, 0, -4, 0, 0, 0, 0, -4, 0, 0, 0, 0, 0, 0, 0, -4, 0, 0, 0, -4, 0, 0, 0, 0, -4, 0, 0, 0, + // State 83 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -48, -48, -48, 0, -48, -48, 0, 0, 0, -48, 0, 0, + // State 84 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 87, 0, 0, 0, 0, 0, 0, 0, 0, 0, + // State 85 + -5, -5, -5, -5, 0, -5, 0, -5, 0, 0, 0, 0, -5, 0, 0, 0, 0, 0, 0, 0, -5, 0, 0, 0, -5, 0, 0, 0, 0, -5, 0, 0, 0, + // State 86 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -47, -47, -47, 0, -47, -47, 0, 0, 0, -47, 0, 0, ]; fn __action(state: i8, integer: usize) -> i8 { - __ACTION[(state as usize) * 1 + integer] + __ACTION[(state as usize) * 33 + integer] } const __EOF_ACTION: &[i8] = &[ // State 0 - -1, + -41, // State 1 - -2, + -42, // State 2 - -8, + 0, // State 3 - -6, + 0, // State 4 - -3, + 0, // State 5 + 0, + // State 6 + 0, + // State 7 + 0, + // State 8 + 0, + // State 9 + 0, + // State 10 + 0, + // State 11 + 0, + // State 12 + 0, + // State 13 + 0, + // State 14 + 0, + // State 15 + 0, + // State 16 + 0, + // State 17 + 0, + // State 18 + 0, + // State 19 + 0, + // State 20 + 0, + // State 21 + 0, + // State 22 + 0, + // State 23 + 0, + // State 24 + 0, + // State 25 + 0, + // State 26 + 0, + // State 27 + 0, + // State 28 + 0, + // State 29 + 0, + // State 30 + 0, + // State 31 + -57, + // State 32 + -51, + // State 33 + -52, + // State 34 + 0, + // State 35 + -34, + // State 36 + -22, + // State 37 + -39, + // State 38 + -54, + // State 39 + -9, + // State 40 + 0, + // State 41 + -20, + // State 42 + -6, + // State 43 + -12, + // State 44 + -33, + // State 45 + -11, + // State 46 + -35, + // State 47 + -14, + // State 48 + -13, + // State 49 + -43, + // State 50 + -38, + // State 51 + 0, + // State 52 + -55, + // State 53 + -17, + // State 54 + 0, + // State 55 + -56, + // State 56 + -19, + // State 57 + 0, + // State 58 -7, + // State 59 + -8, + // State 60 + -10, + // State 61 + -24, + // State 62 + -27, + // State 63 + -25, + // State 64 + -23, + // State 65 + -28, + // State 66 + -26, + // State 67 + 0, + // State 68 + 0, + // State 69 + 0, + // State 70 + -16, + // State 71 + -36, + // State 72 + -37, + // State 73 + -40, + // State 74 + -18, + // State 75 + -21, + // State 76 + -45, + // State 77 + -44, + // State 78 + 0, + // State 79 + -46, + // State 80 + 0, + // State 81 + -15, + // State 82 + 0, + // State 83 + -48, + // State 84 + 0, + // State 85 + 0, + // State 86 + -47, ]; fn __goto(state: i8, nt: usize) -> i8 { match nt { - 0 => 2, - 1 => match state { - 1 => 5, - _ => 3, + 2 => 29, + 3 => match state { + 14 => 61, + 15 => 62, + 16 => 63, + 17 => 64, + 18 => 65, + 19 => 66, + _ => 36, + }, + 4 => match state { + 24 => 73, + _ => 37, + }, + 5 => 38, + 6 => match state { + 13 => 60, + _ => 39, + }, + 7 => 68, + 9 => match state { + 3 => 40, + 7 => 54, + 21 => 69, + 26 => 77, + 29 => 80, + _ => 27, + }, + 10 => match state { + 2 => 34, + 4 => 51, + 6 => 53, + 9 => 56, + 25 => 74, + _ => 41, + }, + 11 => match state { + 11 => 58, + 12 => 59, + _ => 42, + }, + 12 => 43, + 13 => 44, + 14 => 31, + 15 => 45, + 16 => match state { + 1 | 28 => 33, + _ => 32, + }, + 18 => match state { + 0 => 1, + _ => 28, + }, + 19 => match state { + 27 => 78, + 30 => 84, + _ => 67, + }, + 20 => match state { + 5 => 52, + 8 => 55, + 22 => 71, + 23 => 72, + _ => 46, }, - 3 => 1, _ => 0, } } + #[allow(clippy::needless_raw_string_hashes)] const __TERMINAL: &[&str] = &[ - r###""hello""###, + r###"r#"\"[^\"]*\""#"###, + r###"r#"[0-9]+(\\.[0-9]+)?"#"###, + r###"r#"[a-zA-Z_][a-zA-Z0-9_]*"#"###, + r###""!""###, + r###""!=""###, + r###""$""###, + r###""&&""###, + r###""(""###, + r###"")""###, + r###""*""###, + r###""+""###, + r###"",""###, + r###""-""###, + r###""/""###, + r###""<""###, + r###""<=""###, + r###""=""###, + r###""==""###, + r###"">""###, + r###"">=""###, + r###""@""###, + r###""Else""###, + r###""EndFor""###, + r###""EndIf""###, + r###""False""###, + r###""For""###, + r###""If""###, + r###""In""###, + r###""Then""###, + r###""True""###, + r###""Var""###, + r###""assigned""###, + r###""||""###, ]; fn __expected_tokens(__state: i8) -> alloc::vec::Vec { __TERMINAL.iter().enumerate().filter_map(|(index, terminal)| { @@ -95,7 +521,7 @@ mod __parse__Program { } }).collect() } - pub(crate) struct __StateMachine<'input> + struct __StateMachine<'input> where { input: &'input str, @@ -109,7 +535,7 @@ mod __parse__Program { type Token = Token<'input>; type TokenIndex = usize; type Symbol = __Symbol<'input>; - type Success = (); + type Success = Program; type StateIndex = i8; type Action = i8; type ReduceIndex = i8; @@ -137,7 +563,7 @@ mod __parse__Program { #[inline] fn error_action(&self, state: i8) -> i8 { - __action(state, 1 - 1) + __action(state, 33 - 1) } #[inline] @@ -203,8 +629,41 @@ mod __parse__Program { _: core::marker::PhantomData<(&'input ())>, ) -> Option { - match *__token { + #[warn(unused_variables)] + match __token { Token(0, _) if true => Some(0), + Token(1, _) if true => Some(1), + Token(2, _) if true => Some(2), + Token(4, _) if true => Some(3), + Token(5, _) if true => Some(4), + Token(6, _) if true => Some(5), + Token(7, _) if true => Some(6), + Token(8, _) if true => Some(7), + Token(9, _) if true => Some(8), + Token(10, _) if true => Some(9), + Token(11, _) if true => Some(10), + Token(12, _) if true => Some(11), + Token(13, _) if true => Some(12), + Token(14, _) if true => Some(13), + Token(15, _) if true => Some(14), + Token(16, _) if true => Some(15), + Token(17, _) if true => Some(16), + Token(18, _) if true => Some(17), + Token(19, _) if true => Some(18), + Token(20, _) if true => Some(19), + Token(21, _) if true => Some(20), + Token(22, _) if true => Some(21), + Token(23, _) if true => Some(22), + Token(24, _) if true => Some(23), + Token(25, _) if true => Some(24), + Token(26, _) if true => Some(25), + Token(27, _) if true => Some(26), + Token(28, _) if true => Some(27), + Token(29, _) if true => Some(28), + Token(30, _) if true => Some(29), + Token(31, _) if true => Some(30), + Token(32, _) if true => Some(31), + Token(33, _) if true => Some(32), _ => None, } } @@ -216,9 +675,9 @@ mod __parse__Program { _: core::marker::PhantomData<(&'input ())>, ) -> __Symbol<'input> { - match __token_index { - 0 => match __token { - Token(0, __tok0) if true => __Symbol::Variant0(__tok0), + #[allow(clippy::manual_range_patterns)]match __token_index { + 0 | 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 => match __token { + Token(0, __tok0) | Token(1, __tok0) | Token(2, __tok0) | Token(4, __tok0) | Token(5, __tok0) | Token(6, __tok0) | Token(7, __tok0) | Token(8, __tok0) | Token(9, __tok0) | Token(10, __tok0) | Token(11, __tok0) | Token(12, __tok0) | Token(13, __tok0) | Token(14, __tok0) | Token(15, __tok0) | Token(16, __tok0) | Token(17, __tok0) | Token(18, __tok0) | Token(19, __tok0) | Token(20, __tok0) | Token(21, __tok0) | Token(22, __tok0) | Token(23, __tok0) | Token(24, __tok0) | Token(25, __tok0) | Token(26, __tok0) | Token(27, __tok0) | Token(28, __tok0) | Token(29, __tok0) | Token(30, __tok0) | Token(31, __tok0) | Token(32, __tok0) | Token(33, __tok0) if true => __Symbol::Variant0(__tok0), _ => unreachable!(), }, _ => unreachable!(), @@ -234,14 +693,14 @@ mod __parse__Program { match __reduce_index { 0 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 0, + states_to_pop: 2, nonterminal_produced: 0, } } 1 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, - nonterminal_produced: 0, + states_to_pop: 0, + nonterminal_produced: 1, } } 2 => { @@ -252,13 +711,13 @@ mod __parse__Program { } 3 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 0, + states_to_pop: 2, nonterminal_produced: 2, } } 4 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 1, + states_to_pop: 3, nonterminal_produced: 2, } } @@ -270,12 +729,306 @@ mod __parse__Program { } 6 => { __state_machine::SimulatedReduce::Reduce { - states_to_pop: 2, + states_to_pop: 3, nonterminal_produced: 3, } } - 7 => __state_machine::SimulatedReduce::Accept, - _ => panic!("invalid reduction index {}", __reduce_index) + 7 => { + __state_machine::SimulatedReduce::Reduce { + states_to_pop: 3, + nonterminal_produced: 3, + } + } + 8 => { + __state_machine::SimulatedReduce::Reduce { + states_to_pop: 1, + nonterminal_produced: 4, + } + } + 9 => { + __state_machine::SimulatedReduce::Reduce { + states_to_pop: 3, + nonterminal_produced: 4, + } + } + 10 => { + __state_machine::SimulatedReduce::Reduce { + states_to_pop: 1, + nonterminal_produced: 5, + } + } + 11 => { + __state_machine::SimulatedReduce::Reduce { + states_to_pop: 1, + nonterminal_produced: 5, + } + } + 12 => { + __state_machine::SimulatedReduce::Reduce { + states_to_pop: 1, + nonterminal_produced: 5, + } + } + 13 => { + __state_machine::SimulatedReduce::Reduce { + states_to_pop: 1, + nonterminal_produced: 5, + } + } + 14 => { + __state_machine::SimulatedReduce::Reduce { + states_to_pop: 4, + nonterminal_produced: 5, + } + } + 15 => { + __state_machine::SimulatedReduce::Reduce { + states_to_pop: 3, + nonterminal_produced: 5, + } + } + 16 => { + __state_machine::SimulatedReduce::Reduce { + states_to_pop: 2, + nonterminal_produced: 5, + } + } + 17 => { + __state_machine::SimulatedReduce::Reduce { + states_to_pop: 3, + nonterminal_produced: 5, + } + } + 18 => { + __state_machine::SimulatedReduce::Reduce { + states_to_pop: 2, + nonterminal_produced: 5, + } + } + 19 => { + __state_machine::SimulatedReduce::Reduce { + states_to_pop: 1, + nonterminal_produced: 5, + } + } + 20 => { + __state_machine::SimulatedReduce::Reduce { + states_to_pop: 3, + nonterminal_produced: 5, + } + } + 21 => { + __state_machine::SimulatedReduce::Reduce { + states_to_pop: 1, + nonterminal_produced: 6, + } + } + 22 => { + __state_machine::SimulatedReduce::Reduce { + states_to_pop: 3, + nonterminal_produced: 6, + } + } + 23 => { + __state_machine::SimulatedReduce::Reduce { + states_to_pop: 3, + nonterminal_produced: 6, + } + } + 24 => { + __state_machine::SimulatedReduce::Reduce { + states_to_pop: 3, + nonterminal_produced: 6, + } + } + 25 => { + __state_machine::SimulatedReduce::Reduce { + states_to_pop: 3, + nonterminal_produced: 6, + } + } + 26 => { + __state_machine::SimulatedReduce::Reduce { + states_to_pop: 3, + nonterminal_produced: 6, + } + } + 27 => { + __state_machine::SimulatedReduce::Reduce { + states_to_pop: 3, + nonterminal_produced: 6, + } + } + 28 => { + __state_machine::SimulatedReduce::Reduce { + states_to_pop: 1, + nonterminal_produced: 7, + } + } + 29 => { + __state_machine::SimulatedReduce::Reduce { + states_to_pop: 2, + nonterminal_produced: 7, + } + } + 30 => { + __state_machine::SimulatedReduce::Reduce { + states_to_pop: 1, + nonterminal_produced: 8, + } + } + 31 => { + __state_machine::SimulatedReduce::Reduce { + states_to_pop: 0, + nonterminal_produced: 8, + } + } + 32 => { + __state_machine::SimulatedReduce::Reduce { + states_to_pop: 1, + nonterminal_produced: 9, + } + } + 33 => { + __state_machine::SimulatedReduce::Reduce { + states_to_pop: 1, + nonterminal_produced: 10, + } + } + 34 => { + __state_machine::SimulatedReduce::Reduce { + states_to_pop: 1, + nonterminal_produced: 11, + } + } + 35 => { + __state_machine::SimulatedReduce::Reduce { + states_to_pop: 3, + nonterminal_produced: 11, + } + } + 36 => { + __state_machine::SimulatedReduce::Reduce { + states_to_pop: 3, + nonterminal_produced: 11, + } + } + 37 => { + __state_machine::SimulatedReduce::Reduce { + states_to_pop: 1, + nonterminal_produced: 12, + } + } + 38 => { + __state_machine::SimulatedReduce::Reduce { + states_to_pop: 1, + nonterminal_produced: 13, + } + } + 39 => { + __state_machine::SimulatedReduce::Reduce { + states_to_pop: 3, + nonterminal_produced: 13, + } + } + 40 => { + __state_machine::SimulatedReduce::Reduce { + states_to_pop: 0, + nonterminal_produced: 14, + } + } + 41 => { + __state_machine::SimulatedReduce::Reduce { + states_to_pop: 1, + nonterminal_produced: 14, + } + } + 42 => { + __state_machine::SimulatedReduce::Reduce { + states_to_pop: 1, + nonterminal_produced: 15, + } + } + 43 => { + __state_machine::SimulatedReduce::Reduce { + states_to_pop: 4, + nonterminal_produced: 16, + } + } + 44 => { + __state_machine::SimulatedReduce::Reduce { + states_to_pop: 4, + nonterminal_produced: 16, + } + } + 45 => { + __state_machine::SimulatedReduce::Reduce { + states_to_pop: 5, + nonterminal_produced: 16, + } + } + 46 => { + __state_machine::SimulatedReduce::Reduce { + states_to_pop: 7, + nonterminal_produced: 16, + } + } + 47 => { + __state_machine::SimulatedReduce::Reduce { + states_to_pop: 6, + nonterminal_produced: 16, + } + } + 48 => { + __state_machine::SimulatedReduce::Reduce { + states_to_pop: 0, + nonterminal_produced: 17, + } + } + 49 => { + __state_machine::SimulatedReduce::Reduce { + states_to_pop: 1, + nonterminal_produced: 17, + } + } + 50 => { + __state_machine::SimulatedReduce::Reduce { + states_to_pop: 1, + nonterminal_produced: 18, + } + } + 51 => { + __state_machine::SimulatedReduce::Reduce { + states_to_pop: 2, + nonterminal_produced: 18, + } + } + 52 => { + __state_machine::SimulatedReduce::Reduce { + states_to_pop: 1, + nonterminal_produced: 19, + } + } + 53 => { + __state_machine::SimulatedReduce::Reduce { + states_to_pop: 1, + nonterminal_produced: 20, + } + } + 54 => { + __state_machine::SimulatedReduce::Reduce { + states_to_pop: 2, + nonterminal_produced: 20, + } + } + 55 => { + __state_machine::SimulatedReduce::Reduce { + states_to_pop: 2, + nonterminal_produced: 20, + } + } + 56 => __state_machine::SimulatedReduce::Accept, + _ => panic!("invalid reduction index {__reduce_index}") } } pub struct ProgramParser { @@ -283,6 +1036,7 @@ mod __parse__Program { _priv: (), } + impl Default for ProgramParser { fn default() -> Self { Self::new() } } impl ProgramParser { pub fn new() -> ProgramParser { let __builder = super::__intern_token::new_builder(); @@ -298,7 +1052,7 @@ mod __parse__Program { >( &self, input: &'input str, - ) -> Result<(), __lalrpop_util::ParseError, &'static str>> + ) -> Result, &'static str>> { let mut __tokens = self.builder.matcher(input); __state_machine::Parser::drive( @@ -343,7 +1097,7 @@ mod __parse__Program { __states.push(__next_state); } } - pub(crate) fn __reduce< + fn __reduce< 'input, >( input: &'input str, @@ -352,7 +1106,7 @@ mod __parse__Program { __states: &mut alloc::vec::Vec, __symbols: &mut alloc::vec::Vec<(usize,__Symbol<'input>,usize)>, _: core::marker::PhantomData<(&'input ())>, - ) -> Option, &'static str>>> + ) -> Option, &'static str>>> { let (__pop_states, __nonterminal) = match __action { 0 => { @@ -377,14 +1131,161 @@ mod __parse__Program { __reduce6(input, __lookahead_start, __symbols, core::marker::PhantomData::<(&())>) } 7 => { + __reduce7(input, __lookahead_start, __symbols, core::marker::PhantomData::<(&())>) + } + 8 => { + __reduce8(input, __lookahead_start, __symbols, core::marker::PhantomData::<(&())>) + } + 9 => { + __reduce9(input, __lookahead_start, __symbols, core::marker::PhantomData::<(&())>) + } + 10 => { + __reduce10(input, __lookahead_start, __symbols, core::marker::PhantomData::<(&())>) + } + 11 => { + __reduce11(input, __lookahead_start, __symbols, core::marker::PhantomData::<(&())>) + } + 12 => { + __reduce12(input, __lookahead_start, __symbols, core::marker::PhantomData::<(&())>) + } + 13 => { + __reduce13(input, __lookahead_start, __symbols, core::marker::PhantomData::<(&())>) + } + 14 => { + __reduce14(input, __lookahead_start, __symbols, core::marker::PhantomData::<(&())>) + } + 15 => { + __reduce15(input, __lookahead_start, __symbols, core::marker::PhantomData::<(&())>) + } + 16 => { + __reduce16(input, __lookahead_start, __symbols, core::marker::PhantomData::<(&())>) + } + 17 => { + __reduce17(input, __lookahead_start, __symbols, core::marker::PhantomData::<(&())>) + } + 18 => { + __reduce18(input, __lookahead_start, __symbols, core::marker::PhantomData::<(&())>) + } + 19 => { + __reduce19(input, __lookahead_start, __symbols, core::marker::PhantomData::<(&())>) + } + 20 => { + __reduce20(input, __lookahead_start, __symbols, core::marker::PhantomData::<(&())>) + } + 21 => { + __reduce21(input, __lookahead_start, __symbols, core::marker::PhantomData::<(&())>) + } + 22 => { + __reduce22(input, __lookahead_start, __symbols, core::marker::PhantomData::<(&())>) + } + 23 => { + __reduce23(input, __lookahead_start, __symbols, core::marker::PhantomData::<(&())>) + } + 24 => { + __reduce24(input, __lookahead_start, __symbols, core::marker::PhantomData::<(&())>) + } + 25 => { + __reduce25(input, __lookahead_start, __symbols, core::marker::PhantomData::<(&())>) + } + 26 => { + __reduce26(input, __lookahead_start, __symbols, core::marker::PhantomData::<(&())>) + } + 27 => { + __reduce27(input, __lookahead_start, __symbols, core::marker::PhantomData::<(&())>) + } + 28 => { + __reduce28(input, __lookahead_start, __symbols, core::marker::PhantomData::<(&())>) + } + 29 => { + __reduce29(input, __lookahead_start, __symbols, core::marker::PhantomData::<(&())>) + } + 30 => { + __reduce30(input, __lookahead_start, __symbols, core::marker::PhantomData::<(&())>) + } + 31 => { + __reduce31(input, __lookahead_start, __symbols, core::marker::PhantomData::<(&())>) + } + 32 => { + __reduce32(input, __lookahead_start, __symbols, core::marker::PhantomData::<(&())>) + } + 33 => { + __reduce33(input, __lookahead_start, __symbols, core::marker::PhantomData::<(&())>) + } + 34 => { + __reduce34(input, __lookahead_start, __symbols, core::marker::PhantomData::<(&())>) + } + 35 => { + __reduce35(input, __lookahead_start, __symbols, core::marker::PhantomData::<(&())>) + } + 36 => { + __reduce36(input, __lookahead_start, __symbols, core::marker::PhantomData::<(&())>) + } + 37 => { + __reduce37(input, __lookahead_start, __symbols, core::marker::PhantomData::<(&())>) + } + 38 => { + __reduce38(input, __lookahead_start, __symbols, core::marker::PhantomData::<(&())>) + } + 39 => { + __reduce39(input, __lookahead_start, __symbols, core::marker::PhantomData::<(&())>) + } + 40 => { + __reduce40(input, __lookahead_start, __symbols, core::marker::PhantomData::<(&())>) + } + 41 => { + __reduce41(input, __lookahead_start, __symbols, core::marker::PhantomData::<(&())>) + } + 42 => { + __reduce42(input, __lookahead_start, __symbols, core::marker::PhantomData::<(&())>) + } + 43 => { + __reduce43(input, __lookahead_start, __symbols, core::marker::PhantomData::<(&())>) + } + 44 => { + __reduce44(input, __lookahead_start, __symbols, core::marker::PhantomData::<(&())>) + } + 45 => { + __reduce45(input, __lookahead_start, __symbols, core::marker::PhantomData::<(&())>) + } + 46 => { + __reduce46(input, __lookahead_start, __symbols, core::marker::PhantomData::<(&())>) + } + 47 => { + __reduce47(input, __lookahead_start, __symbols, core::marker::PhantomData::<(&())>) + } + 48 => { + __reduce48(input, __lookahead_start, __symbols, core::marker::PhantomData::<(&())>) + } + 49 => { + __reduce49(input, __lookahead_start, __symbols, core::marker::PhantomData::<(&())>) + } + 50 => { + __reduce50(input, __lookahead_start, __symbols, core::marker::PhantomData::<(&())>) + } + 51 => { + __reduce51(input, __lookahead_start, __symbols, core::marker::PhantomData::<(&())>) + } + 52 => { + __reduce52(input, __lookahead_start, __symbols, core::marker::PhantomData::<(&())>) + } + 53 => { + __reduce53(input, __lookahead_start, __symbols, core::marker::PhantomData::<(&())>) + } + 54 => { + __reduce54(input, __lookahead_start, __symbols, core::marker::PhantomData::<(&())>) + } + 55 => { + __reduce55(input, __lookahead_start, __symbols, core::marker::PhantomData::<(&())>) + } + 56 => { // __Program = Program => ActionFn(0); - let __sym0 = __pop_Variant1(__symbols); - let __start = __sym0.0; - let __end = __sym0.2; + let __sym0 = __pop_Variant7(__symbols); + let __start = __sym0.0.clone(); + let __end = __sym0.2.clone(); let __nt = super::__action0::<>(input, __sym0); return Some(Ok(__nt)); } - _ => panic!("invalid action code {}", __action) + _ => panic!("invalid action code {__action}") }; let __states_len = __states.len(); __states.truncate(__states_len - __pop_states); @@ -401,24 +1302,112 @@ mod __parse__Program { 'input, >( __symbols: &mut alloc::vec::Vec<(usize,__Symbol<'input>,usize)> - ) -> (usize, (), usize) + ) -> (usize, Expression, usize) { match __symbols.pop() { Some((__l, __Symbol::Variant1(__v), __r)) => (__l, __v, __r), _ => __symbol_type_mismatch() } } + fn __pop_Variant4< + 'input, + >( + __symbols: &mut alloc::vec::Vec<(usize,__Symbol<'input>,usize)> + ) -> (usize, Option>, usize) + { + match __symbols.pop() { + Some((__l, __Symbol::Variant4(__v), __r)) => (__l, __v, __r), + _ => __symbol_type_mismatch() + } + } + fn __pop_Variant7< + 'input, + >( + __symbols: &mut alloc::vec::Vec<(usize,__Symbol<'input>,usize)> + ) -> (usize, Program, usize) + { + match __symbols.pop() { + Some((__l, __Symbol::Variant7(__v), __r)) => (__l, __v, __r), + _ => __symbol_type_mismatch() + } + } + fn __pop_Variant8< + 'input, + >( + __symbols: &mut alloc::vec::Vec<(usize,__Symbol<'input>,usize)> + ) -> (usize, Statement, usize) + { + match __symbols.pop() { + Some((__l, __Symbol::Variant8(__v), __r)) => (__l, __v, __r), + _ => __symbol_type_mismatch() + } + } + fn __pop_Variant5< + 'input, + >( + __symbols: &mut alloc::vec::Vec<(usize,__Symbol<'input>,usize)> + ) -> (usize, String, usize) + { + match __symbols.pop() { + Some((__l, __Symbol::Variant5(__v), __r)) => (__l, __v, __r), + _ => __symbol_type_mismatch() + } + } + fn __pop_Variant3< + 'input, + >( + __symbols: &mut alloc::vec::Vec<(usize,__Symbol<'input>,usize)> + ) -> (usize, Vec, usize) + { + match __symbols.pop() { + Some((__l, __Symbol::Variant3(__v), __r)) => (__l, __v, __r), + _ => __symbol_type_mismatch() + } + } + fn __pop_Variant10< + 'input, + >( + __symbols: &mut alloc::vec::Vec<(usize,__Symbol<'input>,usize)> + ) -> (usize, Vec, usize) + { + match __symbols.pop() { + Some((__l, __Symbol::Variant10(__v), __r)) => (__l, __v, __r), + _ => __symbol_type_mismatch() + } + } fn __pop_Variant2< 'input, >( __symbols: &mut alloc::vec::Vec<(usize,__Symbol<'input>,usize)> - ) -> (usize, alloc::vec::Vec<()>, usize) + ) -> (usize, alloc::vec::Vec, usize) { match __symbols.pop() { Some((__l, __Symbol::Variant2(__v), __r)) => (__l, __v, __r), _ => __symbol_type_mismatch() } } + fn __pop_Variant9< + 'input, + >( + __symbols: &mut alloc::vec::Vec<(usize,__Symbol<'input>,usize)> + ) -> (usize, alloc::vec::Vec, usize) + { + match __symbols.pop() { + Some((__l, __Symbol::Variant9(__v), __r)) => (__l, __v, __r), + _ => __symbol_type_mismatch() + } + } + fn __pop_Variant6< + 'input, + >( + __symbols: &mut alloc::vec::Vec<(usize,__Symbol<'input>,usize)> + ) -> (usize, f64, usize) + { + match __symbols.pop() { + Some((__l, __Symbol::Variant6(__v), __r)) => (__l, __v, __r), + _ => __symbol_type_mismatch() + } + } fn __pop_Variant0< 'input, >( @@ -430,7 +1419,7 @@ mod __parse__Program { _ => __symbol_type_mismatch() } } - pub(crate) fn __reduce0< + fn __reduce0< 'input, >( input: &'input str, @@ -439,14 +1428,17 @@ mod __parse__Program { _: core::marker::PhantomData<(&'input ())>, ) -> (usize, usize) { - // Program = => ActionFn(7); - let __start = __lookahead_start.cloned().or_else(|| __symbols.last().map(|s| s.2.clone())).unwrap_or_default(); - let __end = __start.clone(); - let __nt = super::__action7::<>(input, &__start, &__end); + // ( ",") = Expr, "," => ActionFn(51); + assert!(__symbols.len() >= 2); + let __sym1 = __pop_Variant0(__symbols); + let __sym0 = __pop_Variant1(__symbols); + let __start = __sym0.0.clone(); + let __end = __sym1.2.clone(); + let __nt = super::__action51::<>(input, __sym0, __sym1); __symbols.push((__start, __Symbol::Variant1(__nt), __end)); - (0, 0) + (2, 0) } - pub(crate) fn __reduce1< + fn __reduce1< 'input, >( input: &'input str, @@ -455,32 +1447,31 @@ mod __parse__Program { _: core::marker::PhantomData<(&'input ())>, ) -> (usize, usize) { - // Program = Statement+ => ActionFn(8); + // ( ",")* = => ActionFn(49); + let __start = __lookahead_start.cloned().or_else(|| __symbols.last().map(|s| s.2)).unwrap_or_default(); + let __end = __start; + let __nt = super::__action49::<>(input, &__start, &__end); + __symbols.push((__start, __Symbol::Variant2(__nt), __end)); + (0, 1) + } + fn __reduce2< + 'input, + >( + input: &'input str, + __lookahead_start: Option<&usize>, + __symbols: &mut alloc::vec::Vec<(usize,__Symbol<'input>,usize)>, + _: core::marker::PhantomData<(&'input ())>, + ) -> (usize, usize) + { + // ( ",")* = ( ",")+ => ActionFn(50); let __sym0 = __pop_Variant2(__symbols); - let __start = __sym0.0; - let __end = __sym0.2; - let __nt = super::__action8::<>(input, __sym0); - __symbols.push((__start, __Symbol::Variant1(__nt), __end)); - (1, 0) - } - pub(crate) fn __reduce2< - 'input, - >( - input: &'input str, - __lookahead_start: Option<&usize>, - __symbols: &mut alloc::vec::Vec<(usize,__Symbol<'input>,usize)>, - _: core::marker::PhantomData<(&'input ())>, - ) -> (usize, usize) - { - // Statement = "hello" => ActionFn(2); - let __sym0 = __pop_Variant0(__symbols); - let __start = __sym0.0; - let __end = __sym0.2; - let __nt = super::__action2::<>(input, __sym0); - __symbols.push((__start, __Symbol::Variant1(__nt), __end)); + let __start = __sym0.0.clone(); + let __end = __sym0.2.clone(); + let __nt = super::__action50::<>(input, __sym0); + __symbols.push((__start, __Symbol::Variant2(__nt), __end)); (1, 1) } - pub(crate) fn __reduce3< + fn __reduce3< 'input, >( input: &'input str, @@ -489,48 +1480,54 @@ mod __parse__Program { _: core::marker::PhantomData<(&'input ())>, ) -> (usize, usize) { - // Statement* = => ActionFn(3); - let __start = __lookahead_start.cloned().or_else(|| __symbols.last().map(|s| s.2.clone())).unwrap_or_default(); - let __end = __start.clone(); - let __nt = super::__action3::<>(input, &__start, &__end); - __symbols.push((__start, __Symbol::Variant2(__nt), __end)); - (0, 2) - } - pub(crate) fn __reduce4< - 'input, - >( - input: &'input str, - __lookahead_start: Option<&usize>, - __symbols: &mut alloc::vec::Vec<(usize,__Symbol<'input>,usize)>, - _: core::marker::PhantomData<(&'input ())>, - ) -> (usize, usize) - { - // Statement* = Statement+ => ActionFn(4); - let __sym0 = __pop_Variant2(__symbols); - let __start = __sym0.0; - let __end = __sym0.2; - let __nt = super::__action4::<>(input, __sym0); - __symbols.push((__start, __Symbol::Variant2(__nt), __end)); - (1, 2) - } - pub(crate) fn __reduce5< - 'input, - >( - input: &'input str, - __lookahead_start: Option<&usize>, - __symbols: &mut alloc::vec::Vec<(usize,__Symbol<'input>,usize)>, - _: core::marker::PhantomData<(&'input ())>, - ) -> (usize, usize) - { - // Statement+ = Statement => ActionFn(5); + // ( ",")+ = Expr, "," => ActionFn(54); + assert!(__symbols.len() >= 2); + let __sym1 = __pop_Variant0(__symbols); let __sym0 = __pop_Variant1(__symbols); - let __start = __sym0.0; - let __end = __sym0.2; - let __nt = super::__action5::<>(input, __sym0); + let __start = __sym0.0.clone(); + let __end = __sym1.2.clone(); + let __nt = super::__action54::<>(input, __sym0, __sym1); __symbols.push((__start, __Symbol::Variant2(__nt), __end)); + (2, 2) + } + fn __reduce4< + 'input, + >( + input: &'input str, + __lookahead_start: Option<&usize>, + __symbols: &mut alloc::vec::Vec<(usize,__Symbol<'input>,usize)>, + _: core::marker::PhantomData<(&'input ())>, + ) -> (usize, usize) + { + // ( ",")+ = ( ",")+, Expr, "," => ActionFn(55); + assert!(__symbols.len() >= 3); + let __sym2 = __pop_Variant0(__symbols); + let __sym1 = __pop_Variant1(__symbols); + let __sym0 = __pop_Variant2(__symbols); + let __start = __sym0.0.clone(); + let __end = __sym2.2.clone(); + let __nt = super::__action55::<>(input, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant2(__nt), __end)); + (3, 2) + } + fn __reduce5< + 'input, + >( + input: &'input str, + __lookahead_start: Option<&usize>, + __symbols: &mut alloc::vec::Vec<(usize,__Symbol<'input>,usize)>, + _: core::marker::PhantomData<(&'input ())>, + ) -> (usize, usize) + { + // AddExpr = MulExpr => ActionFn(19); + let __sym0 = __pop_Variant1(__symbols); + let __start = __sym0.0.clone(); + let __end = __sym0.2.clone(); + let __nt = super::__action19::<>(input, __sym0); + __symbols.push((__start, __Symbol::Variant1(__nt), __end)); (1, 3) } - pub(crate) fn __reduce6< + fn __reduce6< 'input, >( input: &'input str, @@ -539,31 +1536,980 @@ mod __parse__Program { _: core::marker::PhantomData<(&'input ())>, ) -> (usize, usize) { - // Statement+ = Statement+, Statement => ActionFn(6); + // AddExpr = AddExpr, "+", MulExpr => ActionFn(20); + assert!(__symbols.len() >= 3); + let __sym2 = __pop_Variant1(__symbols); + let __sym1 = __pop_Variant0(__symbols); + let __sym0 = __pop_Variant1(__symbols); + let __start = __sym0.0.clone(); + let __end = __sym2.2.clone(); + let __nt = super::__action20::<>(input, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant1(__nt), __end)); + (3, 3) + } + fn __reduce7< + 'input, + >( + input: &'input str, + __lookahead_start: Option<&usize>, + __symbols: &mut alloc::vec::Vec<(usize,__Symbol<'input>,usize)>, + _: core::marker::PhantomData<(&'input ())>, + ) -> (usize, usize) + { + // AddExpr = AddExpr, "-", MulExpr => ActionFn(21); + assert!(__symbols.len() >= 3); + let __sym2 = __pop_Variant1(__symbols); + let __sym1 = __pop_Variant0(__symbols); + let __sym0 = __pop_Variant1(__symbols); + let __start = __sym0.0.clone(); + let __end = __sym2.2.clone(); + let __nt = super::__action21::<>(input, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant1(__nt), __end)); + (3, 3) + } + fn __reduce8< + 'input, + >( + input: &'input str, + __lookahead_start: Option<&usize>, + __symbols: &mut alloc::vec::Vec<(usize,__Symbol<'input>,usize)>, + _: core::marker::PhantomData<(&'input ())>, + ) -> (usize, usize) + { + // AndExpr = CmpExpr => ActionFn(10); + let __sym0 = __pop_Variant1(__symbols); + let __start = __sym0.0.clone(); + let __end = __sym0.2.clone(); + let __nt = super::__action10::<>(input, __sym0); + __symbols.push((__start, __Symbol::Variant1(__nt), __end)); + (1, 4) + } + fn __reduce9< + 'input, + >( + input: &'input str, + __lookahead_start: Option<&usize>, + __symbols: &mut alloc::vec::Vec<(usize,__Symbol<'input>,usize)>, + _: core::marker::PhantomData<(&'input ())>, + ) -> (usize, usize) + { + // AndExpr = AndExpr, "&&", CmpExpr => ActionFn(11); + assert!(__symbols.len() >= 3); + let __sym2 = __pop_Variant1(__symbols); + let __sym1 = __pop_Variant0(__symbols); + let __sym0 = __pop_Variant1(__symbols); + let __start = __sym0.0.clone(); + let __end = __sym2.2.clone(); + let __nt = super::__action11::<>(input, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant1(__nt), __end)); + (3, 4) + } + fn __reduce10< + 'input, + >( + input: &'input str, + __lookahead_start: Option<&usize>, + __symbols: &mut alloc::vec::Vec<(usize,__Symbol<'input>,usize)>, + _: core::marker::PhantomData<(&'input ())>, + ) -> (usize, usize) + { + // AtomExpr = STRING => ActionFn(28); + let __sym0 = __pop_Variant5(__symbols); + let __start = __sym0.0.clone(); + let __end = __sym0.2.clone(); + let __nt = super::__action28::<>(input, __sym0); + __symbols.push((__start, __Symbol::Variant1(__nt), __end)); + (1, 5) + } + fn __reduce11< + 'input, + >( + input: &'input str, + __lookahead_start: Option<&usize>, + __symbols: &mut alloc::vec::Vec<(usize,__Symbol<'input>,usize)>, + _: core::marker::PhantomData<(&'input ())>, + ) -> (usize, usize) + { + // AtomExpr = NUM => ActionFn(29); + let __sym0 = __pop_Variant6(__symbols); + let __start = __sym0.0.clone(); + let __end = __sym0.2.clone(); + let __nt = super::__action29::<>(input, __sym0); + __symbols.push((__start, __Symbol::Variant1(__nt), __end)); + (1, 5) + } + fn __reduce12< + 'input, + >( + input: &'input str, + __lookahead_start: Option<&usize>, + __symbols: &mut alloc::vec::Vec<(usize,__Symbol<'input>,usize)>, + _: core::marker::PhantomData<(&'input ())>, + ) -> (usize, usize) + { + // AtomExpr = "True" => ActionFn(30); + let __sym0 = __pop_Variant0(__symbols); + let __start = __sym0.0.clone(); + let __end = __sym0.2.clone(); + let __nt = super::__action30::<>(input, __sym0); + __symbols.push((__start, __Symbol::Variant1(__nt), __end)); + (1, 5) + } + fn __reduce13< + 'input, + >( + input: &'input str, + __lookahead_start: Option<&usize>, + __symbols: &mut alloc::vec::Vec<(usize,__Symbol<'input>,usize)>, + _: core::marker::PhantomData<(&'input ())>, + ) -> (usize, usize) + { + // AtomExpr = "False" => ActionFn(31); + let __sym0 = __pop_Variant0(__symbols); + let __start = __sym0.0.clone(); + let __end = __sym0.2.clone(); + let __nt = super::__action31::<>(input, __sym0); + __symbols.push((__start, __Symbol::Variant1(__nt), __end)); + (1, 5) + } + fn __reduce14< + 'input, + >( + input: &'input str, + __lookahead_start: Option<&usize>, + __symbols: &mut alloc::vec::Vec<(usize,__Symbol<'input>,usize)>, + _: core::marker::PhantomData<(&'input ())>, + ) -> (usize, usize) + { + // AtomExpr = Ident, "(", Comma, ")" => ActionFn(58); + assert!(__symbols.len() >= 4); + let __sym3 = __pop_Variant0(__symbols); + let __sym2 = __pop_Variant3(__symbols); + let __sym1 = __pop_Variant0(__symbols); + let __sym0 = __pop_Variant5(__symbols); + let __start = __sym0.0.clone(); + let __end = __sym3.2.clone(); + let __nt = super::__action58::<>(input, __sym0, __sym1, __sym2, __sym3); + __symbols.push((__start, __Symbol::Variant1(__nt), __end)); + (4, 5) + } + fn __reduce15< + 'input, + >( + input: &'input str, + __lookahead_start: Option<&usize>, + __symbols: &mut alloc::vec::Vec<(usize,__Symbol<'input>,usize)>, + _: core::marker::PhantomData<(&'input ())>, + ) -> (usize, usize) + { + // AtomExpr = Ident, "(", ")" => ActionFn(59); + assert!(__symbols.len() >= 3); + let __sym2 = __pop_Variant0(__symbols); + let __sym1 = __pop_Variant0(__symbols); + let __sym0 = __pop_Variant5(__symbols); + let __start = __sym0.0.clone(); + let __end = __sym2.2.clone(); + let __nt = super::__action59::<>(input, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant1(__nt), __end)); + (3, 5) + } + fn __reduce16< + 'input, + >( + input: &'input str, + __lookahead_start: Option<&usize>, + __symbols: &mut alloc::vec::Vec<(usize,__Symbol<'input>,usize)>, + _: core::marker::PhantomData<(&'input ())>, + ) -> (usize, usize) + { + // AtomExpr = "$", Ident => ActionFn(33); + assert!(__symbols.len() >= 2); + let __sym1 = __pop_Variant5(__symbols); + let __sym0 = __pop_Variant0(__symbols); + let __start = __sym0.0.clone(); + let __end = __sym1.2.clone(); + let __nt = super::__action33::<>(input, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant1(__nt), __end)); + (2, 5) + } + fn __reduce17< + 'input, + >( + input: &'input str, + __lookahead_start: Option<&usize>, + __symbols: &mut alloc::vec::Vec<(usize,__Symbol<'input>,usize)>, + _: core::marker::PhantomData<(&'input ())>, + ) -> (usize, usize) + { + // AtomExpr = "$", "-", Ident => ActionFn(34); + assert!(__symbols.len() >= 3); + let __sym2 = __pop_Variant5(__symbols); + let __sym1 = __pop_Variant0(__symbols); + let __sym0 = __pop_Variant0(__symbols); + let __start = __sym0.0.clone(); + let __end = __sym2.2.clone(); + let __nt = super::__action34::<>(input, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant1(__nt), __end)); + (3, 5) + } + fn __reduce18< + 'input, + >( + input: &'input str, + __lookahead_start: Option<&usize>, + __symbols: &mut alloc::vec::Vec<(usize,__Symbol<'input>,usize)>, + _: core::marker::PhantomData<(&'input ())>, + ) -> (usize, usize) + { + // AtomExpr = "@", Ident => ActionFn(35); + assert!(__symbols.len() >= 2); + let __sym1 = __pop_Variant5(__symbols); + let __sym0 = __pop_Variant0(__symbols); + let __start = __sym0.0.clone(); + let __end = __sym1.2.clone(); + let __nt = super::__action35::<>(input, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant1(__nt), __end)); + (2, 5) + } + fn __reduce19< + 'input, + >( + input: &'input str, + __lookahead_start: Option<&usize>, + __symbols: &mut alloc::vec::Vec<(usize,__Symbol<'input>,usize)>, + _: core::marker::PhantomData<(&'input ())>, + ) -> (usize, usize) + { + // AtomExpr = Ident => ActionFn(36); + let __sym0 = __pop_Variant5(__symbols); + let __start = __sym0.0.clone(); + let __end = __sym0.2.clone(); + let __nt = super::__action36::<>(input, __sym0); + __symbols.push((__start, __Symbol::Variant1(__nt), __end)); + (1, 5) + } + fn __reduce20< + 'input, + >( + input: &'input str, + __lookahead_start: Option<&usize>, + __symbols: &mut alloc::vec::Vec<(usize,__Symbol<'input>,usize)>, + _: core::marker::PhantomData<(&'input ())>, + ) -> (usize, usize) + { + // AtomExpr = "(", Expr, ")" => ActionFn(37); + assert!(__symbols.len() >= 3); + let __sym2 = __pop_Variant0(__symbols); + let __sym1 = __pop_Variant1(__symbols); + let __sym0 = __pop_Variant0(__symbols); + let __start = __sym0.0.clone(); + let __end = __sym2.2.clone(); + let __nt = super::__action37::<>(input, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant1(__nt), __end)); + (3, 5) + } + fn __reduce21< + 'input, + >( + input: &'input str, + __lookahead_start: Option<&usize>, + __symbols: &mut alloc::vec::Vec<(usize,__Symbol<'input>,usize)>, + _: core::marker::PhantomData<(&'input ())>, + ) -> (usize, usize) + { + // CmpExpr = AddExpr => ActionFn(12); + let __sym0 = __pop_Variant1(__symbols); + let __start = __sym0.0.clone(); + let __end = __sym0.2.clone(); + let __nt = super::__action12::<>(input, __sym0); + __symbols.push((__start, __Symbol::Variant1(__nt), __end)); + (1, 6) + } + fn __reduce22< + 'input, + >( + input: &'input str, + __lookahead_start: Option<&usize>, + __symbols: &mut alloc::vec::Vec<(usize,__Symbol<'input>,usize)>, + _: core::marker::PhantomData<(&'input ())>, + ) -> (usize, usize) + { + // CmpExpr = CmpExpr, "==", AddExpr => ActionFn(13); + assert!(__symbols.len() >= 3); + let __sym2 = __pop_Variant1(__symbols); + let __sym1 = __pop_Variant0(__symbols); + let __sym0 = __pop_Variant1(__symbols); + let __start = __sym0.0.clone(); + let __end = __sym2.2.clone(); + let __nt = super::__action13::<>(input, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant1(__nt), __end)); + (3, 6) + } + fn __reduce23< + 'input, + >( + input: &'input str, + __lookahead_start: Option<&usize>, + __symbols: &mut alloc::vec::Vec<(usize,__Symbol<'input>,usize)>, + _: core::marker::PhantomData<(&'input ())>, + ) -> (usize, usize) + { + // CmpExpr = CmpExpr, "!=", AddExpr => ActionFn(14); + assert!(__symbols.len() >= 3); + let __sym2 = __pop_Variant1(__symbols); + let __sym1 = __pop_Variant0(__symbols); + let __sym0 = __pop_Variant1(__symbols); + let __start = __sym0.0.clone(); + let __end = __sym2.2.clone(); + let __nt = super::__action14::<>(input, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant1(__nt), __end)); + (3, 6) + } + fn __reduce24< + 'input, + >( + input: &'input str, + __lookahead_start: Option<&usize>, + __symbols: &mut alloc::vec::Vec<(usize,__Symbol<'input>,usize)>, + _: core::marker::PhantomData<(&'input ())>, + ) -> (usize, usize) + { + // CmpExpr = CmpExpr, "<=", AddExpr => ActionFn(15); + assert!(__symbols.len() >= 3); + let __sym2 = __pop_Variant1(__symbols); + let __sym1 = __pop_Variant0(__symbols); + let __sym0 = __pop_Variant1(__symbols); + let __start = __sym0.0.clone(); + let __end = __sym2.2.clone(); + let __nt = super::__action15::<>(input, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant1(__nt), __end)); + (3, 6) + } + fn __reduce25< + 'input, + >( + input: &'input str, + __lookahead_start: Option<&usize>, + __symbols: &mut alloc::vec::Vec<(usize,__Symbol<'input>,usize)>, + _: core::marker::PhantomData<(&'input ())>, + ) -> (usize, usize) + { + // CmpExpr = CmpExpr, ">=", AddExpr => ActionFn(16); + assert!(__symbols.len() >= 3); + let __sym2 = __pop_Variant1(__symbols); + let __sym1 = __pop_Variant0(__symbols); + let __sym0 = __pop_Variant1(__symbols); + let __start = __sym0.0.clone(); + let __end = __sym2.2.clone(); + let __nt = super::__action16::<>(input, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant1(__nt), __end)); + (3, 6) + } + fn __reduce26< + 'input, + >( + input: &'input str, + __lookahead_start: Option<&usize>, + __symbols: &mut alloc::vec::Vec<(usize,__Symbol<'input>,usize)>, + _: core::marker::PhantomData<(&'input ())>, + ) -> (usize, usize) + { + // CmpExpr = CmpExpr, "<", AddExpr => ActionFn(17); + assert!(__symbols.len() >= 3); + let __sym2 = __pop_Variant1(__symbols); + let __sym1 = __pop_Variant0(__symbols); + let __sym0 = __pop_Variant1(__symbols); + let __start = __sym0.0.clone(); + let __end = __sym2.2.clone(); + let __nt = super::__action17::<>(input, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant1(__nt), __end)); + (3, 6) + } + fn __reduce27< + 'input, + >( + input: &'input str, + __lookahead_start: Option<&usize>, + __symbols: &mut alloc::vec::Vec<(usize,__Symbol<'input>,usize)>, + _: core::marker::PhantomData<(&'input ())>, + ) -> (usize, usize) + { + // CmpExpr = CmpExpr, ">", AddExpr => ActionFn(18); + assert!(__symbols.len() >= 3); + let __sym2 = __pop_Variant1(__symbols); + let __sym1 = __pop_Variant0(__symbols); + let __sym0 = __pop_Variant1(__symbols); + let __start = __sym0.0.clone(); + let __end = __sym2.2.clone(); + let __nt = super::__action18::<>(input, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant1(__nt), __end)); + (3, 6) + } + fn __reduce28< + 'input, + >( + input: &'input str, + __lookahead_start: Option<&usize>, + __symbols: &mut alloc::vec::Vec<(usize,__Symbol<'input>,usize)>, + _: core::marker::PhantomData<(&'input ())>, + ) -> (usize, usize) + { + // Comma = Expr => ActionFn(56); + let __sym0 = __pop_Variant1(__symbols); + let __start = __sym0.0.clone(); + let __end = __sym0.2.clone(); + let __nt = super::__action56::<>(input, __sym0); + __symbols.push((__start, __Symbol::Variant3(__nt), __end)); + (1, 7) + } + fn __reduce29< + 'input, + >( + input: &'input str, + __lookahead_start: Option<&usize>, + __symbols: &mut alloc::vec::Vec<(usize,__Symbol<'input>,usize)>, + _: core::marker::PhantomData<(&'input ())>, + ) -> (usize, usize) + { + // Comma = ( ",")+, Expr => ActionFn(57); assert!(__symbols.len() >= 2); let __sym1 = __pop_Variant1(__symbols); let __sym0 = __pop_Variant2(__symbols); - let __start = __sym0.0; - let __end = __sym1.2; - let __nt = super::__action6::<>(input, __sym0, __sym1); - __symbols.push((__start, __Symbol::Variant2(__nt), __end)); - (2, 3) + let __start = __sym0.0.clone(); + let __end = __sym1.2.clone(); + let __nt = super::__action57::<>(input, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant3(__nt), __end)); + (2, 7) + } + fn __reduce30< + 'input, + >( + input: &'input str, + __lookahead_start: Option<&usize>, + __symbols: &mut alloc::vec::Vec<(usize,__Symbol<'input>,usize)>, + _: core::marker::PhantomData<(&'input ())>, + ) -> (usize, usize) + { + // Comma? = Comma => ActionFn(44); + let __sym0 = __pop_Variant3(__symbols); + let __start = __sym0.0.clone(); + let __end = __sym0.2.clone(); + let __nt = super::__action44::<>(input, __sym0); + __symbols.push((__start, __Symbol::Variant4(__nt), __end)); + (1, 8) + } + fn __reduce31< + 'input, + >( + input: &'input str, + __lookahead_start: Option<&usize>, + __symbols: &mut alloc::vec::Vec<(usize,__Symbol<'input>,usize)>, + _: core::marker::PhantomData<(&'input ())>, + ) -> (usize, usize) + { + // Comma? = => ActionFn(45); + let __start = __lookahead_start.cloned().or_else(|| __symbols.last().map(|s| s.2)).unwrap_or_default(); + let __end = __start; + let __nt = super::__action45::<>(input, &__start, &__end); + __symbols.push((__start, __Symbol::Variant4(__nt), __end)); + (0, 8) + } + fn __reduce32< + 'input, + >( + input: &'input str, + __lookahead_start: Option<&usize>, + __symbols: &mut alloc::vec::Vec<(usize,__Symbol<'input>,usize)>, + _: core::marker::PhantomData<(&'input ())>, + ) -> (usize, usize) + { + // Expr = OrExpr => ActionFn(7); + let __sym0 = __pop_Variant1(__symbols); + let __start = __sym0.0.clone(); + let __end = __sym0.2.clone(); + let __nt = super::__action7::<>(input, __sym0); + __symbols.push((__start, __Symbol::Variant1(__nt), __end)); + (1, 9) + } + fn __reduce33< + 'input, + >( + input: &'input str, + __lookahead_start: Option<&usize>, + __symbols: &mut alloc::vec::Vec<(usize,__Symbol<'input>,usize)>, + _: core::marker::PhantomData<(&'input ())>, + ) -> (usize, usize) + { + // Ident = r#"[a-zA-Z_][a-zA-Z0-9_]*"# => ActionFn(41); + let __sym0 = __pop_Variant0(__symbols); + let __start = __sym0.0.clone(); + let __end = __sym0.2.clone(); + let __nt = super::__action41::<>(input, __sym0); + __symbols.push((__start, __Symbol::Variant5(__nt), __end)); + (1, 10) + } + fn __reduce34< + 'input, + >( + input: &'input str, + __lookahead_start: Option<&usize>, + __symbols: &mut alloc::vec::Vec<(usize,__Symbol<'input>,usize)>, + _: core::marker::PhantomData<(&'input ())>, + ) -> (usize, usize) + { + // MulExpr = UnExpr => ActionFn(22); + let __sym0 = __pop_Variant1(__symbols); + let __start = __sym0.0.clone(); + let __end = __sym0.2.clone(); + let __nt = super::__action22::<>(input, __sym0); + __symbols.push((__start, __Symbol::Variant1(__nt), __end)); + (1, 11) + } + fn __reduce35< + 'input, + >( + input: &'input str, + __lookahead_start: Option<&usize>, + __symbols: &mut alloc::vec::Vec<(usize,__Symbol<'input>,usize)>, + _: core::marker::PhantomData<(&'input ())>, + ) -> (usize, usize) + { + // MulExpr = MulExpr, "*", UnExpr => ActionFn(23); + assert!(__symbols.len() >= 3); + let __sym2 = __pop_Variant1(__symbols); + let __sym1 = __pop_Variant0(__symbols); + let __sym0 = __pop_Variant1(__symbols); + let __start = __sym0.0.clone(); + let __end = __sym2.2.clone(); + let __nt = super::__action23::<>(input, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant1(__nt), __end)); + (3, 11) + } + fn __reduce36< + 'input, + >( + input: &'input str, + __lookahead_start: Option<&usize>, + __symbols: &mut alloc::vec::Vec<(usize,__Symbol<'input>,usize)>, + _: core::marker::PhantomData<(&'input ())>, + ) -> (usize, usize) + { + // MulExpr = MulExpr, "/", UnExpr => ActionFn(24); + assert!(__symbols.len() >= 3); + let __sym2 = __pop_Variant1(__symbols); + let __sym1 = __pop_Variant0(__symbols); + let __sym0 = __pop_Variant1(__symbols); + let __start = __sym0.0.clone(); + let __end = __sym2.2.clone(); + let __nt = super::__action24::<>(input, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant1(__nt), __end)); + (3, 11) + } + fn __reduce37< + 'input, + >( + input: &'input str, + __lookahead_start: Option<&usize>, + __symbols: &mut alloc::vec::Vec<(usize,__Symbol<'input>,usize)>, + _: core::marker::PhantomData<(&'input ())>, + ) -> (usize, usize) + { + // NUM = r#"[0-9]+(\\.[0-9]+)?"# => ActionFn(40); + let __sym0 = __pop_Variant0(__symbols); + let __start = __sym0.0.clone(); + let __end = __sym0.2.clone(); + let __nt = super::__action40::<>(input, __sym0); + __symbols.push((__start, __Symbol::Variant6(__nt), __end)); + (1, 12) + } + fn __reduce38< + 'input, + >( + input: &'input str, + __lookahead_start: Option<&usize>, + __symbols: &mut alloc::vec::Vec<(usize,__Symbol<'input>,usize)>, + _: core::marker::PhantomData<(&'input ())>, + ) -> (usize, usize) + { + // OrExpr = AndExpr => ActionFn(8); + let __sym0 = __pop_Variant1(__symbols); + let __start = __sym0.0.clone(); + let __end = __sym0.2.clone(); + let __nt = super::__action8::<>(input, __sym0); + __symbols.push((__start, __Symbol::Variant1(__nt), __end)); + (1, 13) + } + fn __reduce39< + 'input, + >( + input: &'input str, + __lookahead_start: Option<&usize>, + __symbols: &mut alloc::vec::Vec<(usize,__Symbol<'input>,usize)>, + _: core::marker::PhantomData<(&'input ())>, + ) -> (usize, usize) + { + // OrExpr = OrExpr, "||", AndExpr => ActionFn(9); + assert!(__symbols.len() >= 3); + let __sym2 = __pop_Variant1(__symbols); + let __sym1 = __pop_Variant0(__symbols); + let __sym0 = __pop_Variant1(__symbols); + let __start = __sym0.0.clone(); + let __end = __sym2.2.clone(); + let __nt = super::__action9::<>(input, __sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant1(__nt), __end)); + (3, 13) + } + fn __reduce40< + 'input, + >( + input: &'input str, + __lookahead_start: Option<&usize>, + __symbols: &mut alloc::vec::Vec<(usize,__Symbol<'input>,usize)>, + _: core::marker::PhantomData<(&'input ())>, + ) -> (usize, usize) + { + // Program = => ActionFn(60); + let __start = __lookahead_start.cloned().or_else(|| __symbols.last().map(|s| s.2)).unwrap_or_default(); + let __end = __start; + let __nt = super::__action60::<>(input, &__start, &__end); + __symbols.push((__start, __Symbol::Variant7(__nt), __end)); + (0, 14) + } + fn __reduce41< + 'input, + >( + input: &'input str, + __lookahead_start: Option<&usize>, + __symbols: &mut alloc::vec::Vec<(usize,__Symbol<'input>,usize)>, + _: core::marker::PhantomData<(&'input ())>, + ) -> (usize, usize) + { + // Program = Stmt+ => ActionFn(61); + let __sym0 = __pop_Variant9(__symbols); + let __start = __sym0.0.clone(); + let __end = __sym0.2.clone(); + let __nt = super::__action61::<>(input, __sym0); + __symbols.push((__start, __Symbol::Variant7(__nt), __end)); + (1, 14) + } + fn __reduce42< + 'input, + >( + input: &'input str, + __lookahead_start: Option<&usize>, + __symbols: &mut alloc::vec::Vec<(usize,__Symbol<'input>,usize)>, + _: core::marker::PhantomData<(&'input ())>, + ) -> (usize, usize) + { + // STRING = r#"\"[^\"]*\""# => ActionFn(39); + let __sym0 = __pop_Variant0(__symbols); + let __start = __sym0.0.clone(); + let __end = __sym0.2.clone(); + let __nt = super::__action39::<>(input, __sym0); + __symbols.push((__start, __Symbol::Variant5(__nt), __end)); + (1, 15) + } + fn __reduce43< + 'input, + >( + input: &'input str, + __lookahead_start: Option<&usize>, + __symbols: &mut alloc::vec::Vec<(usize,__Symbol<'input>,usize)>, + _: core::marker::PhantomData<(&'input ())>, + ) -> (usize, usize) + { + // Stmt = "Var", Ident, "=", Expr => ActionFn(2); + assert!(__symbols.len() >= 4); + let __sym3 = __pop_Variant1(__symbols); + let __sym2 = __pop_Variant0(__symbols); + let __sym1 = __pop_Variant5(__symbols); + let __sym0 = __pop_Variant0(__symbols); + let __start = __sym0.0.clone(); + let __end = __sym3.2.clone(); + let __nt = super::__action2::<>(input, __sym0, __sym1, __sym2, __sym3); + __symbols.push((__start, __Symbol::Variant8(__nt), __end)); + (4, 16) + } + fn __reduce44< + 'input, + >( + input: &'input str, + __lookahead_start: Option<&usize>, + __symbols: &mut alloc::vec::Vec<(usize,__Symbol<'input>,usize)>, + _: core::marker::PhantomData<(&'input ())>, + ) -> (usize, usize) + { + // Stmt = "Var", Ident, "!", "assigned" => ActionFn(3); + assert!(__symbols.len() >= 4); + let __sym3 = __pop_Variant0(__symbols); + let __sym2 = __pop_Variant0(__symbols); + let __sym1 = __pop_Variant5(__symbols); + let __sym0 = __pop_Variant0(__symbols); + let __start = __sym0.0.clone(); + let __end = __sym3.2.clone(); + let __nt = super::__action3::<>(input, __sym0, __sym1, __sym2, __sym3); + __symbols.push((__start, __Symbol::Variant8(__nt), __end)); + (4, 16) + } + fn __reduce45< + 'input, + >( + input: &'input str, + __lookahead_start: Option<&usize>, + __symbols: &mut alloc::vec::Vec<(usize,__Symbol<'input>,usize)>, + _: core::marker::PhantomData<(&'input ())>, + ) -> (usize, usize) + { + // Stmt = "If", Expr, "Then", Stmts, "EndIf" => ActionFn(4); + assert!(__symbols.len() >= 5); + let __sym4 = __pop_Variant0(__symbols); + let __sym3 = __pop_Variant10(__symbols); + let __sym2 = __pop_Variant0(__symbols); + let __sym1 = __pop_Variant1(__symbols); + let __sym0 = __pop_Variant0(__symbols); + let __start = __sym0.0.clone(); + let __end = __sym4.2.clone(); + let __nt = super::__action4::<>(input, __sym0, __sym1, __sym2, __sym3, __sym4); + __symbols.push((__start, __Symbol::Variant8(__nt), __end)); + (5, 16) + } + fn __reduce46< + 'input, + >( + input: &'input str, + __lookahead_start: Option<&usize>, + __symbols: &mut alloc::vec::Vec<(usize,__Symbol<'input>,usize)>, + _: core::marker::PhantomData<(&'input ())>, + ) -> (usize, usize) + { + // Stmt = "If", Expr, "Then", Stmts, "Else", Stmts, "EndIf" => ActionFn(5); + assert!(__symbols.len() >= 7); + let __sym6 = __pop_Variant0(__symbols); + let __sym5 = __pop_Variant10(__symbols); + let __sym4 = __pop_Variant0(__symbols); + let __sym3 = __pop_Variant10(__symbols); + let __sym2 = __pop_Variant0(__symbols); + let __sym1 = __pop_Variant1(__symbols); + let __sym0 = __pop_Variant0(__symbols); + let __start = __sym0.0.clone(); + let __end = __sym6.2.clone(); + let __nt = super::__action5::<>(input, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5, __sym6); + __symbols.push((__start, __Symbol::Variant8(__nt), __end)); + (7, 16) + } + fn __reduce47< + 'input, + >( + input: &'input str, + __lookahead_start: Option<&usize>, + __symbols: &mut alloc::vec::Vec<(usize,__Symbol<'input>,usize)>, + _: core::marker::PhantomData<(&'input ())>, + ) -> (usize, usize) + { + // Stmt = "For", Ident, "In", Expr, Stmts, "EndFor" => ActionFn(6); + assert!(__symbols.len() >= 6); + let __sym5 = __pop_Variant0(__symbols); + let __sym4 = __pop_Variant10(__symbols); + let __sym3 = __pop_Variant1(__symbols); + let __sym2 = __pop_Variant0(__symbols); + let __sym1 = __pop_Variant5(__symbols); + let __sym0 = __pop_Variant0(__symbols); + let __start = __sym0.0.clone(); + let __end = __sym5.2.clone(); + let __nt = super::__action6::<>(input, __sym0, __sym1, __sym2, __sym3, __sym4, __sym5); + __symbols.push((__start, __Symbol::Variant8(__nt), __end)); + (6, 16) + } + fn __reduce48< + 'input, + >( + input: &'input str, + __lookahead_start: Option<&usize>, + __symbols: &mut alloc::vec::Vec<(usize,__Symbol<'input>,usize)>, + _: core::marker::PhantomData<(&'input ())>, + ) -> (usize, usize) + { + // Stmt* = => ActionFn(47); + let __start = __lookahead_start.cloned().or_else(|| __symbols.last().map(|s| s.2)).unwrap_or_default(); + let __end = __start; + let __nt = super::__action47::<>(input, &__start, &__end); + __symbols.push((__start, __Symbol::Variant9(__nt), __end)); + (0, 17) + } + fn __reduce49< + 'input, + >( + input: &'input str, + __lookahead_start: Option<&usize>, + __symbols: &mut alloc::vec::Vec<(usize,__Symbol<'input>,usize)>, + _: core::marker::PhantomData<(&'input ())>, + ) -> (usize, usize) + { + // Stmt* = Stmt+ => ActionFn(48); + let __sym0 = __pop_Variant9(__symbols); + let __start = __sym0.0.clone(); + let __end = __sym0.2.clone(); + let __nt = super::__action48::<>(input, __sym0); + __symbols.push((__start, __Symbol::Variant9(__nt), __end)); + (1, 17) + } + fn __reduce50< + 'input, + >( + input: &'input str, + __lookahead_start: Option<&usize>, + __symbols: &mut alloc::vec::Vec<(usize,__Symbol<'input>,usize)>, + _: core::marker::PhantomData<(&'input ())>, + ) -> (usize, usize) + { + // Stmt+ = Stmt => ActionFn(42); + let __sym0 = __pop_Variant8(__symbols); + let __start = __sym0.0.clone(); + let __end = __sym0.2.clone(); + let __nt = super::__action42::<>(input, __sym0); + __symbols.push((__start, __Symbol::Variant9(__nt), __end)); + (1, 18) + } + fn __reduce51< + 'input, + >( + input: &'input str, + __lookahead_start: Option<&usize>, + __symbols: &mut alloc::vec::Vec<(usize,__Symbol<'input>,usize)>, + _: core::marker::PhantomData<(&'input ())>, + ) -> (usize, usize) + { + // Stmt+ = Stmt+, Stmt => ActionFn(43); + assert!(__symbols.len() >= 2); + let __sym1 = __pop_Variant8(__symbols); + let __sym0 = __pop_Variant9(__symbols); + let __start = __sym0.0.clone(); + let __end = __sym1.2.clone(); + let __nt = super::__action43::<>(input, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant9(__nt), __end)); + (2, 18) + } + fn __reduce52< + 'input, + >( + input: &'input str, + __lookahead_start: Option<&usize>, + __symbols: &mut alloc::vec::Vec<(usize,__Symbol<'input>,usize)>, + _: core::marker::PhantomData<(&'input ())>, + ) -> (usize, usize) + { + // Stmts = Stmt+ => ActionFn(38); + let __sym0 = __pop_Variant9(__symbols); + let __start = __sym0.0.clone(); + let __end = __sym0.2.clone(); + let __nt = super::__action38::<>(input, __sym0); + __symbols.push((__start, __Symbol::Variant10(__nt), __end)); + (1, 19) + } + fn __reduce53< + 'input, + >( + input: &'input str, + __lookahead_start: Option<&usize>, + __symbols: &mut alloc::vec::Vec<(usize,__Symbol<'input>,usize)>, + _: core::marker::PhantomData<(&'input ())>, + ) -> (usize, usize) + { + // UnExpr = AtomExpr => ActionFn(25); + let __sym0 = __pop_Variant1(__symbols); + let __start = __sym0.0.clone(); + let __end = __sym0.2.clone(); + let __nt = super::__action25::<>(input, __sym0); + __symbols.push((__start, __Symbol::Variant1(__nt), __end)); + (1, 20) + } + fn __reduce54< + 'input, + >( + input: &'input str, + __lookahead_start: Option<&usize>, + __symbols: &mut alloc::vec::Vec<(usize,__Symbol<'input>,usize)>, + _: core::marker::PhantomData<(&'input ())>, + ) -> (usize, usize) + { + // UnExpr = "!", UnExpr => ActionFn(26); + assert!(__symbols.len() >= 2); + let __sym1 = __pop_Variant1(__symbols); + let __sym0 = __pop_Variant0(__symbols); + let __start = __sym0.0.clone(); + let __end = __sym1.2.clone(); + let __nt = super::__action26::<>(input, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant1(__nt), __end)); + (2, 20) + } + fn __reduce55< + 'input, + >( + input: &'input str, + __lookahead_start: Option<&usize>, + __symbols: &mut alloc::vec::Vec<(usize,__Symbol<'input>,usize)>, + _: core::marker::PhantomData<(&'input ())>, + ) -> (usize, usize) + { + // UnExpr = "-", UnExpr => ActionFn(27); + assert!(__symbols.len() >= 2); + let __sym1 = __pop_Variant1(__symbols); + let __sym0 = __pop_Variant0(__symbols); + let __start = __sym0.0.clone(); + let __end = __sym1.2.clone(); + let __nt = super::__action27::<>(input, __sym0, __sym1); + __symbols.push((__start, __Symbol::Variant1(__nt), __end)); + (2, 20) } } +#[allow(unused_imports)] pub use self::__parse__Program::ProgramParser; -#[cfg_attr(rustfmt, rustfmt_skip)] +#[rustfmt::skip] mod __intern_token { #![allow(unused_imports)] + use crate::xml::ast::nodes::{AssignmentType, BinaryOpKind, Expression, LiteralValue, Program, Statement, UnaryOpKind}; #[allow(unused_extern_crates)] extern crate lalrpop_util as __lalrpop_util; #[allow(unused_imports)] use self::__lalrpop_util::state_machine as __state_machine; - extern crate core; + #[allow(unused_extern_crates)] extern crate alloc; pub fn new_builder() -> __lalrpop_util::lexer::MatcherBuilder { let __strs: &[(&str, bool)] = &[ - ("^((?:hello))", false), - (r"^(\s*)", true), + ("(?:\"[\0-!\\#-\u{10ffff}]*\")", false), + ("(?:[0-9]+((?:\\.[0-9]+))?)", false), + ("(?:[A-Z_a-z][0-9A-Z_a-z]*)", false), + ("[\t-\r \u{85}\u{a0}\u{1680}\u{2000}-\u{200a}\u{2028}\u{2029}\u{202f}\u{205f}\u{3000}]+", true), + ("!", false), + ("(?:!=)", false), + ("\\$", false), + ("(?:\\&\\&)", false), + ("\\(", false), + ("\\)", false), + ("\\*", false), + ("\\+", false), + (",", false), + ("\\-", false), + ("/", false), + ("<", false), + ("(?:<=)", false), + ("=", false), + ("(?:==)", false), + (">", false), + ("(?:>=)", false), + ("@", false), + ("(?:Else)", false), + ("(?:EndFor)", false), + ("(?:EndIf)", false), + ("(?:False)", false), + ("(?:For)", false), + ("(?:If)", false), + ("(?:In)", false), + ("(?:Then)", false), + ("(?:True)", false), + ("(?:Var)", false), + ("(?:assigned)", false), + ("(?:\\|\\|)", false), ]; __lalrpop_util::lexer::MatcherBuilder::new(__strs.iter().copied()).unwrap() } @@ -571,101 +2517,922 @@ mod __intern_token { pub(crate) use self::__lalrpop_util::lexer::Token; #[allow(unused_variables)] -#[allow(clippy::too_many_arguments)] +#[allow(clippy::too_many_arguments, clippy::needless_lifetimes, clippy::just_underscores_and_digits)] fn __action0< 'input, >( input: &'input str, - (_, __0, _): (usize, (), usize), -) + (_, __0, _): (usize, Program, usize), +) -> Program { + __0 } #[allow(unused_variables)] -#[allow(clippy::too_many_arguments)] +#[allow(clippy::too_many_arguments, clippy::needless_lifetimes, clippy::just_underscores_and_digits)] fn __action1< 'input, >( input: &'input str, - (_, __0, _): (usize, alloc::vec::Vec<()>, usize), -) + (_, stmts, _): (usize, alloc::vec::Vec, usize), +) -> Program { + Program { statements: stmts } } #[allow(unused_variables)] -#[allow(clippy::too_many_arguments)] +#[allow(clippy::too_many_arguments, clippy::needless_lifetimes, clippy::just_underscores_and_digits)] fn __action2< 'input, >( input: &'input str, - (_, __0, _): (usize, &'input str, usize), -) + (_, _, _): (usize, &'input str, usize), + (_, name, _): (usize, String, usize), + (_, _, _): (usize, &'input str, usize), + (_, v, _): (usize, Expression, usize), +) -> Statement { + Statement::VarDecl { + name, + value: Some(v), + assignment_type: AssignmentType::Equals, + } } #[allow(unused_variables)] -#[allow(clippy::too_many_arguments)] +#[allow(clippy::too_many_arguments, clippy::needless_lifetimes, clippy::just_underscores_and_digits)] fn __action3< 'input, >( input: &'input str, - __lookbehind: &usize, - __lookahead: &usize, -) -> alloc::vec::Vec<()> + (_, _, _): (usize, &'input str, usize), + (_, name, _): (usize, String, usize), + (_, _, _): (usize, &'input str, usize), + (_, _, _): (usize, &'input str, usize), +) -> Statement { - alloc::vec![] + Statement::VarDecl { + name, + value: None, + assignment_type: AssignmentType::NotAssigned, + } } #[allow(unused_variables)] -#[allow(clippy::too_many_arguments)] +#[allow(clippy::too_many_arguments, clippy::needless_lifetimes, clippy::just_underscores_and_digits)] fn __action4< 'input, >( input: &'input str, - (_, v, _): (usize, alloc::vec::Vec<()>, usize), -) -> alloc::vec::Vec<()> + (_, _, _): (usize, &'input str, usize), + (_, cond, _): (usize, Expression, usize), + (_, _, _): (usize, &'input str, usize), + (_, then_body, _): (usize, Vec, usize), + (_, _, _): (usize, &'input str, usize), +) -> Statement { - v + Statement::IfStmt { + condition: cond, + then_branch: then_body, + else_branch: vec![], + } } #[allow(unused_variables)] -#[allow(clippy::too_many_arguments)] +#[allow(clippy::too_many_arguments, clippy::needless_lifetimes, clippy::just_underscores_and_digits)] fn __action5< 'input, >( input: &'input str, - (_, __0, _): (usize, (), usize), -) -> alloc::vec::Vec<()> + (_, _, _): (usize, &'input str, usize), + (_, cond, _): (usize, Expression, usize), + (_, _, _): (usize, &'input str, usize), + (_, then_body, _): (usize, Vec, usize), + (_, _, _): (usize, &'input str, usize), + (_, else_body, _): (usize, Vec, usize), + (_, _, _): (usize, &'input str, usize), +) -> Statement +{ + Statement::IfStmt { + condition: cond, + then_branch: then_body, + else_branch: else_body, + } +} + +#[allow(unused_variables)] +#[allow(clippy::too_many_arguments, clippy::needless_lifetimes, clippy::just_underscores_and_digits)] +fn __action6< + 'input, +>( + input: &'input str, + (_, _, _): (usize, &'input str, usize), + (_, var, _): (usize, String, usize), + (_, _, _): (usize, &'input str, usize), + (_, iter, _): (usize, Expression, usize), + (_, body, _): (usize, Vec, usize), + (_, _, _): (usize, &'input str, usize), +) -> Statement +{ + Statement::ForStmt { + variable: var, + iterable: iter, + body, + } +} + +#[allow(unused_variables)] +#[allow(clippy::too_many_arguments, clippy::needless_lifetimes, clippy::just_underscores_and_digits)] +fn __action7< + 'input, +>( + input: &'input str, + (_, __0, _): (usize, Expression, usize), +) -> Expression +{ + __0 +} + +#[allow(unused_variables)] +#[allow(clippy::too_many_arguments, clippy::needless_lifetimes, clippy::just_underscores_and_digits)] +fn __action8< + 'input, +>( + input: &'input str, + (_, __0, _): (usize, Expression, usize), +) -> Expression +{ + __0 +} + +#[allow(unused_variables)] +#[allow(clippy::too_many_arguments, clippy::needless_lifetimes, clippy::just_underscores_and_digits)] +fn __action9< + 'input, +>( + input: &'input str, + (_, left, _): (usize, Expression, usize), + (_, _, _): (usize, &'input str, usize), + (_, right, _): (usize, Expression, usize), +) -> Expression +{ + Expression::BinaryOp { + left: Box::new(left), + op: BinaryOpKind::Add, + right: Box::new(right), + } +} + +#[allow(unused_variables)] +#[allow(clippy::too_many_arguments, clippy::needless_lifetimes, clippy::just_underscores_and_digits)] +fn __action10< + 'input, +>( + input: &'input str, + (_, __0, _): (usize, Expression, usize), +) -> Expression +{ + __0 +} + +#[allow(unused_variables)] +#[allow(clippy::too_many_arguments, clippy::needless_lifetimes, clippy::just_underscores_and_digits)] +fn __action11< + 'input, +>( + input: &'input str, + (_, left, _): (usize, Expression, usize), + (_, _, _): (usize, &'input str, usize), + (_, right, _): (usize, Expression, usize), +) -> Expression +{ + Expression::BinaryOp { + left: Box::new(left), + op: BinaryOpKind::Add, + right: Box::new(right), + } +} + +#[allow(unused_variables)] +#[allow(clippy::too_many_arguments, clippy::needless_lifetimes, clippy::just_underscores_and_digits)] +fn __action12< + 'input, +>( + input: &'input str, + (_, __0, _): (usize, Expression, usize), +) -> Expression +{ + __0 +} + +#[allow(unused_variables)] +#[allow(clippy::too_many_arguments, clippy::needless_lifetimes, clippy::just_underscores_and_digits)] +fn __action13< + 'input, +>( + input: &'input str, + (_, left, _): (usize, Expression, usize), + (_, _, _): (usize, &'input str, usize), + (_, right, _): (usize, Expression, usize), +) -> Expression +{ + Expression::BinaryOp { left: Box::new(left), op: BinaryOpKind::Eq, right: Box::new(right) } +} + +#[allow(unused_variables)] +#[allow(clippy::too_many_arguments, clippy::needless_lifetimes, clippy::just_underscores_and_digits)] +fn __action14< + 'input, +>( + input: &'input str, + (_, left, _): (usize, Expression, usize), + (_, _, _): (usize, &'input str, usize), + (_, right, _): (usize, Expression, usize), +) -> Expression +{ + Expression::BinaryOp { left: Box::new(left), op: BinaryOpKind::Neq, right: Box::new(right) } +} + +#[allow(unused_variables)] +#[allow(clippy::too_many_arguments, clippy::needless_lifetimes, clippy::just_underscores_and_digits)] +fn __action15< + 'input, +>( + input: &'input str, + (_, left, _): (usize, Expression, usize), + (_, _, _): (usize, &'input str, usize), + (_, right, _): (usize, Expression, usize), +) -> Expression +{ + Expression::BinaryOp { left: Box::new(left), op: BinaryOpKind::Lte, right: Box::new(right) } +} + +#[allow(unused_variables)] +#[allow(clippy::too_many_arguments, clippy::needless_lifetimes, clippy::just_underscores_and_digits)] +fn __action16< + 'input, +>( + input: &'input str, + (_, left, _): (usize, Expression, usize), + (_, _, _): (usize, &'input str, usize), + (_, right, _): (usize, Expression, usize), +) -> Expression +{ + Expression::BinaryOp { left: Box::new(left), op: BinaryOpKind::Gte, right: Box::new(right) } +} + +#[allow(unused_variables)] +#[allow(clippy::too_many_arguments, clippy::needless_lifetimes, clippy::just_underscores_and_digits)] +fn __action17< + 'input, +>( + input: &'input str, + (_, left, _): (usize, Expression, usize), + (_, _, _): (usize, &'input str, usize), + (_, right, _): (usize, Expression, usize), +) -> Expression +{ + Expression::BinaryOp { left: Box::new(left), op: BinaryOpKind::Lt, right: Box::new(right) } +} + +#[allow(unused_variables)] +#[allow(clippy::too_many_arguments, clippy::needless_lifetimes, clippy::just_underscores_and_digits)] +fn __action18< + 'input, +>( + input: &'input str, + (_, left, _): (usize, Expression, usize), + (_, _, _): (usize, &'input str, usize), + (_, right, _): (usize, Expression, usize), +) -> Expression +{ + Expression::BinaryOp { left: Box::new(left), op: BinaryOpKind::Gt, right: Box::new(right) } +} + +#[allow(unused_variables)] +#[allow(clippy::too_many_arguments, clippy::needless_lifetimes, clippy::just_underscores_and_digits)] +fn __action19< + 'input, +>( + input: &'input str, + (_, __0, _): (usize, Expression, usize), +) -> Expression +{ + __0 +} + +#[allow(unused_variables)] +#[allow(clippy::too_many_arguments, clippy::needless_lifetimes, clippy::just_underscores_and_digits)] +fn __action20< + 'input, +>( + input: &'input str, + (_, left, _): (usize, Expression, usize), + (_, _, _): (usize, &'input str, usize), + (_, right, _): (usize, Expression, usize), +) -> Expression +{ + Expression::BinaryOp { left: Box::new(left), op: BinaryOpKind::Add, right: Box::new(right) } +} + +#[allow(unused_variables)] +#[allow(clippy::too_many_arguments, clippy::needless_lifetimes, clippy::just_underscores_and_digits)] +fn __action21< + 'input, +>( + input: &'input str, + (_, left, _): (usize, Expression, usize), + (_, _, _): (usize, &'input str, usize), + (_, right, _): (usize, Expression, usize), +) -> Expression +{ + Expression::BinaryOp { left: Box::new(left), op: BinaryOpKind::Sub, right: Box::new(right) } +} + +#[allow(unused_variables)] +#[allow(clippy::too_many_arguments, clippy::needless_lifetimes, clippy::just_underscores_and_digits)] +fn __action22< + 'input, +>( + input: &'input str, + (_, __0, _): (usize, Expression, usize), +) -> Expression +{ + __0 +} + +#[allow(unused_variables)] +#[allow(clippy::too_many_arguments, clippy::needless_lifetimes, clippy::just_underscores_and_digits)] +fn __action23< + 'input, +>( + input: &'input str, + (_, left, _): (usize, Expression, usize), + (_, _, _): (usize, &'input str, usize), + (_, right, _): (usize, Expression, usize), +) -> Expression +{ + Expression::BinaryOp { left: Box::new(left), op: BinaryOpKind::Mul, right: Box::new(right) } +} + +#[allow(unused_variables)] +#[allow(clippy::too_many_arguments, clippy::needless_lifetimes, clippy::just_underscores_and_digits)] +fn __action24< + 'input, +>( + input: &'input str, + (_, left, _): (usize, Expression, usize), + (_, _, _): (usize, &'input str, usize), + (_, right, _): (usize, Expression, usize), +) -> Expression +{ + Expression::BinaryOp { left: Box::new(left), op: BinaryOpKind::Div, right: Box::new(right) } +} + +#[allow(unused_variables)] +#[allow(clippy::too_many_arguments, clippy::needless_lifetimes, clippy::just_underscores_and_digits)] +fn __action25< + 'input, +>( + input: &'input str, + (_, __0, _): (usize, Expression, usize), +) -> Expression +{ + __0 +} + +#[allow(unused_variables)] +#[allow(clippy::too_many_arguments, clippy::needless_lifetimes, clippy::just_underscores_and_digits)] +fn __action26< + 'input, +>( + input: &'input str, + (_, _, _): (usize, &'input str, usize), + (_, e, _): (usize, Expression, usize), +) -> Expression +{ + Expression::UnaryOp { op: UnaryOpKind::Not, operand: Box::new(e) } +} + +#[allow(unused_variables)] +#[allow(clippy::too_many_arguments, clippy::needless_lifetimes, clippy::just_underscores_and_digits)] +fn __action27< + 'input, +>( + input: &'input str, + (_, _, _): (usize, &'input str, usize), + (_, e, _): (usize, Expression, usize), +) -> Expression +{ + Expression::UnaryOp { op: UnaryOpKind::Neg, operand: Box::new(e) } +} + +#[allow(unused_variables)] +#[allow(clippy::too_many_arguments, clippy::needless_lifetimes, clippy::just_underscores_and_digits)] +fn __action28< + 'input, +>( + input: &'input str, + (_, s, _): (usize, String, usize), +) -> Expression +{ + Expression::Literal(LiteralValue::String(s)) +} + +#[allow(unused_variables)] +#[allow(clippy::too_many_arguments, clippy::needless_lifetimes, clippy::just_underscores_and_digits)] +fn __action29< + 'input, +>( + input: &'input str, + (_, n, _): (usize, f64, usize), +) -> Expression +{ + Expression::Literal(LiteralValue::Number(n)) +} + +#[allow(unused_variables)] +#[allow(clippy::too_many_arguments, clippy::needless_lifetimes, clippy::just_underscores_and_digits)] +fn __action30< + 'input, +>( + input: &'input str, + (_, __0, _): (usize, &'input str, usize), +) -> Expression +{ + Expression::Literal(LiteralValue::Bool(true)) +} + +#[allow(unused_variables)] +#[allow(clippy::too_many_arguments, clippy::needless_lifetimes, clippy::just_underscores_and_digits)] +fn __action31< + 'input, +>( + input: &'input str, + (_, __0, _): (usize, &'input str, usize), +) -> Expression +{ + Expression::Literal(LiteralValue::Bool(false)) +} + +#[allow(unused_variables)] +#[allow(clippy::too_many_arguments, clippy::needless_lifetimes, clippy::just_underscores_and_digits)] +fn __action32< + 'input, +>( + input: &'input str, + (_, name, _): (usize, String, usize), + (_, _, _): (usize, &'input str, usize), + (_, args, _): (usize, Option>, usize), + (_, _, _): (usize, &'input str, usize), +) -> Expression +{ + Expression::FunctionCall { name, args: args.unwrap_or_default() } +} + +#[allow(unused_variables)] +#[allow(clippy::too_many_arguments, clippy::needless_lifetimes, clippy::just_underscores_and_digits)] +fn __action33< + 'input, +>( + input: &'input str, + (_, _, _): (usize, &'input str, usize), + (_, name, _): (usize, String, usize), +) -> Expression +{ + Expression::SpecialVar { name, is_negative: false } +} + +#[allow(unused_variables)] +#[allow(clippy::too_many_arguments, clippy::needless_lifetimes, clippy::just_underscores_and_digits)] +fn __action34< + 'input, +>( + input: &'input str, + (_, _, _): (usize, &'input str, usize), + (_, _, _): (usize, &'input str, usize), + (_, name, _): (usize, String, usize), +) -> Expression +{ + Expression::SpecialVar { name, is_negative: true } +} + +#[allow(unused_variables)] +#[allow(clippy::too_many_arguments, clippy::needless_lifetimes, clippy::just_underscores_and_digits)] +fn __action35< + 'input, +>( + input: &'input str, + (_, _, _): (usize, &'input str, usize), + (_, name, _): (usize, String, usize), +) -> Expression +{ + Expression::AutoVarExpr { variable: Box::new(Expression::SpecialVar { name, is_negative: false }) } +} + +#[allow(unused_variables)] +#[allow(clippy::too_many_arguments, clippy::needless_lifetimes, clippy::just_underscores_and_digits)] +fn __action36< + 'input, +>( + input: &'input str, + (_, name, _): (usize, String, usize), +) -> Expression +{ + Expression::Identifier(name) +} + +#[allow(unused_variables)] +#[allow(clippy::too_many_arguments, clippy::needless_lifetimes, clippy::just_underscores_and_digits)] +fn __action37< + 'input, +>( + input: &'input str, + (_, _, _): (usize, &'input str, usize), + (_, e, _): (usize, Expression, usize), + (_, _, _): (usize, &'input str, usize), +) -> Expression +{ + e +} + +#[allow(unused_variables)] +#[allow(clippy::too_many_arguments, clippy::needless_lifetimes, clippy::just_underscores_and_digits)] +fn __action38< + 'input, +>( + input: &'input str, + (_, stmts, _): (usize, alloc::vec::Vec, usize), +) -> Vec +{ + stmts +} + +#[allow(unused_variables)] +#[allow(clippy::too_many_arguments, clippy::needless_lifetimes, clippy::just_underscores_and_digits)] +fn __action39< + 'input, +>( + input: &'input str, + (_, s, _): (usize, &'input str, usize), +) -> String +{ + s[1..s.len()-1].to_string() +} + +#[allow(unused_variables)] +#[allow(clippy::too_many_arguments, clippy::needless_lifetimes, clippy::just_underscores_and_digits)] +fn __action40< + 'input, +>( + input: &'input str, + (_, s, _): (usize, &'input str, usize), +) -> f64 +{ + s.parse::().unwrap() +} + +#[allow(unused_variables)] +#[allow(clippy::too_many_arguments, clippy::needless_lifetimes, clippy::just_underscores_and_digits)] +fn __action41< + 'input, +>( + input: &'input str, + (_, s, _): (usize, &'input str, usize), +) -> String +{ + s.to_string() +} + +#[allow(unused_variables)] +#[allow(clippy::too_many_arguments, clippy::needless_lifetimes, clippy::just_underscores_and_digits)] +fn __action42< + 'input, +>( + input: &'input str, + (_, __0, _): (usize, Statement, usize), +) -> alloc::vec::Vec { alloc::vec![__0] } #[allow(unused_variables)] -#[allow(clippy::too_many_arguments)] -fn __action6< +#[allow(clippy::too_many_arguments, clippy::needless_lifetimes, clippy::just_underscores_and_digits)] +fn __action43< 'input, >( input: &'input str, - (_, v, _): (usize, alloc::vec::Vec<()>, usize), - (_, e, _): (usize, (), usize), -) -> alloc::vec::Vec<()> + (_, v, _): (usize, alloc::vec::Vec, usize), + (_, e, _): (usize, Statement, usize), +) -> alloc::vec::Vec { { let mut v = v; v.push(e); v } } #[allow(unused_variables)] -#[allow(clippy::too_many_arguments)] -fn __action7< +#[allow(clippy::too_many_arguments, clippy::needless_lifetimes, clippy::just_underscores_and_digits)] +fn __action44< + 'input, +>( + input: &'input str, + (_, __0, _): (usize, Vec, usize), +) -> Option> +{ + Some(__0) +} + +#[allow(unused_variables)] +#[allow(clippy::too_many_arguments, clippy::needless_lifetimes, clippy::just_underscores_and_digits)] +fn __action45< 'input, >( input: &'input str, __lookbehind: &usize, __lookahead: &usize, -) +) -> Option> +{ + None +} + +#[allow(unused_variables)] +#[allow(clippy::too_many_arguments, clippy::needless_lifetimes, clippy::just_underscores_and_digits)] +fn __action46< + 'input, +>( + input: &'input str, + (_, v, _): (usize, alloc::vec::Vec, usize), + (_, e, _): (usize, Expression, usize), +) -> Vec +{ + { + let mut v = v; + v.push(e); + v + } +} + +#[allow(unused_variables)] +#[allow(clippy::too_many_arguments, clippy::needless_lifetimes, clippy::just_underscores_and_digits)] +fn __action47< + 'input, +>( + input: &'input str, + __lookbehind: &usize, + __lookahead: &usize, +) -> alloc::vec::Vec +{ + alloc::vec![] +} + +#[allow(unused_variables)] +#[allow(clippy::too_many_arguments, clippy::needless_lifetimes, clippy::just_underscores_and_digits)] +fn __action48< + 'input, +>( + input: &'input str, + (_, v, _): (usize, alloc::vec::Vec, usize), +) -> alloc::vec::Vec +{ + v +} + +#[allow(unused_variables)] +#[allow(clippy::too_many_arguments, clippy::needless_lifetimes, clippy::just_underscores_and_digits)] +fn __action49< + 'input, +>( + input: &'input str, + __lookbehind: &usize, + __lookahead: &usize, +) -> alloc::vec::Vec +{ + alloc::vec![] +} + +#[allow(unused_variables)] +#[allow(clippy::too_many_arguments, clippy::needless_lifetimes, clippy::just_underscores_and_digits)] +fn __action50< + 'input, +>( + input: &'input str, + (_, v, _): (usize, alloc::vec::Vec, usize), +) -> alloc::vec::Vec +{ + v +} + +#[allow(unused_variables)] +#[allow(clippy::too_many_arguments, clippy::needless_lifetimes, clippy::just_underscores_and_digits)] +fn __action51< + 'input, +>( + input: &'input str, + (_, __0, _): (usize, Expression, usize), + (_, _, _): (usize, &'input str, usize), +) -> Expression +{ + __0 +} + +#[allow(unused_variables)] +#[allow(clippy::too_many_arguments, clippy::needless_lifetimes, clippy::just_underscores_and_digits)] +fn __action52< + 'input, +>( + input: &'input str, + (_, __0, _): (usize, Expression, usize), +) -> alloc::vec::Vec +{ + alloc::vec![__0] +} + +#[allow(unused_variables)] +#[allow(clippy::too_many_arguments, clippy::needless_lifetimes, clippy::just_underscores_and_digits)] +fn __action53< + 'input, +>( + input: &'input str, + (_, v, _): (usize, alloc::vec::Vec, usize), + (_, e, _): (usize, Expression, usize), +) -> alloc::vec::Vec +{ + { let mut v = v; v.push(e); v } +} + +#[allow(unused_variables)] +#[allow(clippy::too_many_arguments, clippy::needless_lifetimes, + clippy::just_underscores_and_digits)] +fn __action54< + 'input, +>( + input: &'input str, + __0: (usize, Expression, usize), + __1: (usize, &'input str, usize), +) -> alloc::vec::Vec +{ + let __start0 = __0.0; + let __end0 = __1.2; + let __temp0 = __action51( + input, + __0, + __1, + ); + let __temp0 = (__start0, __temp0, __end0); + __action52( + input, + __temp0, + ) +} + +#[allow(unused_variables)] +#[allow(clippy::too_many_arguments, clippy::needless_lifetimes, + clippy::just_underscores_and_digits)] +fn __action55< + 'input, +>( + input: &'input str, + __0: (usize, alloc::vec::Vec, usize), + __1: (usize, Expression, usize), + __2: (usize, &'input str, usize), +) -> alloc::vec::Vec +{ + let __start0 = __1.0; + let __end0 = __2.2; + let __temp0 = __action51( + input, + __1, + __2, + ); + let __temp0 = (__start0, __temp0, __end0); + __action53( + input, + __0, + __temp0, + ) +} + +#[allow(unused_variables)] +#[allow(clippy::too_many_arguments, clippy::needless_lifetimes, + clippy::just_underscores_and_digits)] +fn __action56< + 'input, +>( + input: &'input str, + __0: (usize, Expression, usize), +) -> Vec +{ + let __start0 = __0.0; + let __end0 = __0.0; + let __temp0 = __action49( + input, + &__start0, + &__end0, + ); + let __temp0 = (__start0, __temp0, __end0); + __action46( + input, + __temp0, + __0, + ) +} + +#[allow(unused_variables)] +#[allow(clippy::too_many_arguments, clippy::needless_lifetimes, + clippy::just_underscores_and_digits)] +fn __action57< + 'input, +>( + input: &'input str, + __0: (usize, alloc::vec::Vec, usize), + __1: (usize, Expression, usize), +) -> Vec +{ + let __start0 = __0.0; + let __end0 = __0.2; + let __temp0 = __action50( + input, + __0, + ); + let __temp0 = (__start0, __temp0, __end0); + __action46( + input, + __temp0, + __1, + ) +} + +#[allow(unused_variables)] +#[allow(clippy::too_many_arguments, clippy::needless_lifetimes, + clippy::just_underscores_and_digits)] +fn __action58< + 'input, +>( + input: &'input str, + __0: (usize, String, usize), + __1: (usize, &'input str, usize), + __2: (usize, Vec, usize), + __3: (usize, &'input str, usize), +) -> Expression +{ + let __start0 = __2.0; + let __end0 = __2.2; + let __temp0 = __action44( + input, + __2, + ); + let __temp0 = (__start0, __temp0, __end0); + __action32( + input, + __0, + __1, + __temp0, + __3, + ) +} + +#[allow(unused_variables)] +#[allow(clippy::too_many_arguments, clippy::needless_lifetimes, + clippy::just_underscores_and_digits)] +fn __action59< + 'input, +>( + input: &'input str, + __0: (usize, String, usize), + __1: (usize, &'input str, usize), + __2: (usize, &'input str, usize), +) -> Expression +{ + let __start0 = __1.2; + let __end0 = __2.0; + let __temp0 = __action45( + input, + &__start0, + &__end0, + ); + let __temp0 = (__start0, __temp0, __end0); + __action32( + input, + __0, + __1, + __temp0, + __2, + ) +} + +#[allow(unused_variables)] +#[allow(clippy::too_many_arguments, clippy::needless_lifetimes, + clippy::just_underscores_and_digits)] +fn __action60< + 'input, +>( + input: &'input str, + __lookbehind: &usize, + __lookahead: &usize, +) -> Program { let __start0 = *__lookbehind; let __end0 = *__lookahead; - let __temp0 = __action3( + let __temp0 = __action47( input, &__start0, &__end0, @@ -678,17 +3445,18 @@ fn __action7< } #[allow(unused_variables)] -#[allow(clippy::too_many_arguments)] -fn __action8< +#[allow(clippy::too_many_arguments, clippy::needless_lifetimes, + clippy::just_underscores_and_digits)] +fn __action61< 'input, >( input: &'input str, - __0: (usize, alloc::vec::Vec<()>, usize), -) + __0: (usize, alloc::vec::Vec, usize), +) -> Program { let __start0 = __0.0; let __end0 = __0.2; - let __temp0 = __action4( + let __temp0 = __action48( input, __0, ); @@ -698,25 +3466,22 @@ fn __action8< __temp0, ) } -#[allow(clippy::type_complexity)] +#[allow(clippy::type_complexity, dead_code)] pub trait __ToTriple<'input, > { - fn to_triple(value: Self) -> Result<(usize,Token<'input>,usize), __lalrpop_util::ParseError, &'static str>>; + fn to_triple(self) -> Result<(usize,Token<'input>,usize), __lalrpop_util::ParseError, &'static str>>; } impl<'input, > __ToTriple<'input, > for (usize, Token<'input>, usize) { - fn to_triple(value: Self) -> Result<(usize,Token<'input>,usize), __lalrpop_util::ParseError, &'static str>> { - Ok(value) + fn to_triple(self) -> Result<(usize,Token<'input>,usize), __lalrpop_util::ParseError, &'static str>> { + Ok(self) } } impl<'input, > __ToTriple<'input, > for Result<(usize, Token<'input>, usize), &'static str> { - fn to_triple(value: Self) -> Result<(usize,Token<'input>,usize), __lalrpop_util::ParseError, &'static str>> { - match value { - Ok(v) => Ok(v), - Err(error) => Err(__lalrpop_util::ParseError::User { error }), - } + fn to_triple(self) -> Result<(usize,Token<'input>,usize), __lalrpop_util::ParseError, &'static str>> { + self.map_err(|error| __lalrpop_util::ParseError::User { error }) } } diff --git a/src/xml/parser/mod.rs b/src/xml/parser/mod.rs index 17c855f..64f4127 100644 --- a/src/xml/parser/mod.rs +++ b/src/xml/parser/mod.rs @@ -1,24 +1,21 @@ -use crate::xml::ast::nodes::{AssignmentType, BinaryOpKind, Expression, LiteralValue, Program, Statement, UnaryOpKind}; -use crate::xml::error::{ParseError, ParserResult}; +use crate::xml::ast::nodes::{ + AssignmentType, BinaryOpKind, Expression, LiteralValue, Program, Statement, UnaryOpKind, +}; +use crate::xml::error::ParserResult; -// The LALRPOP-generated parser will be in this module +#[allow(clippy::all)] pub mod grammar; -pub use grammar::ProgramParser; +use grammar::ProgramParser; -// Wrapper around the LALRPOP parser to provide a cleaner interface pub struct ScriptParser; impl ScriptParser { - /// Parse a script string into an AST pub fn parse(source: &str) -> ParserResult { - let parser = grammar::ProgramParser::new(); + let parser = ProgramParser::new(); match parser.parse(source) { - Ok(_) => { - // For now, just return an empty program since our grammar returns unit - Ok(Program { statements: vec![] }) - }, - Err(e) => Err(ParseError::from_lalrpop_error(source, e)), + Ok(program) => Ok(program), + Err(e) => Err(crate::xml::error::ParseError::from_lalrpop_error(source, e)), } } } @@ -26,7 +23,7 @@ impl ScriptParser { #[cfg(test)] mod tests { use super::*; - + #[test] fn test_empty() { let result = ScriptParser::parse(""); @@ -34,4 +31,148 @@ mod tests { let program = result.unwrap(); assert_eq!(program.statements.len(), 0); } -} + + #[test] + fn test_whitespace() { + let result = ScriptParser::parse(" \n\n \t "); + assert!(result.is_ok()); + let program = result.unwrap(); + assert_eq!(program.statements.len(), 0); + } + + #[test] + fn test_var_decl_number() { + let result = ScriptParser::parse("Var x = 5"); + assert!(result.is_ok(), "parse failed: {:?}", result.err()); + let program = result.unwrap(); + assert_eq!(program.statements.len(), 1); + if let Statement::VarDecl { name, value, assignment_type } = &program.statements[0] { + assert_eq!(name, "x"); + assert_eq!(*assignment_type, AssignmentType::Equals); + if let Some(Expression::Literal(LiteralValue::Number(n))) = value { + assert_eq!(*n, 5.0); + } else { + panic!("Expected number literal"); + } + } else { + panic!("Expected VarDecl"); + } + } + + #[test] + fn test_var_decl_string() { + let result = ScriptParser::parse(r#"Var x = "hello""#); + assert!(result.is_ok(), "parse failed: {:?}", result.err()); + let program = result.unwrap(); + if let Statement::VarDecl { name, value, .. } = &program.statements[0] { + assert_eq!(name, "x"); + if let Some(Expression::Literal(LiteralValue::String(s))) = value { + assert_eq!(s, "hello"); + } else { + panic!("Expected string literal"); + } + } + } + + #[test] + fn test_var_decl_not_assigned() { + let result = ScriptParser::parse("Var x !assigned"); + assert!(result.is_ok(), "parse failed: {:?}", result.err()); + let program = result.unwrap(); + if let Statement::VarDecl { name, value, assignment_type } = &program.statements[0] { + assert_eq!(name, "x"); + assert!(value.is_none()); + assert_eq!(*assignment_type, AssignmentType::NotAssigned); + } + } + + #[test] + fn test_if_stmt_simple() { + let result = ScriptParser::parse("If x == 5 Then Var y = 10 EndIf"); + assert!(result.is_ok(), "parse failed: {:?}", result.err()); + } + + #[test] + fn test_if_with_else() { + let result = ScriptParser::parse("If x == 5 Then Var y = 10 Else Var y = 20 EndIf"); + assert!(result.is_ok(), "parse failed: {:?}", result.err()); + let program = result.unwrap(); + if let Statement::IfStmt { else_branch, .. } = &program.statements[0] { + assert!(!else_branch.is_empty()); + } + } + + #[test] + fn test_special_var() { + let result = ScriptParser::parse("Var x = $myVar"); + assert!(result.is_ok(), "parse failed: {:?}", result.err()); + let program = result.unwrap(); + if let Statement::VarDecl { value, .. } = &program.statements[0] { + if let Some(Expression::SpecialVar { name, is_negative }) = value { + assert_eq!(name, "myVar"); + assert!(!is_negative); + } else { + panic!("Expected SpecialVar"); + } + } + } + + #[test] + fn test_special_var_negative() { + let result = ScriptParser::parse("Var x = $-myVar"); + assert!(result.is_ok(), "parse failed: {:?}", result.err()); + let program = result.unwrap(); + if let Statement::VarDecl { value, .. } = &program.statements[0] { + if let Some(Expression::SpecialVar { name, is_negative }) = value { + assert_eq!(name, "myVar"); + assert!(is_negative); + } else { + panic!("Expected SpecialVar"); + } + } + } + + #[test] + fn test_auto_var() { + let result = ScriptParser::parse("Var x = @myVar"); + assert!(result.is_ok(), "parse failed: {:?}", result.err()); + } + + #[test] + fn test_function_call() { + let result = ScriptParser::parse("Var x = myFunc(1, 2)"); + assert!(result.is_ok(), "parse failed: {:?}", result.err()); + } + + #[test] + fn test_arithmetic() { + let result = ScriptParser::parse("Var x = 1 + 2 * 3"); + assert!(result.is_ok(), "parse failed: {:?}", result.err()); + } + + #[test] + fn test_comparison() { + let result = ScriptParser::parse("If x != 5 Then Var y = 10 EndIf"); + assert!(result.is_ok(), "parse failed: {:?}", result.err()); + } + + #[test] + fn test_for_loop() { + let result = ScriptParser::parse("For i In items Var x = i EndFor"); + assert!(result.is_ok(), "parse failed: {:?}", result.err()); + } + + #[test] + fn test_boolean_literals() { + let result = ScriptParser::parse("Var x = True"); + assert!(result.is_ok(), "parse failed: {:?}", result.err()); + let result2 = ScriptParser::parse("Var x = False"); + assert!(result2.is_ok(), "parse failed: {:?}", result2.err()); + } + + #[test] + fn test_parenthesized_expression() { + let result = ScriptParser::parse("Var x = (1 + 2) * 3"); + assert!(result.is_ok(), "parse failed: {:?}", result.err()); + } +} \ No newline at end of file diff --git a/src/xml/parser/mod.rs.bak b/src/xml/parser/mod.rs.bak deleted file mode 100644 index ed8404f..0000000 --- a/src/xml/parser/mod.rs.bak +++ /dev/null @@ -1,59 +0,0 @@ -use crate::xml::ast::nodes::{AssignmentType, BinaryOpKind, Expression, LiteralValue, Program, Statement, UnaryOpKind}; -use crate::xml::error::{ParseError, ParserResult}; - -// The LALRPOP-generated parser will be in this module -mod grammar; - -pub use grammar::ProgramParser; - -// Wrapper around the LALRPOP parser to provide a cleaner interface -pub struct ScriptParser; - -impl ScriptParser { - /// Parse a script string into an AST - pub fn parse(source: &str) -> ParserResult { - let parser = grammar::ProgramParser::new(); - match parser.parse(source) { - Ok(program) => Ok(program), - Err(e) => Err(ParseError::from_lalrpop_error(source, e)), - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_empty() { - let result = ScriptParser::parse(""); - assert!(result.is_ok()); - let program = result.unwrap(); - assert_eq!(program.statements.len(), 0); - } - - #[test] - fn test_simple_var_decl() { - let result = ScriptParser::parse("Var x = 5"); - assert!(result.is_ok()); - let program = result.unwrap(); - assert_eq!(program.statements.len(), 1); - if let Statement::VarDecl { name, value, assignment_type } = &program.statements[0] { - assert_eq!(name, "x"); - assert_eq!(assignment_type, &AssignmentType::Equals); - if let Some(Expression::Literal(LiteralValue::Number(val))) = value { - assert_eq!(*val, 5.0); - } else { - panic!("Expected number literal"); - } - } else { - panic!("Expected VarDecl statement"); - } - } - - #[test] - fn test_if_stmt() { - let result = ScriptParser::parse("If x = 5 Then Var y = 10 EndIf"); - assert!(result.is_ok()); - } -} diff --git a/src/xml/vm/mod.rs b/src/xml/vm/mod.rs new file mode 100644 index 0000000..2cbd0b4 --- /dev/null +++ b/src/xml/vm/mod.rs @@ -0,0 +1,636 @@ +use std::collections::HashMap; + +use crate::xml::ast::nodes::{ + AssignmentType, BinaryOpKind, Expression, LiteralValue, Program, Statement, UnaryOpKind, +}; + +#[derive(Clone, Debug, PartialEq)] +pub enum Value { + Number(f64), + String(String), + Bool(bool), + Null, +} + +impl Value { + pub fn to_f64(&self) -> Option { + match self { + Value::Number(n) => Some(*n), + Value::String(s) => s.parse::().ok(), + Value::Bool(b) => Some(if *b { 1.0 } else { 0.0 }), + Value::Null => None, + } + } + + pub fn to_bool(&self) -> bool { + match self { + Value::Number(n) => *n != 0.0, + Value::String(s) => !s.is_empty(), + Value::Bool(b) => *b, + Value::Null => false, + } + } + + pub fn to_string_val(&self) -> String { + match self { + Value::Number(n) => { + if n.fract() == 0.0 { + format!("{}", *n as i64) + } else { + format!("{}", n) + } + } + Value::String(s) => s.clone(), + Value::Bool(b) => b.to_string(), + Value::Null => "null".to_string(), + } + } +} + +impl std::fmt::Display for Value { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Value::Number(n) => write!(f, "{}", n), + Value::String(s) => write!(f, "{}", s), + Value::Bool(b) => write!(f, "{}", b), + Value::Null => write!(f, "null"), + } + } +} + +impl From for Value { + fn from(n: f64) -> Self { Value::Number(n) } +} + +impl From for Value { + fn from(s: String) -> Self { Value::String(s) } +} + +impl From<&str> for Value { + fn from(s: &str) -> Self { Value::String(s.to_string()) } +} + +impl From for Value { + fn from(b: bool) -> Self { Value::Bool(b) } +} + +pub type Environment = HashMap; + +#[derive(Debug)] +pub enum VmError { + UndefinedVariable(String), + TypeError(String), + DivisionByZero, + UndefinedFunction(String), + NotIterable(Value), + RuntimeError(String), +} + +impl std::fmt::Display for VmError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + VmError::UndefinedVariable(name) => write!(f, "Undefined variable: {}", name), + VmError::TypeError(msg) => write!(f, "Type error: {}", msg), + VmError::DivisionByZero => write!(f, "Division by zero"), + VmError::UndefinedFunction(name) => write!(f, "Undefined function: {}", name), + VmError::NotIterable(v) => write!(f, "Not iterable: {:?}", v), + VmError::RuntimeError(msg) => write!(f, "Runtime error: {}", msg), + } + } +} + +impl std::error::Error for VmError {} + +pub type VmResult = Result; + +pub type NativeFn = fn(&[Value]) -> VmResult; + +fn builtin_abs(args: &[Value]) -> VmResult { + match args.first() { + Some(Value::Number(n)) => Ok(Value::Number(n.abs())), + _ => Err(VmError::TypeError("abs expects a number".into())), + } +} + +fn builtin_min(args: &[Value]) -> VmResult { + if args.len() < 2 { + return Err(VmError::TypeError("min expects at least 2 arguments".into())); + } + let nums: VmResult> = args.iter().map(|v| v.to_f64().ok_or_else(|| VmError::TypeError("min expects numbers".into()))).collect(); + let nums = nums?; + Ok(Value::Number(nums.iter().cloned().fold(f64::INFINITY, f64::min))) +} + +fn builtin_max(args: &[Value]) -> VmResult { + if args.len() < 2 { + return Err(VmError::TypeError("max expects at least 2 arguments".into())); + } + let nums: VmResult> = args.iter().map(|v| v.to_f64().ok_or_else(|| VmError::TypeError("max expects numbers".into()))).collect(); + let nums = nums?; + Ok(Value::Number(nums.iter().cloned().fold(f64::NEG_INFINITY, f64::max))) +} + +fn builtin_len(args: &[Value]) -> VmResult { + match args.first() { + Some(Value::String(s)) => Ok(Value::Number(s.len() as f64)), + _ => Err(VmError::TypeError("len expects a string".into())), + } +} + +fn builtin_str(args: &[Value]) -> VmResult { + match args.first() { + Some(v) => Ok(Value::String(v.to_string_val())), + None => Err(VmError::TypeError("str expects 1 argument".into())), + } +} + +fn builtin_num(args: &[Value]) -> VmResult { + match args.first() { + Some(Value::String(s)) => s.parse::().map(Value::Number).map_err(|_| VmError::TypeError("num: invalid number string".into())), + Some(Value::Number(n)) => Ok(Value::Number(*n)), + Some(Value::Bool(b)) => Ok(Value::Number(if *b { 1.0 } else { 0.0 })), + _ => Err(VmError::TypeError("num expects a string or number".into())), + } +} + +fn builtin_int(args: &[Value]) -> VmResult { + match args.first() { + Some(Value::Number(n)) => Ok(Value::Number(n.trunc())), + Some(Value::String(s)) => s.parse::().map(|n| Value::Number(n.trunc())).map_err(|_| VmError::TypeError("int: invalid number string".into())), + _ => Err(VmError::TypeError("int expects a number or string".into())), + } +} + +pub struct Vm { + globals: Environment, + functions: HashMap, +} + +impl Vm { + pub fn new() -> Self { + let mut vm = Vm { + globals: Environment::new(), + functions: HashMap::new(), + }; + vm.register_builtins(); + vm + } + + pub fn with_globals(globals: Environment) -> Self { + let mut vm = Vm { + globals, + functions: HashMap::new(), + }; + vm.register_builtins(); + vm + } + + pub fn set_global(&mut self, name: impl Into, value: Value) { + self.globals.insert(name.into(), value); + } + + pub fn get_global(&self, name: &str) -> Option<&Value> { + self.globals.get(name) + } + + pub fn register_function(&mut self, name: impl Into, func: NativeFn) { + self.functions.insert(name.into(), func); + } + + fn register_builtins(&mut self) { + self.register_function("abs", builtin_abs); + self.register_function("min", builtin_min); + self.register_function("max", builtin_max); + self.register_function("len", builtin_len); + self.register_function("str", builtin_str); + self.register_function("num", builtin_num); + self.register_function("int", builtin_int); + } + + pub fn run(&mut self, program: &Program) -> VmResult<()> { + for stmt in &program.statements { + self.exec_statement(stmt)?; + } + Ok(()) + } + + pub fn run_and_get_result(&mut self, program: &Program) -> VmResult { + let mut last_value = Value::Null; + for stmt in &program.statements { + if let Some(v) = self.exec_statement_for_value(stmt)? { + last_value = v; + } + } + Ok(last_value) + } + + fn eval_expr(&self, expr: &Expression) -> VmResult { + match expr { + Expression::Literal(lit) => Ok(match lit { + LiteralValue::String(s) => Value::String(s.clone()), + LiteralValue::Number(n) => Value::Number(*n), + LiteralValue::Bool(b) => Value::Bool(*b), + }), + + Expression::Identifier(name) => { + self.globals.get(name).cloned() + .ok_or_else(|| VmError::UndefinedVariable(name.clone())) + } + + Expression::BinaryOp { left, op, right } => { + let lval = self.eval_expr(left)?; + let rval = self.eval_expr(right)?; + Self::eval_binary_op(*op, lval, rval) + } + + Expression::UnaryOp { op, operand } => { + let val = self.eval_expr(operand)?; + match op { + UnaryOpKind::Neg => { + val.to_f64() + .map(|n| Value::Number(-n)) + .ok_or_else(|| VmError::TypeError("Cannot negate non-number".into())) + } + UnaryOpKind::Not => Ok(Value::Bool(!val.to_bool())), + } + } + + Expression::SpecialVar { name, is_negative } => { + let lookup = format!("${}", name); + let val = self.globals.get(&lookup).cloned() + .ok_or_else(|| VmError::UndefinedVariable(format!("${}", name)))?; + if *is_negative { + val.to_f64() + .map(|n| Value::Number(-n)) + .ok_or_else(|| VmError::TypeError("Cannot negate non-number special var".into())) + } else { + Ok(val) + } + } + + Expression::AutoVarExpr { variable } => { + self.eval_expr(variable) + } + + Expression::FunctionCall { name, args } => { + let evaluated_args: VmResult> = args.iter().map(|a| self.eval_expr(a)).collect(); + let evaluated_args = evaluated_args?; + + if let Some(func) = self.functions.get(name) { + func(&evaluated_args) + } else { + Err(VmError::UndefinedFunction(name.clone())) + } + } + + Expression::ArrayAccess { name, indices } => { + let base = self.globals.get(name).cloned() + .ok_or_else(|| VmError::UndefinedVariable(name.clone()))?; + let idx_vals: VmResult> = indices.iter().map(|i| self.eval_expr(i)).collect(); + let idx_vals = idx_vals?; + match (&base, idx_vals.first()) { + (Value::String(s), Some(Value::Number(idx))) => { + let i = *idx as usize; + s.chars().nth(i) + .map(|c| Value::String(c.to_string())) + .ok_or_else(|| VmError::RuntimeError(format!("String index {} out of bounds", i))) + } + _ => Err(VmError::TypeError("Array access not supported for this type".into())) + } + } + + Expression::FlagExpr { args } => { + let evaluated_args: VmResult> = args.iter().map(|a| self.eval_expr(a)).collect(); + let evaluated_args = evaluated_args?; + if let Some(func) = self.functions.get("flag") { + func(&evaluated_args) + } else { + Ok(Value::Bool(true)) + } + } + + Expression::StringConcat { parts } => { + let result: VmResult = parts.iter().map(|p| { + self.eval_expr(p).map(|v| v.to_string_val()) + }).collect(); + Ok(Value::String(result?)) + } + } + } + + fn eval_binary_op(op: BinaryOpKind, left: Value, right: Value) -> VmResult { + match op { + BinaryOpKind::Add => { + match (&left, &right) { + (Value::Number(l), Value::Number(r)) => Ok(Value::Number(l + r)), + (Value::String(l), Value::String(r)) => Ok(Value::String(format!("{}{}", l, r))), + (Value::String(l), r) => Ok(Value::String(format!("{}{}", l, r.to_string_val()))), + (l, Value::String(r)) => Ok(Value::String(format!("{}{}", l.to_string_val(), r))), + _ => Err(VmError::TypeError(format!("Cannot add {:?} and {:?}", left, right))), + } + } + BinaryOpKind::Sub => { + let l = left.to_f64().ok_or_else(|| VmError::TypeError("Cannot subtract non-numbers".into()))?; + let r = right.to_f64().ok_or_else(|| VmError::TypeError("Cannot subtract non-numbers".into()))?; + Ok(Value::Number(l - r)) + } + BinaryOpKind::Mul => { + let l = left.to_f64().ok_or_else(|| VmError::TypeError("Cannot multiply non-numbers".into()))?; + let r = right.to_f64().ok_or_else(|| VmError::TypeError("Cannot multiply non-numbers".into()))?; + Ok(Value::Number(l * r)) + } + BinaryOpKind::Div => { + let l = left.to_f64().ok_or_else(|| VmError::TypeError("Cannot divide non-numbers".into()))?; + let r = right.to_f64().ok_or_else(|| VmError::TypeError("Cannot divide non-numbers".into()))?; + if r == 0.0 { + Err(VmError::DivisionByZero) + } else { + Ok(Value::Number(l / r)) + } + } + BinaryOpKind::Eq => Ok(Value::Bool(left == right)), + BinaryOpKind::Neq => Ok(Value::Bool(left != right)), + BinaryOpKind::Lt => { + let l = left.to_f64().ok_or_else(|| VmError::TypeError("Cannot compare non-numbers".into()))?; + let r = right.to_f64().ok_or_else(|| VmError::TypeError("Cannot compare non-numbers".into()))?; + Ok(Value::Bool(l < r)) + } + BinaryOpKind::Gt => { + let l = left.to_f64().ok_or_else(|| VmError::TypeError("Cannot compare non-numbers".into()))?; + let r = right.to_f64().ok_or_else(|| VmError::TypeError("Cannot compare non-numbers".into()))?; + Ok(Value::Bool(l > r)) + } + BinaryOpKind::Lte => { + let l = left.to_f64().ok_or_else(|| VmError::TypeError("Cannot compare non-numbers".into()))?; + let r = right.to_f64().ok_or_else(|| VmError::TypeError("Cannot compare non-numbers".into()))?; + Ok(Value::Bool(l <= r)) + } + BinaryOpKind::Gte => { + let l = left.to_f64().ok_or_else(|| VmError::TypeError("Cannot compare non-numbers".into()))?; + let r = right.to_f64().ok_or_else(|| VmError::TypeError("Cannot compare non-numbers".into()))?; + Ok(Value::Bool(l >= r)) + } + } + } + + fn exec_statement(&mut self, stmt: &Statement) -> VmResult<()> { + match stmt { + Statement::VarDecl { name, value, assignment_type } => { + match assignment_type { + AssignmentType::Equals => { + if let Some(expr) = value { + let val = self.eval_expr(expr)?; + self.globals.insert(name.clone(), val); + } else { + self.globals.insert(name.clone(), Value::Null); + } + } + AssignmentType::NotAssigned => { + self.globals.insert(name.clone(), Value::Null); + } + } + Ok(()) + } + Statement::IfStmt { condition, then_branch, else_branch } => { + let cond_val = self.eval_expr(condition)?; + if cond_val.to_bool() { + for s in then_branch { + self.exec_statement(s)?; + } + } else { + for s in else_branch { + self.exec_statement(s)?; + } + } + Ok(()) + } + Statement::ForStmt { variable, iterable, body } => { + let iter_val = self.eval_expr(iterable)?; + match iter_val { + Value::Number(n) => { + for i in 0..(n as i64) { + self.globals.insert(variable.clone(), Value::Number(i as f64)); + for s in body { + self.exec_statement(s)?; + } + } + } + _ => { + return Err(VmError::NotIterable(iter_val)); + } + } + Ok(()) + } + Statement::ExprStmt { expression } => { + self.eval_expr(expression)?; + Ok(()) + } + } + } + + fn exec_statement_for_value(&mut self, stmt: &Statement) -> VmResult> { + match stmt { + Statement::VarDecl { name, value, assignment_type } => { + match assignment_type { + AssignmentType::Equals => { + if let Some(expr) = value { + let val = self.eval_expr(expr)?; + self.globals.insert(name.clone(), val.clone()); + Ok(Some(val)) + } else { + self.globals.insert(name.clone(), Value::Null); + Ok(None) + } + } + AssignmentType::NotAssigned => { + self.globals.insert(name.clone(), Value::Null); + Ok(None) + } + } + } + Statement::ExprStmt { expression } => { + let val = self.eval_expr(expression)?; + Ok(Some(val)) + } + _ => { + self.exec_statement(stmt)?; + Ok(None) + } + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + fn parse_and_run(source: &str) -> VmResult { + let program = crate::xml::parser::ScriptParser::parse(source) + .map_err(|e| VmError::RuntimeError(e.to_string()))?; + let mut vm = Vm::new(); + vm.run_and_get_result(&program) + } + + fn parse_and_run_with_globals(source: &str, globals: Environment) -> VmResult { + let program = crate::xml::parser::ScriptParser::parse(source) + .map_err(|e| VmError::RuntimeError(e.to_string()))?; + let mut vm = Vm::with_globals(globals); + vm.run_and_get_result(&program) + } + + #[test] + fn test_var_decl_number() { + let result = parse_and_run("Var x = 42"); + assert!(result.is_ok()); + assert_eq!(result.unwrap(), Value::Number(42.0)); + } + + #[test] + fn test_var_decl_string() { + let result = parse_and_run(r#"Var x = "hello""#); + assert!(result.is_ok()); + assert_eq!(result.unwrap(), Value::String("hello".to_string())); + } + + #[test] + fn test_arithmetic() { + let result = parse_and_run("Var x = 2 + 3 * 4"); + assert!(result.is_ok()); + assert_eq!(result.unwrap(), Value::Number(14.0)); + } + + #[test] + fn test_arithmetic_with_parens() { + let result = parse_and_run("Var x = (2 + 3) * 4"); + assert!(result.is_ok()); + assert_eq!(result.unwrap(), Value::Number(20.0)); + } + + #[test] + fn test_comparison_eq() { + let mut globals = Environment::new(); + globals.insert("x".to_string(), Value::Number(5.0)); + let program = crate::xml::parser::ScriptParser::parse("If x == 5 Then Var y = 1 Else Var y = 0 EndIf") + .map_err(|e| VmError::RuntimeError(e.to_string())).unwrap(); + let mut vm = Vm::with_globals(globals); + vm.run(&program).unwrap(); + assert_eq!(*vm.get_global("y").unwrap(), Value::Number(1.0)); + } + + #[test] + fn test_comparison_neq() { + let mut globals = Environment::new(); + globals.insert("x".to_string(), Value::Number(3.0)); + let program = crate::xml::parser::ScriptParser::parse("If x != 5 Then Var y = 1 Else Var y = 0 EndIf") + .map_err(|e| VmError::RuntimeError(e.to_string())).unwrap(); + let mut vm = Vm::with_globals(globals); + vm.run(&program).unwrap(); + assert_eq!(*vm.get_global("y").unwrap(), Value::Number(1.0)); + } + + #[test] + fn test_if_else_false() { + let mut globals = Environment::new(); + globals.insert("x".to_string(), Value::Number(10.0)); + let program = crate::xml::parser::ScriptParser::parse("If x == 5 Then Var y = 1 Else Var y = 2 EndIf") + .map_err(|e| VmError::RuntimeError(e.to_string())).unwrap(); + let mut vm = Vm::with_globals(globals); + vm.run(&program).unwrap(); + assert_eq!(*vm.get_global("y").unwrap(), Value::Number(2.0)); + } + + #[test] + fn test_bool_literals() { + let result = parse_and_run("Var x = True"); + assert!(result.is_ok()); + assert_eq!(result.unwrap(), Value::Bool(true)); + + let result = parse_and_run("Var x = False"); + assert!(result.is_ok()); + assert_eq!(result.unwrap(), Value::Bool(false)); + } + + #[test] + fn test_string_concat_via_add() { + let result = parse_and_run(r#"Var x = "hello" + " world""#); + assert!(result.is_ok()); + assert_eq!(result.unwrap(), Value::String("hello world".to_string())); + } + + #[test] + fn test_negation() { + let result = parse_and_run("Var x = -5"); + assert!(result.is_ok()); + assert_eq!(result.unwrap(), Value::Number(-5.0)); + } + + #[test] + fn test_not() { + let mut globals = Environment::new(); + globals.insert("x".to_string(), Value::Bool(true)); + let result = parse_and_run_with_globals("Var y = !x", globals); + assert!(result.is_ok()); + assert_eq!(result.unwrap(), Value::Bool(false)); + } + + #[test] + fn test_special_var() { + let mut globals = Environment::new(); + globals.insert("$count".to_string(), Value::Number(10.0)); + let result = parse_and_run_with_globals("Var x = $count", globals); + assert!(result.is_ok()); + assert_eq!(result.unwrap(), Value::Number(10.0)); + } + + #[test] + fn test_special_var_negative() { + let mut globals = Environment::new(); + globals.insert("$count".to_string(), Value::Number(10.0)); + let result = parse_and_run_with_globals("Var x = $-count", globals); + assert!(result.is_ok()); + assert_eq!(result.unwrap(), Value::Number(-10.0)); + } + + #[test] + fn test_builtin_abs() { + let result = parse_and_run("Var x = abs(-5)"); + assert!(result.is_ok()); + assert_eq!(result.unwrap(), Value::Number(5.0)); + } + + #[test] + fn test_builtin_len() { + let result = parse_and_run(r#"Var x = len("hello")"#); + assert!(result.is_ok()); + assert_eq!(result.unwrap(), Value::Number(5.0)); + } + + #[test] + fn test_for_loop() { + let program = crate::xml::parser::ScriptParser::parse("For i In 3 Var x = i EndFor") + .map_err(|e| VmError::RuntimeError(e.to_string())).unwrap(); + let mut vm = Vm::new(); + vm.run(&program).unwrap(); + let val = vm.get_global("x").unwrap(); + assert_eq!(*val, Value::Number(2.0)); + } + + #[test] + fn test_division() { + let result = parse_and_run("Var x = 10 / 2"); + assert!(result.is_ok()); + assert_eq!(result.unwrap(), Value::Number(5.0)); + } + + #[test] + fn test_division_by_zero() { + let result = parse_and_run("Var x = 10 / 0"); + assert!(result.is_err()); + } + + #[test] + fn test_undefined_variable() { + let result = parse_and_run("Var x = unknown_var"); + assert!(result.is_err()); + } +} \ No newline at end of file diff --git a/uniffi-bindgen.rs b/uniffi-bindgen.rs new file mode 100644 index 0000000..f6cff6c --- /dev/null +++ b/uniffi-bindgen.rs @@ -0,0 +1,3 @@ +fn main() { + uniffi::uniffi_bindgen_main() +}