Skip to main content
Glama
CommandParser.cs7.42 kB
using System; using System.Collections.Generic; using System.Text.RegularExpressions; using UnityEngine; namespace UnityMCP.Client.Editor.Commands { /// <summary> /// Parser for converting code into commands /// </summary> public static class CommandParser { /// <summary> /// Parse code into a sequence of commands /// </summary> /// <param name="code">The code to parse</param> /// <returns>A list of commands to execute</returns> public static List<ICommand> Parse(string code) { var commands = new List<ICommand>(); try { // Trim the code code = code.Trim(); // Split the code into statements string[] statements = code.Split(new[] { ';', '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries); // Parse each statement foreach (string statement in statements) { string trimmedStatement = statement.Trim(); if (string.IsNullOrEmpty(trimmedStatement)) { continue; } // Try to parse the statement using the ExpressionParser var parser = new ExpressionParser(trimmedStatement); ICommand command = parser.Parse(); if (command != null) { commands.Add(command); } } } catch (Exception ex) { Debug.LogError($"[Unity MCP] Error parsing code: {ex.Message}"); commands.Add(new GenericCommand(code)); } return commands; } /// <summary> /// Parse a single statement into a command /// </summary> /// <param name="statement">The statement to parse</param> /// <returns>The command to execute, or null if the statement couldn't be parsed</returns> private static ICommand ParseStatement(string statement) { // Check if it's a variable assignment Match assignmentMatch = Regex.Match(statement, @"^\s*var\s+(\w+)\s*=\s*(.+)$"); if (assignmentMatch.Success) { string variableName = assignmentMatch.Groups[1].Value; string expression = assignmentMatch.Groups[2].Value; // Parse the expression return ParseExpression(expression, variableName); } // Check if it's a property access Match propertyMatch = Regex.Match(statement, @"^\s*(\w+)\.(\w+)\s*$"); if (propertyMatch.Success) { string objectName = propertyMatch.Groups[1].Value; string propertyName = propertyMatch.Groups[2].Value; // Create a property command return new PropertyCommand(objectName, propertyName); } // Check if it's a GameObject access Match gameObjectMatch = Regex.Match(statement, @"^\s*GameObject\[""([^""]+)""\](.*)$"); if (gameObjectMatch.Success) { string gameObjectName = gameObjectMatch.Groups[1].Value; string rest = gameObjectMatch.Groups[2].Value; // Create a find command string resultVariableName = "_temp_" + Guid.NewGuid().ToString("N").Substring(0, 8); var findCommand = new FindGameObjectCommand(gameObjectName, resultVariableName); // If there's more to the expression, parse it if (!string.IsNullOrEmpty(rest)) { // Check if it's a property access Match restPropertyMatch = Regex.Match(rest, @"^\s*\.(\w+)\s*$"); if (restPropertyMatch.Success) { string propertyName = restPropertyMatch.Groups[1].Value; // Create a property command return new PropertyCommand(resultVariableName, propertyName); } } return findCommand; } // Check if it's a Debug.Log Match logMatch = Regex.Match(statement, @"^\s*Debug\.Log\((.+)\)\s*$"); if (logMatch.Success) { string message = logMatch.Groups[1].Value; // Create a log command return new LogCommand(statement); } // Check if it's a new GameObject Match gameObjectCreateMatch = Regex.Match(statement, @"^\s*new\s+GameObject\((.+)\)\s*$"); if (gameObjectCreateMatch.Success) { // Create a create GameObject command return new CreateGameObjectCommand(statement); } // If we couldn't parse the statement, return a generic command return new GenericCommand(statement); } /// <summary> /// Parse an expression into a command /// </summary> /// <param name="expression">The expression to parse</param> /// <param name="resultVariableName">The variable name to store the result in, if any</param> /// <returns>The command to execute, or null if the expression couldn't be parsed</returns> private static ICommand ParseExpression(string expression, string resultVariableName = null) { // Check if it's a GameObject access Match gameObjectMatch = Regex.Match(expression, @"^\s*GameObject\[""([^""]+)""\](.*)$"); if (gameObjectMatch.Success) { string gameObjectName = gameObjectMatch.Groups[1].Value; string rest = gameObjectMatch.Groups[2].Value; // Create a find command string tempVariableName = "_temp_" + Guid.NewGuid().ToString("N").Substring(0, 8); var findCommand = new FindGameObjectCommand(gameObjectName, string.IsNullOrEmpty(rest) ? resultVariableName : tempVariableName); // If there's more to the expression, parse it if (!string.IsNullOrEmpty(rest)) { // Check if it's a property access Match restPropertyMatch = Regex.Match(rest, @"^\s*\.(\w+)\s*$"); if (restPropertyMatch.Success) { string propertyName = restPropertyMatch.Groups[1].Value; // Create a property command return new PropertyCommand(tempVariableName, propertyName, resultVariableName); } } return findCommand; } // Check if it's a new GameObject Match gameObjectCreateMatch = Regex.Match(expression, @"^\s*new\s+GameObject\((.+)\)\s*$"); if (gameObjectCreateMatch.Success) { // Create a create GameObject command return new CreateGameObjectCommand(expression, resultVariableName); } // If we couldn't parse the expression, return a generic command return new GenericCommand(expression, resultVariableName); } } }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/TSavo/Unity-MCP'

If you have feedback or need assistance with the MCP directory API, please join our Discord server