using System; using System.Collections.Generic; using SLexGenerated; using SCCGenerated; namespace SLexSccCalc { class Program { static double Evaluate(SyntaxNode? node) { if (node == null) return 0.0; switch (node.Id) { case SyntaxId.number_expr: if (node.Children.Count > 0 && node.Children[0].EnclosureType == EnclosureType.Segment) { var seg = node.Children[0].Segment; if (seg != null) return double.Parse(seg.Content); } return 0.0; case SyntaxId.group_expr: if (node.Children.Count > 0 && node.Children[0].EnclosureType == EnclosureType.Node) { return Evaluate(node.Children[0].Node); } return 0.0; case SyntaxId.term: case SyntaxId.expr: if (node.Children.Count > 0 && node.Children[0].EnclosureType == EnclosureType.Node) { return Evaluate(node.Children[0].Node); } return 0.0; case SyntaxId.add_expr: if (node.Children.Count == 3 && node.Children[0].EnclosureType == EnclosureType.Node && node.Children[2].EnclosureType == EnclosureType.Node) { return Evaluate(node.Children[0].Node) + Evaluate(node.Children[2].Node); } return 0.0; case SyntaxId.sub_expr: if (node.Children.Count == 3 && node.Children[0].EnclosureType == EnclosureType.Node && node.Children[2].EnclosureType == EnclosureType.Node) { return Evaluate(node.Children[0].Node) - Evaluate(node.Children[2].Node); } return 0.0; case SyntaxId.mul_expr: if (node.Children.Count == 3 && node.Children[0].EnclosureType == EnclosureType.Node && node.Children[2].EnclosureType == EnclosureType.Node) { return Evaluate(node.Children[0].Node) * Evaluate(node.Children[2].Node); } return 0.0; case SyntaxId.div_expr: if (node.Children.Count == 3 && node.Children[0].EnclosureType == EnclosureType.Node && node.Children[2].EnclosureType == EnclosureType.Node) { double divisor = Evaluate(node.Children[2].Node); if (divisor == 0.0) { throw new DivideByZeroException("Error: Division by zero!"); } return Evaluate(node.Children[0].Node) / divisor; } return 0.0; default: return 0.0; } } static void PrintAST(SyntaxNode? node, int indent) { if (node == null) return; Console.WriteLine(new string(' ', indent * 2) + $"Node: {node.SyntaxName} (id={node.Id}, child_count={node.Children.Count})"); foreach (var child in node.Children) { if (child.EnclosureType == EnclosureType.Node) { PrintAST(child.Node, indent + 1); } else if (child.Segment != null) { Console.WriteLine(new string(' ', (indent + 1) * 2) + $"Segment: '{child.Segment.Content}' (tag={child.Segment.Tag}, id={child.Segment.Id})"); } } } static void Main(string[] args) { string inputExpr = args.Length > 0 ? string.Join(" ", args) : "3 + 4 * ( 5 - 2 )"; Console.WriteLine($"Lexing input expression: \"{inputExpr}\""); var lexer = new SLexer(); if (!lexer.SLex(inputExpr, out Segment? lexerHead) || lexerHead == null) { Console.Error.WriteLine("Error: Lexical analysis failed"); return; } Console.WriteLine("Parsing lexical segments..."); var parser = new SCC(); if (!parser.Parse(lexerHead, out SyntaxNode? root) || root == null) { Console.Error.WriteLine("Error: Parsing failed"); return; } Console.WriteLine("\nAST Structure:"); PrintAST(root, 0); try { double result = Evaluate(root); Console.WriteLine("\nEvaluation Result:"); Console.WriteLine($"{inputExpr} = {result}"); } catch (Exception ex) { Console.Error.WriteLine(ex.Message); } } } }