AScript represents an innovative open-source C# dynamic script parsing and execution library that supports customizable syntax parsing. This powerful framework enables developers to create domain-specific languages tailored to their specific needs. In this comprehensive guide, we explore how to build a Chinese scripting engine example using AScript, demonstrating the implementation of conditional statements using natural language constructs: "如果...则...否则..." (If...Then...Else...).

Understanding AScript's Architecture

AScript's flexibility stems from its modular design, which separates token handling, syntax analysis, and execution contexts. This architecture allows developers to define custom grammars without modifying the core engine. The library provides several key extension points:

  • ITokenHandler Interface: For defining custom syntax parsing rules
  • ScriptLang Base Class: For establishing language-specific environments
  • BuildOptions Configuration: For controlling tree generation behavior

This modular approach makes AScript particularly suitable for creating domain-specific languages (DSLs) that align closely with business terminology and natural language patterns.

Step 1: Implementing the ITokenHandler Interface

The foundation of our Chinese scripting engine lies in creating a custom token handler for conditional statements. The 如果语法处理器 (IfSyntaxHandler) class implements the ITokenHandler interface to define how the parser should recognize and process Chinese conditional constructs.

public class 如果语法处理器 : ITokenHandler
{
    private static readonly HashSet<string> _StatementEndTokens = 
        new HashSet<string> { "则", "否则" };

    public void Build(DefaultSyntaxAnalyzer analyzer, TokenAnalyzingArgs e)
    {
        e.IsHandled = true;
        e.End = true;

        // If there's already a statement, push back and return
        if (e.TreeBuilder.Root != null)
        {
            e.TokenReader.Push(e.CurrentToken);
            return;
        }

        // Build the condition expression until we hit "则" or "否则"
        var condition = analyzer.BuildOneStatement(
            e.BuildContext, 
            e.ScriptContext, 
            e.Options, 
            e.TokenReader, 
            e.Control, 
            e.Ignore, 
            endTokens: _StatementEndTokens
        );
        
        // Validate and consume the "则" keyword
        analyzer.ValidateNextToken(e.TokenReader, "则");
        
        // Build the main body with full tree creation
        var createAllOptions = new BuildOptions(e.Options) 
        { 
            CreateFullTreeNode = true 
        };
        var body = analyzer.BuildOneStatement(
            e.BuildContext, 
            e.ScriptContext, 
            createAllOptions, 
            e.TokenReader, 
            e.Control, 
            e.Ignore, 
            endTokens: _StatementEndTokens
        );
        
        // Create the IF node with condition and body
        var node = new IfNode 
        { 
            Condition = condition, 
            Body = body 
        };
        
        // Check for optional semicolon
        var nextToken = e.TokenReader.Read();
        if (nextToken.HasValue && nextToken.Value.Value == ";")
        {
            nextToken = e.TokenReader.Read();
        }
        
        // Handle optional "否则" (else) clause
        if (nextToken.HasValue)
        {
            if (nextToken.Value.Value == "否则")
            {
                node.Else = analyzer.BuildOneStatement(
                    e.BuildContext, 
                    e.ScriptContext, 
                    createAllOptions, 
                    e.TokenReader, 
                    e.Control, 
                    e.Ignore
                );
            }
            else
            {
                e.TokenReader.Push(nextToken.Value);
            }
        }
        
        // Add the completed node to the tree
        e.TreeBuilder.Add(
            e.BuildContext, 
            e.ScriptContext, 
            e.Options, 
            e.Control, 
            node
        );
    }
}

This implementation demonstrates several important concepts:

Token Boundary Detection: The _StatementEndTokens HashSet defines which tokens signal the end of a condition or body segment. In our Chinese syntax, "则" marks the end of the condition, while "否则" can end either the condition or the main body.

Tree Building Logic: The handler carefully manages the syntax tree construction, ensuring proper nesting of conditional structures. The CreateFullTreeNode option ensures complete AST generation for complex expressions.

Else Clause Handling: The implementation gracefully handles optional else clauses, including nested "否则 如果" (else if) constructs, enabling sophisticated conditional logic.

Step 2: Defining the Chinese Language Environment

With the token handler in place, we create a ScriptLang subclass that establishes the Chinese language environment. This class defines available types, keywords, and their associated handlers.

public class 中文语言 : ScriptLang
{
    public static readonly 中文语言 实例 = new 中文语言();

    public 中文语言()
    {
        // Register Chinese type names
        AddType<int>("整型");
        AddType<string>("文本");

        // Register Chinese keyword handlers
        AddTokenHandler("如果", new 如果语法处理器());
        AddTokenHandler("返回", AScript.TokenHandlers.ReturnTokenHandler.Instance);
    }
}

This concise class accomplishes several critical tasks:

Type Registration: By mapping Chinese type names ("整型" for integer, "文本" for string) to their .NET counterparts, we enable developers to write type declarations in natural Chinese.

Keyword Binding: The AddTokenHandler method associates Chinese keywords with their parsing logic. "如果" triggers our custom conditional handler, while "返回" uses AScript's built-in return statement handler.

Singleton Pattern: The static 实例 (instance) field ensures consistent language configuration across all script executions.

Step 3: Registering the Chinese Language

Before scripts can be executed, the language must be registered with the AScript engine:

Script.Langs["中文"] = 中文语言。实例;

This single line makes the Chinese language available for script execution. The registration system supports multiple languages simultaneously, allowing applications to switch between different scripting environments as needed.

Step 4: Chinese Script Example

With the language registered, we can now write and execute scripts using natural Chinese syntax:

string s = @"
整型 n=10;
文本 s='';
如果 n<5 则 {
    s='小于 5';
} 否则 如果 n<20 则 {
    s='大于等于 5 且小于 20';
} 否则 {
    s='大于等于 20';
}
返回 $'{n},{s}';
";

var script = new Script();
Assert.AreEqual("10,大于等于 5 且小于 20", script.Eval(s));

This example demonstrates several powerful features:

Natural Language Variable Declarations: Variables are declared using Chinese type names, making the code immediately understandable to Chinese-speaking developers and business analysts.

Nested Conditional Logic: The script showcases nested "否则 如果" (else if) constructs, demonstrating the parser's ability to handle complex branching logic.

String Interpolation: The $'{n},{s}' syntax enables clean string formatting within the Chinese scripting context.

Expected Output: When executed with n=10, the script correctly evaluates the condition and returns "10,大于等于 5 且小于 20" (10, greater than or equal to 5 and less than 20).

Practical Applications of Chinese Scripting Engines

The Chinese scripting engine built with AScript opens numerous practical applications:

Business Rule Engines

Organizations can encode business rules in natural Chinese, enabling non-technical stakeholders to read, understand, and even modify rule definitions:

如果 客户等级 = "VIP" 则 {
    折扣 = 0.8;
} 否则 如果 订单金额 > 1000 则 {
    折扣 = 0.9;
} 否则 {
    折扣 = 1.0;
}

Educational Tools

Programming education becomes more accessible when students can learn logical concepts in their native language before transitioning to traditional programming syntax.

Configuration Systems

Complex configuration logic can be expressed in domain-specific Chinese terminology, reducing the cognitive load on operations teams.

Rapid Prototyping

Product managers and business analysts can prototype logic flows directly, accelerating the requirements gathering and validation process.

Technical Considerations and Best Practices

When building natural language scripting engines, several considerations ensure robust implementations:

Token Ambiguity Resolution

Natural languages often contain ambiguous constructs. Careful token boundary definition and context-aware parsing prevent misinterpretation of script intent.

Error Messaging

Error messages should be presented in the same language as the script, enabling users to understand and resolve issues without translation barriers.

Performance Optimization

For high-frequency script execution, consider caching parsed syntax trees and implementing efficient token lookup mechanisms.

Security Boundaries

Always validate script inputs and implement execution timeouts to prevent resource exhaustion from malformed or malicious scripts.

Extending the Chinese Language

The AScript framework supports extensive customization beyond conditional statements:

Loop Constructs: Implement "循环...直到..." (loop...until...) or "对于每个...执行..." (for each...execute...) patterns.

Function Definitions: Create "函数...结束函数" (function...end function) blocks for reusable logic.

Exception Handling: Add "尝试...捕获...结束" (try...catch...end) structures for error management.

Custom Operators: Define domain-specific operators that align with business terminology.

Conclusion

The Chinese scripting engine built with AScript demonstrates how natural language programming can bridge the gap between technical implementation and business understanding. By leveraging AScript's flexible token handling and syntax customization capabilities, developers can create domain-specific languages that resonate with their target users.

This approach is particularly valuable in contexts where:

  • Business rules change frequently
  • Non-technical stakeholders need to understand logic
  • Rapid iteration and prototyping are essential
  • Localization and accessibility are priorities

The example presented here serves as a foundation for more sophisticated natural language scripting systems. Interested developers are encouraged to experiment with AScript in their projects, adapting the patterns shown to their specific domain requirements and user needs.

The future of programming may well include multiple natural language options, democratizing software development and enabling broader participation in the digital economy.