You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从DSL的函数调用中提取变量名与数组索引?

Great question! Let's break down how to solve this problem step by step—covering reliable libraries, regex-based approaches, and even manual parsing for edge cases. The goal is to extract variable names (up to 4 layers deep) and optional array indices from function calls in your DSL, outputting a List<(string Name, int? Index)> result.

解决方案概述

First, let's clarify what we're targeting: every variable reference (with optional array access) inside function call parentheses. Variables can be simple like car, multi-layer like house.blah, or combined with array indices like building3[4] or building[4].foo[6].

一、可用库推荐(最可靠的选择)

If you want to avoid reinventing the wheel and handle edge cases gracefully, using a dedicated parsing library is your best bet:

  • ANTLR: You can define a custom grammar for your DSL (including rules for function calls, multi-layer variables, and array indices) and generate a fully functional parser. This is ideal if your DSL might grow more complex over time—ANTLR handles all the heavy lifting of syntax validation and tree traversal.
  • Roslyn: If your DSL mirrors C# syntax (like your examples), use the .NET Roslyn SDK. Treat the DSL string as a C# code snippet, parse it into a syntax tree, then traverse the tree to extract variable references and array indices. This works seamlessly because Roslyn already understands C#-style member access and array syntax.

二、正则表达式实现(快速简单场景)

For simpler use cases where your DSL doesn't have weird edge cases (like nested parentheses in strings), regex can get the job done quickly. Here's how to approach it:

正则设计思路

We'll split the problem into two parts:

  1. Extract all content inside function call parentheses.
  2. For each parameter in that content, parse multi-layer variables and optional array indices—even handling chained access like building[4].foo[6].

Core Regex Patterns

  • Extract function call parameters: \w+\((.*?)\) (uses non-greedy matching to capture everything inside each function's parentheses)
  • Parse individual variable parts: ^((?:\w+\.){0,3}\w+)(?:\[(\d+)\])?(?:\.(.*))?$
    • (?:\w+\.){0,3}\w+: Matches 1-4 layer variable names (e.g., car, house.blah, a.b.c.d)
    • (?:\[(\d+)\])?: Optional capture group for array indices (captures the numeric value inside [])
    • (?:\.(.*))?$: Captures any remaining chained member access (like .foo[6] in building[4].foo[6] to process recursively)

C# Code Example

using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;

public class DslVariableExtractor
{
    public static List<(string Name, int? Index)> ExtractFromDsl(string dslInput)
    {
        var extractedVariables = new List<(string, int?)>();
        
        // Step 1: Grab all function call parameter lists
        var functionCallRegex = new Regex(@"\w+\((.*?)\)", RegexOptions.Singleline);
        var functionMatches = functionCallRegex.Matches(dslInput);

        foreach (Match funcMatch in functionMatches)
        {
            var paramsContent = funcMatch.Groups[1].Value;
            // Split parameters by commas, ignoring whitespace
            var parameters = paramsContent.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);

            foreach (var param in parameters)
            {
                var currentSegment = param.Trim();
                // Recursively process chained access (e.g., building[4].foo[6])
                while (!string.IsNullOrEmpty(currentSegment))
                {
                    var variableRegex = new Regex(@"^((?:\w+\.){0,3}\w+)(?:\[(\d+)\])?(?:\.(.*))?$");
                    var varMatch = variableRegex.Match(currentSegment);

                    if (!varMatch.Success) break;

                    // Extract name and optional index
                    var varName = varMatch.Groups[1].Value;
                    int? index = string.IsNullOrEmpty(varMatch.Groups[2].Value) 
                        ? null 
                        : int.Parse(varMatch.Groups[2].Value);

                    extractedVariables.Add((varName, index));

                    // Move to the next chained segment (e.g., .foo[6] becomes foo[6] for next iteration)
                    currentSegment = varMatch.Groups[3].Value;
                }
            }
        }

        return extractedVariables;
    }

    // Test with your sample DSLs
    public static void Main()
    {
        var sample1 = "DoSomething(car); blahdoSomethingElse(house.blah)";
        var sample2 = "DoSomething(building3[4], building, houseA[5]); blahdoSomethingElse(thing.blah567[8])";
        var sample3 = "DoSomething(building[4].foo[6]); blahdoSomethingElse(thing.blah567[8])";

        Console.WriteLine("Sample 1 Results:");
        foreach (var item in ExtractFromDsl(sample1))
            Console.WriteLine($"Name: {item.Name}, Index: {item.Index ?? -1}");

        Console.WriteLine("\nSample 2 Results:");
        foreach (var item in ExtractFromDsl(sample2))
            Console.WriteLine($"Name: {item.Name}, Index: {item.Index ?? -1}");

        Console.WriteLine("\nSample 3 Results:");
        foreach (var item in ExtractFromDsl(sample3))
            Console.WriteLine($"Name: {item.Name}, Index: {item.Index ?? -1}");
    }
}

三、手动递归下降解析(复杂场景)

If your DSL has more complex syntax (like string literals with parentheses, comments, or nested structures), regex will fall short. A manual recursive descent parser is the way to go:

  1. Lexing: Convert the DSL string into a stream of tokens (identifiers, (, ), ., [, ], commas, numbers).
  2. Parsing: Traverse the token stream to identify function calls, then process each parameter to extract multi-layer variables and array indices recursively.

This approach gives you full control and handles edge cases that regex can't, but requires more code upfront.

Key Notes

  • Regex is great for quick wins, but avoid it if your DSL might evolve or has non-trivial syntax.
  • Roslyn is a no-brainer if your DSL is C#-like—it handles all the edge cases you might not even think about (like whitespace variations, escaped characters, etc.).

内容的提问来源于stack exchange,提问作者TheColonel26

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 08:47:59