private bool TryParseInputExpression(string inputSymbol, out IdentifierNode identifier, out AssociativeNode defaultValue, out string comment) { identifier = null; defaultValue = null; comment = null; var parseString = InputSymbol; parseString += ";"; // During loading of symbol node from file, the elementResolver from the workspace is unavailable // in which case, a local copy of the ER obtained from the symbol node is used var resolver = workspaceElementResolver ?? ElementResolver; var parseParam = new ParseParam(this.GUID, parseString, resolver); if (EngineController.CompilationServices.PreCompileCodeBlock(ref parseParam) && parseParam.ParsedNodes.Any()) { var parsedComments = parseParam.ParsedComments; if (parsedComments.Any()) { comment = String.Join("\n", parsedComments.Select(c => (c as CommentNode).Value)); } var node = parseParam.ParsedNodes.First() as BinaryExpressionNode; Validity.Assert(node != null); if (node != null) { identifier = node.LeftNode as IdentifierNode; if (inputSymbol.Contains('=')) { defaultValue = node.RightNode; } if (parseParam.Errors.Any()) { this.Error(parseParam.Errors.First().Message); } else if (parseParam.Warnings.Any()) { var warnings = parseParam.Warnings.Where(w => w.ID != WarningID.kIdUnboundIdentifier); if (warnings.Any()) { this.Warning(parseParam.Warnings.First().Message); } } return(identifier != null); } } return(false); }
public void ReproMAGN3603() { string code = @"a = 1 + (2 * 3); b = (1 + 2) * 3; c = 1 + 2 * 3;"; ElementResolver elementResolver = new ElementResolver(); ParseParam parseParam = new ParseParam(Guid.NewGuid(), code, elementResolver); Assert.IsTrue(CompilerUtils.PreCompileCodeBlock(thisTest.CreateTestCore(), ref parseParam)); Assert.IsTrue(parseParam.ParsedNodes != null && parseParam.ParsedNodes.Count() > 0); var parsedNode = parseParam.ParsedNodes.ElementAt(0); BinaryExpressionNode n = parsedNode as BinaryExpressionNode; FunctionCallNode funcCall = n.RightNode as FunctionCallNode; Assert.IsTrue(n != null && funcCall != null); IdentifierNode identNode = funcCall.Function as IdentifierNode; Assert.IsTrue(identNode != null && identNode.Value == "%add"); var args = funcCall.FormalArguments; Assert.IsTrue(args.Count == 2); Assert.IsTrue(args[0] is IntNode); FunctionCallNode nestedFuncCall = args[1] as FunctionCallNode; Assert.IsTrue(nestedFuncCall != null && (nestedFuncCall.Function as IdentifierNode).Value == "%mul"); parsedNode = parseParam.ParsedNodes.ElementAt(1); n = parsedNode as BinaryExpressionNode; funcCall = n.RightNode as FunctionCallNode; Assert.IsTrue(n != null && funcCall != null); identNode = funcCall.Function as IdentifierNode; Assert.IsTrue(identNode != null && identNode.Value == "%mul"); args = funcCall.FormalArguments; Assert.IsTrue(args.Count == 2); Assert.IsTrue(args[1] is IntNode); nestedFuncCall = args[0] as FunctionCallNode; Assert.IsTrue(nestedFuncCall != null && (nestedFuncCall.Function as IdentifierNode).Value == "%add"); parsedNode = parseParam.ParsedNodes.ElementAt(2); n = parsedNode as BinaryExpressionNode; funcCall = n.RightNode as FunctionCallNode; Assert.IsTrue(n != null && funcCall != null); identNode = funcCall.Function as IdentifierNode; Assert.IsTrue(identNode != null && identNode.Value == "%add"); args = funcCall.FormalArguments; Assert.IsTrue(args.Count == 2); Assert.IsTrue(args[0] is IntNode); nestedFuncCall = args[1] as FunctionCallNode; Assert.IsTrue(nestedFuncCall != null && (nestedFuncCall.Function as IdentifierNode).Value == "%mul"); }
public void TestUnboundIdentifierInUnnamedSignedExpression() { string code = @"a*-1;"; ElementResolver elementResolver = new ElementResolver(); ParseParam parseParam = new ParseParam(Guid.NewGuid(), code, elementResolver); Assert.IsTrue(CompilerUtils.PreCompileCodeBlock(thisTest.CreateTestCore(), ref parseParam)); Assert.IsTrue(parseParam.ParsedNodes != null && parseParam.ParsedNodes.Any()); var inputIdentifier = parseParam.UnboundIdentifiers; Assert.AreEqual(1, inputIdentifier.Count); Assert.AreEqual("a", inputIdentifier.ElementAt(0).Value); }
private bool TryParseInputSymbol(string inputSymbol, out IdentifierNode identifier, out AssociativeNode defaultValue) { identifier = null; defaultValue = null; // workaround: there is an issue in parsing "x:int" format unless // we create the other parser specially for it. We change it to // "x:int = dummy;" for parsing. var parseString = InputSymbol; // if it has default value, then append ';' if (InputSymbol.Contains("=")) { parseString += ";"; } else { String dummyExpression = "{0}=dummy;"; parseString = string.Format(dummyExpression, parseString); } ParseParam parseParam = new ParseParam(this.GUID, parseString); if (EngineController.CompilationServices.PreCompileCodeBlock(ref parseParam) && parseParam.ParsedNodes != null && parseParam.ParsedNodes.Any()) { var node = parseParam.ParsedNodes.First() as BinaryExpressionNode; Validity.Assert(node != null); if (node != null) { identifier = node.LeftNode as IdentifierNode; if (inputSymbol.Contains('=')) { defaultValue = node.RightNode; } return(identifier != null); } } return(false); }
public void TestUnboundIdentifierInBinaryExpression() { var binaryExpressions = new[] { "x==-0.5;", "x>0.5;", "x<-1;", "x!=1;", "x<=\"a\";", "x>='a';", "x==true;", "x!=false;", "x==null;" }; foreach (var expression in binaryExpressions) { ElementResolver elementResolver = new ElementResolver(); ParseParam parseParam = new ParseParam(Guid.NewGuid(), expression, elementResolver); Assert.IsTrue(CompilerUtils.PreCompileCodeBlock(thisTest.CreateTestCore(), ref parseParam)); Assert.IsTrue(parseParam.ParsedNodes != null && parseParam.ParsedNodes.Any()); var inputIdentifier = parseParam.UnboundIdentifiers; Assert.AreEqual(1, inputIdentifier.Count); Assert.AreEqual("x", inputIdentifier.ElementAt(0).Value); } }
static void CreatAllCS() { Parser parser = new Parser(); if (!Directory.Exists(Application.dataPath + "/" + m_CsConfigFilePath)) { Directory.CreateDirectory(Application.dataPath + "/" + m_CsConfigFilePath); } var param = new ParseParam() { ExcelDir = Application.dataPath + "/" + m_ExcelPath, Serializations = new SerializationParam[] { new SerializationParam() { Serializer = mDic_form_seria[m_DataForm], OutDir = Application.dataPath + "/" + m_DataFilePath, }, }, }; param.Generations = new GenerationParam[] { new GenerationParam() { Generator = new TupledCSharpGenerator(), OutDir = Application.dataPath + "/" + m_CsConfigFilePath, DataDir = Application.dataPath + "/" + m_DataFilePath, Package = m_Namespace, From = m_DataForm, }, }; // 生成初始化类 var sheets = GetAllExcelName(param.ExcelDir); UpdateConfigInitiator(sheets, param.Generations[0]); // 生成配置类 parser.ParseAll(param); param = null; parser = null; AssetDatabase.Refresh(); }
private bool TryParseOutputExpression(string expression, out IdentifierNode outputIdentifier, out string comment) { outputIdentifier = null; comment = null; var resolver = workspaceElementResolver ?? ElementResolver; var parseParam = new ParseParam(GUID, expression + ";", resolver); EngineController.CompilationServices.PreCompileCodeBlock(ref parseParam); if (parseParam.ParsedNodes.Any()) { var parsedComments = parseParam.ParsedComments; if (parsedComments.Any()) { comment = String.Join("\n", parsedComments.Select(c => (c as CommentNode).Value)); } if (parseParam.ParsedNodes.Count() > 1) { this.Warning(Properties.Resources.WarningInvalidOutput); } var node = parseParam.ParsedNodes.First() as BinaryExpressionNode; if (node != null) { var leftIdent = node.LeftNode as IdentifierNode; var rightIdent = node.RightNode as IdentifierNode; // "x" will be compiled to "temp_guid = x;" if (leftIdent != null && leftIdent.Value.StartsWith(Constants.kTempVarForNonAssignment)) { outputIdentifier = rightIdent; } else { outputIdentifier = leftIdent; } return(outputIdentifier != null); } } return(false); }
private bool TryParseInputSymbol(string inputSymbol, out IdentifierNode identifier, out AssociativeNode defaultValue) { identifier = null; defaultValue = null; var parseString = InputSymbol; parseString += ";"; // During loading of symbol node from file, the elementResolver from the workspace is unavailable // in which case, a local copy of the ER obtained from the symbol node is used var resolver = workspaceElementResolver ?? ElementResolver; var parseParam = new ParseParam(this.GUID, parseString, resolver); if (EngineController.CompilationServices.PreCompileCodeBlock(ref parseParam) && parseParam.ParsedNodes != null && parseParam.ParsedNodes.Any()) { var node = parseParam.ParsedNodes.First() as BinaryExpressionNode; Validity.Assert(node != null); if (node != null) { identifier = node.LeftNode as IdentifierNode; if (inputSymbol.Contains('=')) { defaultValue = node.RightNode; } return(identifier != null); } } return(false); }
static void OnlyCreatData() { if (!Directory.Exists(Application.dataPath + "/" + m_CsConfigFilePath)) { Directory.CreateDirectory(Application.dataPath + "/" + m_CsConfigFilePath); } var param = new ParseParam() { ExcelDir = Application.dataPath + "/" + m_ExcelPath, Serializations = new SerializationParam[] { new SerializationParam() { Serializer = mDic_form_seria[m_DataForm], OutDir = Application.dataPath + "/" + m_DataFilePath, }, }, }; Parser parser = new Parser(); parser.ParseAll(param); AssetDatabase.Refresh(); }
private void ProcessCode(ref string errorMessage, ref string warningMessage) { code = CodeBlockUtils.FormatUserText(code); codeStatements.Clear(); if (string.IsNullOrEmpty(Code)) { previewVariable = null; } try { ParseParam parseParam = new ParseParam(this.GUID, code); if (Workspace.DynamoModel.EngineController.TryParseCode(ref parseParam)) { if (parseParam.ParsedNodes != null) { // Create an instance of statement for each code statement written by the user foreach (var parsedNode in parseParam.ParsedNodes) { // Create a statement variable from the generated nodes codeStatements.Add(Statement.CreateInstance(parsedNode)); } SetPreviewVariable(parseParam.ParsedNodes); } } if (parseParam.Errors != null && parseParam.Errors.Any()) { errorMessage = string.Join("\n", parseParam.Errors.Select(m => m.Message)); ProcessError(); CreateInputOutputPorts(); return; } if (parseParam.Warnings != null) { // Unbound identifiers in CBN will have input slots. // // To check function redefinition, we need to check other // CBN to find out if it has been defined yet. Now just // skip this warning. var warnings = parseParam.Warnings.Where((w) => { return(w.ID != WarningID.kIdUnboundIdentifier && w.ID != WarningID.kFunctionAlreadyDefined); }); if (warnings.Any()) { warningMessage = string.Join("\n", warnings.Select(m => m.Message)); } } if (parseParam.UnboundIdentifiers != null) { inputIdentifiers = new List <string>(parseParam.UnboundIdentifiers); } else { inputIdentifiers.Clear(); } } catch (Exception e) { errorMessage = e.Message; previewVariable = null; ProcessError(); return; } // Set the input and output ports based on the statements CreateInputOutputPorts(); }
private static bool CompileCodeBlockAST(ParseParam parseParams) { Dictionary<int, List<VariableLine>> unboundIdentifiers = new Dictionary<int, List<VariableLine>>(); IEnumerable<ProtoCore.BuildData.WarningEntry> warnings = null; ProtoCore.BuildStatus buildStatus = null; try { BuildCore(true); int blockId = ProtoCore.DSASM.Constants.kInvalidIndex; CodeBlockNode codeblock = new ProtoCore.AST.AssociativeAST.CodeBlockNode(); List<AssociativeNode> nodes = new List<AssociativeNode>(); foreach (var i in parseParams.ParsedNodes) { AssociativeNode assocNode = i as AssociativeNode; if (assocNode != null) nodes.Add(NodeUtils.Clone(assocNode)); } codeblock.Body.AddRange(nodes); buildStatus = PreCompile(string.Empty, core, out blockId, codeblock); parseParams.AppendErrors(buildStatus.Errors); parseParams.AppendWarnings(buildStatus.Warnings); if (buildStatus.ErrorCount > 0) { return false; } warnings = buildStatus.Warnings; // Get the unboundIdentifiers from the warnings GetInputLines(parseParams.ParsedNodes, warnings, unboundIdentifiers); foreach (KeyValuePair<int, List<VariableLine>> kvp in unboundIdentifiers) { foreach (VariableLine vl in kvp.Value) parseParams.AppendUnboundIdentifier(vl.variable); } return true; } catch (Exception) { buildStatus = null; return false; } }
/// <summary> /// Pre-compiles DS code in code block node, /// checks for syntax, converts non-assignments to assignments, /// stores list of AST nodes, errors and warnings /// Evaluates and stores list of unbound identifiers /// </summary> /// <param name="parseParams"></param> /// <returns></returns> public static bool PreCompileCodeBlock(ParseParam parseParams) { string postfixGuid = parseParams.PostfixGuid.ToString().Replace("-", "_"); // Parse code to generate AST and add temporaries to non-assignment nodes IEnumerable<ProtoCore.AST.Node> astNodes = ParseUserCode(parseParams.OriginalCode, postfixGuid); // Catch the syntax errors and errors for unsupported // language constructs thrown by compile expression if (core.BuildStatus.ErrorCount > 0) { parseParams.AppendErrors(core.BuildStatus.Errors); parseParams.AppendWarnings(core.BuildStatus.Warnings); return false; } parseParams.AppendParsedNodes(astNodes); // Compile the code to get the resultant unboundidentifiers // and any errors or warnings that were caught by the compiler and cache them in parseParams return CompileCodeBlockAST(parseParams); }
public static bool Parse(ParseParam parseParams) { // TODO: Use the compile expression to format the code by adding // the required %t temp vars needed for non assignment statements var compiledExpressions = new List<String>(); CompileExpression(parseParams.OriginalCode, out compiledExpressions); var postfixGuid = parseParams.PostfixGuid.ToString().Replace("-", "_"); int index = 0; StringBuilder codeToParse = new StringBuilder(); foreach (var expression in compiledExpressions) { var updatedExpression = expression; if (expression.IndexOf("%t") != -1) { string name = string.Format("temp_{0}_{1}", index++, postfixGuid); parseParams.AppendTemporaryVariable(name); updatedExpression = updatedExpression.Replace("%t", name); } codeToParse.Append(updatedExpression); } parseParams.ProcessedCode = codeToParse.ToString(); // Catch the errors thrown by compile expression, // namely function modiferstack and class decl found if (core.BuildStatus.ErrorCount > 0) { parseParams.AppendErrors(core.BuildStatus.Errors); parseParams.AppendWarnings(core.BuildStatus.Warnings); return false; } // Parse and compile the code to get the result AST nodes as well // as any errors or warnings that were caught by the compiler ProtoCore.BuildStatus buildStatus; var unboundIdentifiers = new Dictionary<int, List<VariableLine>>(); List<ProtoCore.AST.Node> nodeList = new List<ProtoCore.AST.Node>(); ParseCodeBlockNodeStatements(parseParams.ProcessedCode, out unboundIdentifiers, out nodeList, out buildStatus); parseParams.AppendErrors(buildStatus.Errors); parseParams.AppendWarnings(buildStatus.Warnings); // Get the unboundIdentifiers from the warnings foreach (KeyValuePair<int, List<VariableLine>> kvp in unboundIdentifiers) { foreach (VariableLine vl in kvp.Value) parseParams.AppendUnboundIdentifier(vl.variable); } if (nodeList != null) { // TODO: Why don't we use the "nodeList" as it is? // Can we not avoid another "Parse" method call here? // ProtoCore.AST.AssociativeAST.CodeBlockNode cNode = null; var codeBlockNode = Parse(parseParams.ProcessedCode, out cNode); parseParams.AppendParsedNodes(ParserUtils.GetAstNodes(codeBlockNode)); } return true; }
private bool TryParseInputExpression(string inputSymbol, out IdentifierNode identifier, out AssociativeNode defaultValue, out string comment) { identifier = null; defaultValue = null; comment = null; var parseString = InputSymbol; parseString += ";"; // During loading of symbol node from file, the elementResolver from the workspace is unavailable // in which case, a local copy of the ER obtained from the symbol node is used var resolver = workspaceElementResolver ?? ElementResolver; var parseParam = new ParseParam(this.GUID, parseString, resolver); if (EngineController.CompilationServices.PreCompileCodeBlock(parseParam) && parseParam.ParsedNodes.Any()) { var parsedComments = parseParam.ParsedComments; if (parsedComments.Any()) { comment = String.Join("\n", parsedComments.Select(c => (c as CommentNode).Value)); } var node = parseParam.ParsedNodes.First() as BinaryExpressionNode; if (node != null) { var leftIdent = node.LeftNode as IdentifierNode; var rightIdent = node.RightNode as IdentifierNode; // "x" will be compiled to "temp_guid = x"; if (leftIdent != null && leftIdent.Value.StartsWith(Constants.kTempVarForNonAssignment)) { identifier = rightIdent; } // "x:int" will be compiled to "x:int = tTypedIdent0"; else if (rightIdent != null && rightIdent.Value.StartsWith(Constants.kTempVarForTypedIdentifier)) { identifier = leftIdent; } else { identifier = leftIdent; } if (inputSymbol.Contains('=')) { defaultValue = node.RightNode; } if (parseParam.Errors.Any()) { this.Error(parseParam.Errors.First().Message); } else if (parseParam.Warnings.Any()) { var warnings = parseParam.Warnings.Where(w => w.ID != WarningID.IdUnboundIdentifier); if (warnings.Any()) { this.Warning(parseParam.Warnings.First().Message); } } return(identifier != null); } } return(false); }
/// <summary> /// Pre-compiles Design script code in code block node. /// </summary> /// <param name="parseParams">Container for compilation related parameters</param> /// <returns>true if code compilation succeeds, false otherwise</returns> internal bool PreCompileCodeBlock(ParseParam parseParams) { return(CompilerUtils.PreCompileCodeBlock(compilationCore, parseParams, priorNames)); }
private void ProcessCode(ref string errorMessage, ref string warningMessage, ElementResolver workspaceElementResolver = null) { code = CodeBlockUtils.FormatUserText(code); codeStatements.Clear(); if (string.IsNullOrEmpty(Code)) { previewVariable = null; } try { // During loading of CBN from file, the elementResolver from the workspace is unavailable // in which case, a local copy of the ER obtained from the CBN is used var resolver = workspaceElementResolver ?? this.ElementResolver; var parseParam = new ParseParam(GUID, code, resolver); if (CompilerUtils.PreCompileCodeBlock(libraryServices.LibraryManagementCore, ref parseParam)) { if (parseParam.ParsedNodes != null) { // Create an instance of statement for each code statement written by the user foreach (var parsedNode in parseParam.ParsedNodes) { // Create a statement variable from the generated nodes codeStatements.Add(Statement.CreateInstance(parsedNode)); } SetPreviewVariable(parseParam.ParsedNodes); } } if (parseParam.Errors.Any()) { errorMessage = string.Join("\n", parseParam.Errors.Select(m => m.Message)); ProcessError(); CreateInputOutputPorts(); return; } if (parseParam.Warnings != null) { // Unbound identifiers in CBN will have input slots. // // To check function redefinition, we need to check other // CBN to find out if it has been defined yet. Now just // skip this warning. var warnings = parseParam.Warnings.Where( w => w.ID != WarningID.kIdUnboundIdentifier && w.ID != WarningID.kFunctionAlreadyDefined); if (warnings.Any()) { warningMessage = string.Join("\n", warnings.Select(m => m.Message)); } } if (parseParam.UnboundIdentifiers != null) { inputIdentifiers = new List <string>(); inputPortNames = new List <string>(); foreach (var kvp in parseParam.UnboundIdentifiers) { inputIdentifiers.Add(kvp.Value); inputPortNames.Add(kvp.Key); } } else { inputIdentifiers.Clear(); inputPortNames.Clear(); } } catch (Exception e) { errorMessage = e.Message; previewVariable = null; ProcessError(); return; } // Set the input and output ports based on the statements CreateInputOutputPorts(); }
/// <summary> /// Pre-compiles Design script code in code block node. /// </summary> /// <param name="parseParams">Container for compilation related parameters</param> /// <returns>true if code compilation succeeds, false otherwise</returns> public bool PreCompileCodeBlock(ref ParseParam parseParams) { return(CompilerUtils.PreCompileCodeBlock(compilationCore, ref parseParams, priorNames)); }
public bool TryParseCode(ref ParseParam parseParam) { return(CompilerUtils.PreCompileCodeBlock(libraryCore, ref parseParam)); }