Added a calculator test program.
This commit is contained in:
@@ -0,0 +1,129 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user