static string ComputeTypeFromStatements(CleanupAstNodeStates states, ref bool needsQuotes) { var typeName = "int"; if (states.Count != 1) { var definedConstantType = states[1].Token; switch (definedConstantType) { case TokenKind.Int: typeName = "int"; break; case TokenKind.Float: typeName = "double"; break; case TokenKind.QuotedString: typeName = "string"; break; case TokenKind.Identifier: typeName = "string"; needsQuotes = true; break; default: throw new InvalidDataException("Type not supported"); } } return typeName; }
static bool CheckIsAssignment(CleanupAstNodeStates cleanStates, int advancePosition) { var colonPos = cleanStates.MappedNodes.GeNextTokenKind(TokenKind.SemiColon, advancePosition); var assign = cleanStates.MappedNodes.GeNextTokenKind(TokenKind.Assign, advancePosition); return (assign > 0) && (assign < colonPos); }
static void TryHandleParameter(TypeData[] fnParams, int i, CleanupAstNodeStates blockStates, int startRange, int endRange, Dictionary<string, TypeData> declarations) { var isFunction = blockStates[startRange + 1].Token == TokenKind.OpenParen; var typeArgument = fnParams[i]; var tmp = typeArgument.Count != 1; if (tmp) return; var argumentType = typeArgument[0].Content; if (argumentType == TypeNames.Unknown) return; var token = blockStates[startRange]; var typeOfParam = declarations.GetTypeOfName(token.Content); if (typeOfParam == null || typeOfParam.Count != 1) return; var paramType = typeOfParam[0].Content; if (paramType == argumentType) return; if (!isFunction && endRange != startRange) return; var formatTypes = string.Format("{0}={1}", paramType, argumentType); FixArgumentType(blockStates, startRange, isFunction, formatTypes); }
protected void FixDeclarationProblem(CleanupAstNodeStates states) { if(states.Count!=5)return; var type = states[0].Content; FixAssignmentWithConstant(states, 3, type); }
public override void OnVisitMatch(ParseNode node) { var cleanStates = new CleanupAstNodeStates(node.Parent.Children); var advance = cleanStates.MappedNodes.IndexOf(node); if (advance == 0) return; cleanStates.ShiftBlock(advance); }
static void ClearRange(CleanupAstNodeStates states, int declarationStart, int declarationEnd) { if (declarationEnd == declarationStart + 1) return; var tokenData = states.MappedNodes[declarationStart + 1].GetTokenData(); if (tokenData.Token == TokenKind.Operator && tokenData.Content == "&") { FixAmpersandAsRef(states, declarationStart); } }
static void FixAmpersandAsRef(CleanupAstNodeStates states, int declarationStart) { var refToken = TokenKind.Ref.BuildTokenFromId(); var spaceToken = TokenKind.Space.BuildTokenFromId(" "); states.RemoveAt(declarationStart + 1); states.Insert(declarationStart, spaceToken); states.Insert(declarationStart, refToken); states.Remap(); }
void HandleMultipleParameters(ParseNode astNode, CleanupAstNodeStates states) { var typeNode = states[0]; var commaPositions = ComputeCommaPositions(states); var functionBlockNode = typeNode.GetParentFunctionBlockNode() ?? typeNode.GetRootNode(); ExtractArrayParameters(states, commaPositions, typeNode, functionBlockNode); astNode.RemoveFromParent(); _found = true; states.Remap(); }
void ExtractArrayParameters(CleanupAstNodeStates states, List<int> commaPositions, ParseNode typeNode, ParseNode functionBlockNode) { var startPos = 1; foreach (var commaPosition in commaPositions) { ExtractArrayParameter(typeNode, states, startPos, commaPosition - 1, functionBlockNode); startPos = commaPosition + 1; } }
public static void AddExplicitCastAtPosition(CleanupAstNodeStates states, string typeName, int positionCast) { var explicitCastList = new List<ParseNode> { TokenKind.OpenParen.BuildTokenFromId(), TokenKind.TypeName.BuildTokenFromId(typeName), TokenKind.CloseParen.BuildTokenFromId() }; states.InsertRange(positionCast, explicitCastList); }
void FixSimpleAssignmentInFunctionProblem(ParseNode node, CleanupAstNodeStates states) { if (states.Count != 4) return; var functionNode = node.GetParentFunctionBlockNode(); var declarations = functionNode.GetDeclarations(); var varName = states[0].Content; var typeData = declarations.GetTypeOfName(varName); if (typeData.Count != 1) return; var type = typeData[0].Content; FixAssignmentWithConstant(states, 2, type); }
static void FoldBlocks(CleanupAstNodeStates cleanStates) { for (var pos = 0; pos < cleanStates.Count; pos++) { var currentNode = cleanStates[pos]; var tokenKind = currentNode.GetTokenKind(); switch (tokenKind) { case TokenKind.OpenCurly: cleanStates.ShiftBlock(pos); break; } } }
public static void ParseData(ParseNode node) { var tokenData = node.Children.First(); var defineText = tokenData.Content.Remove(0, "#define ".Length); var lexer = new Mq4Lexer(); var defineTokens = lexer.BuildTextTokens(defineText); var nodes = defineTokens.Select(token => token.BuildTerminalNode()).ToList(); var states = new CleanupAstNodeStates(nodes); var definedConstantType = states.MappedNodes[1].Token; string typeName; switch (definedConstantType) { case TokenKind.Int: case TokenKind.Float: typeName = definedConstantType.NameOfType(); break; case TokenKind.QuotedString: typeName = "string"; break; case TokenKind.Operator: typeName = states.MappedNodes[2].Token.NameOfType(); break; case TokenKind.Identifier: typeName = ComputeConstTypeFromPreviousConstants(node, states.MappedNodes[1].Content); break; default: throw new InvalidDataException("Type not supported"); } var insertTokenType = new ParseNode(TokenKind.TypeName, typeName); var buildTerminalToken = insertTokenType.BuildTerminalNode(); var variableToken = states[0]; var valueToken = states[1]; var valueToken2 = definedConstantType == TokenKind.Operator ? states.MappedNodes[2] : null; node.Children.Clear(); node.Add(buildTerminalToken); node.AddTerminalToken(new TokenData(0, 0, TokenKind.Space, " ")); node.Add(variableToken); node.AddTerminalToken(new TokenData(0, 0, TokenKind.Assign, "=")); node.Add(valueToken); if (definedConstantType == TokenKind.Operator) { node.Add(valueToken2); } var colon = new ParseNode(TokenKind.SemiColon, ";"); node.Rule = RuleKind.DeclareConstant; node.Children.Add(colon); }
void HandleCastOnParameters(ParseNode identifier, TypeParameterTable functionData, int index, CleanupAstNodeStates states) { var rightType = _declarations.GetTypeOfName(identifier.GetTokenContent()); var leftTypeName = functionData[index].TokenList[0].Content; if (rightType == null || rightType.TokenList.Count == 0) return; var rightTypeName = rightType[0].Content; if (rightTypeName == leftTypeName) return; if (rightTypeName == TypeNames.Unknown) return; if (leftTypeName == TypeNames.Unknown) return; var conversionTypes = string.Format("{0}={1}", leftTypeName, rightTypeName); switch (conversionTypes) { case "int=double": SemanticAnalysisUtils.AddExplicitCastAtPosition(states, leftTypeName, states.IndexOf(identifier)); break; //nothing to do case "color=int": case "datetime=int": case "double=int": case "int=datetime": case "double=color": case "int=color": case "color=double": case "double=datetime": return; case "int=bool": FixAssignmentInFunction.AddCastCall(states, TypeNames.ToInt, states.IndexOf(identifier) + 1); return; case "double=bool": FixAssignmentInFunction.AddCastCall(states, TypeNames.ToDouble, states.IndexOf(identifier) + 1); return; case "bool=int": case "bool=double": FixAssignmentInFunction.AddCastCall(states, TypeNames.ToBool, states.IndexOf(identifier) + 1); return; case "string=bool": case "string=int": case "string=double": FixAssignmentInFunction.AddCastCall(states, TypeNames.ConvStr, states.IndexOf(identifier) + 1); return; default: return; } }
void FixArrayInParam(int pos, int endRange, CleanupAstNodeStates states) { var openParen = states.GeNextTokenKind(TokenKind.OpenSquared, pos); if (openParen == 0 || openParen > endRange) return; var closeParen = states.GeNextTokenKind(TokenKind.CloseSquared, openParen); var openNode = states[openParen]; var closeNode = states[closeParen]; states.RemoveAt(closeParen); states.RemoveAt(openParen); states.Insert(pos + 1, closeNode); states.Insert(pos + 1, openNode); states.Remap(); }
void FixAssignmentWithConstant(CleanupAstNodeStates states, int constantPosition, string type) { var value = states[constantPosition].Content; switch (type) { case TypeNames.Bool: if (states[constantPosition].Token == TokenKind.Int) { FixIntAsBool(states, value); return; } throw new InvalidDataException("case with bool not handled"); case TypeNames.Int: if (states[constantPosition].Token == TokenKind.Float) { FixFloatAsInt(states, value, constantPosition); return; } if (states[constantPosition].Token == TokenKind.Char) { FixCharAsInt(states, value, constantPosition); return; } if (states[constantPosition].Token != TokenKind.Int) throw new InvalidDataException("case with int32 not handled"); break; case TypeNames.Double: break; case TypeNames.String: if (states[constantPosition].Token != TokenKind.QuotedString) throw new InvalidDataException("case with string not handled"); break; case TypeNames.DateTime: if (states[constantPosition].Content != "0") throw new InvalidDataException("case with datetime not handled"); break; case TypeNames.Color: if (states[constantPosition].Content != "0") throw new InvalidDataException("case with color not handled"); break; default: throw new InvalidDataException("case not handled"); } }
void InterpretGlobal(CleanupAstNodeStates cleanStates) { for (var advancePosition = 0; advancePosition < cleanStates.Count; advancePosition++) { var currentNode = cleanStates[advancePosition]; var tokenKind = currentNode.GetTokenKind(); switch (tokenKind) { case TokenKind.TypeName: var isVariableDeclaration = CheckIfTypeDefinesVariable(advancePosition, cleanStates.MappedNodes); if (isVariableDeclaration) cleanStates.ShiftVariableDeclaration(advancePosition); else { cleanStates.ShiftFunctionDeclaration(advancePosition); var blockStates = cleanStates[advancePosition].States[3].States; InterpretBlock(blockStates); } break; case TokenKind.SharpDefine: cleanStates.ShiftSharpDefineDeclaration(advancePosition); break; case TokenKind.SharpImport: cleanStates.ShiftSharpImports(advancePosition); break; case TokenKind.SharpProperty: break; case TokenKind.Static: ShiftStaticDefinition(cleanStates, advancePosition); break; case TokenKind.Extern: ShiftExternDefinition(cleanStates, advancePosition); break; case TokenKind.Input: cleanStates.ShiftInputs(advancePosition); break; default: throw new InvalidDataException("Input type not handled"); } } }
public static void ParseData(ParseNode node) { var tokenData = node.Children.First(); var defineText = tokenData.Content.Remove(0, "#property ".Length); var lexer = new Mq4Lexer(); var defineTokens = lexer.BuildTextTokens(defineText); var nodes = defineTokens.Select(token => token.BuildTerminalNode()).ToList(); var states = new CleanupAstNodeStates(nodes); var assemblyOfAttributes = typeof(indicator_color1Attribute).Assembly; var fullTypeName = string.Format("Mql2Fdk.Attributes.{0}Attribute", states[0].Content); var fullTypeNameReduced = string.Format("Mql2Fdk.Attributes.{0}", states[0].Content); var getTypeofAttribute = assemblyOfAttributes.GetType(fullTypeName) ?? assemblyOfAttributes.GetType(fullTypeNameReduced); bool needsQuotes = false; var typeName = getTypeofAttribute!=null ? ComputeTypenameFromReflection(getTypeofAttribute, states, ref needsQuotes) : ComputeTypeFromStatements(states, ref needsQuotes); var variableToken = states.MappedNodes[0]; var valueToken = states.Count != 1 ? states.MappedNodes[1] : new TokenData(0, 0, TokenKind.Int, "1").BuildTerminalNode(); if (needsQuotes) { var finalTokenData = valueToken.GetTokenData(); finalTokenData.Token = TokenKind.QuotedString; finalTokenData.Content = string.Format("\"{0}\"", finalTokenData.Content); } node.Children.Clear(); var insertTokenType = new TokenData(0, 0, TokenKind.TypeName, typeName); var buildTerminalToken = insertTokenType.BuildTerminalNode(); node.Add(buildTerminalToken); node.AddTerminalToken(new TokenData(0, 0, TokenKind.Space, " ")); node.Add(variableToken); node.AddTerminalToken(new TokenData(0, 0, TokenKind.Assign, "=")); node.Add(valueToken); var colon = new TokenData(0, 0, TokenKind.SemiColon, ";").BuildTerminalNode(); node.Children.Add(colon); }
static void FixArgumentType(CleanupAstNodeStates blockStates, int startRange, bool isFunction, string formatTypes) { switch (formatTypes) { case "int=double": AddExplicitCastToDouble(blockStates, startRange); break; case "double=string": case "int=string": AddExplicitCastIntToString(blockStates, startRange, isFunction); break; case "bool=double": AddExplicitCastBoolToInt(blockStates, startRange, isFunction, "ToDouble"); break; case "bool=int": AddExplicitCastBoolToInt(blockStates, startRange, isFunction, "ToInt"); break; } }
static bool IsMultiParameter(CleanupAstNodeStates states) { var isInParen = false; for (var index = 1; index < states.Count - 1; index++) { var node = states[index]; if (node.Token == TokenKind.OpenSquared) isInParen = true; if (node.Token == TokenKind.CloseSquared) isInParen = false; if (node.Token == TokenKind.Comma) { if (isInParen) continue; return true; } } return false; }
public static void SetRequiredParen(CleanupAstNodeStates states) { var openSquarePos = states.MappedNodes.GeNextTokenKind(TokenKind.OpenSquared); var closeSquarePos = states.MappedNodes.GeNextTokenKind(TokenKind.CloseSquared); var commaPos = states.MappedNodes.GeNextTokenKind(TokenKind.Comma); if (openSquarePos + 1 == closeSquarePos || openSquarePos + 1 == commaPos) { states.Insert(openSquarePos + 1, TokenKind.Int.BuildTokenFromId("0")); states.Remap(); } if (commaPos + 1 == closeSquarePos) { states.Insert(commaPos + 1, TokenKind.Int.BuildTokenFromId("0")); states.Remap(); } var tokenData = states[0].GetTokenData(); var typeToken = tokenData.Clone(); var assignPos = states.GeNextTokenKind(TokenKind.Assign); if (assignPos > 0) { var openSquaredPos = states.GeNextTokenKind(TokenKind.OpenSquared); if (openSquaredPos > assignPos) return; } var nodesToBeAdded = new List<ParseNode> { TokenKind.Assign.BuildTokenFromId(), TokenKind.Space.BuildTokenFromId(" "), TokenKind.New.BuildTokenFromId(), TokenKind.Space.BuildTokenFromId(" "), typeToken.BuildTerminalNode(), }; states.InsertRange(2, nodesToBeAdded); var countSquared = states.Count(node => node.GetTokenKind() == TokenKind.Comma) + 1; var toAdd = BuildSquaresAndCommas(countSquared); states.InsertRange(1, toAdd); }
void FixArrayInParam(int pos, int endRange, CleanupAstNodeStates states) { var openParen = 0; for (var index = pos; index < endRange; index++) { var searchNode = states[index]; if (searchNode.GetTokenKind() == TokenKind.Operator && searchNode.GetTokenData().Content == "&") openParen = index; } if (openParen == 0) return; states.RemoveAt(openParen); states.Insert(pos, TokenKind.Space.BuildTokenFromId(" ")); states.Insert(pos, TokenKind.Ref.BuildTokenFromId()); states.Remap(); }
static void HandleConversions(string conversionTypes, CleanupAstNodeStates states, string leftTypeName, int assign) { int tokenToInsert; if (ComputeInsertCastPosition(states, assign, out tokenToInsert)) return; switch (conversionTypes) { case "int=double": SemanticAnalysisUtils.AddExplicitCastAtPosition(states, leftTypeName, assign + 1); break; //nothing to do case "color=int": case "int=color": case "datetime=int": case "double=int": case "int=datetime": case "color=double": return; case "double=datetime": case "int=string": //hard to handle break; case "int=bool": AddCastCall(states, TypeNames.ToInt, tokenToInsert); break; case "bool=double": case "bool=int": AddCastCall(states, TypeNames.ToBool, tokenToInsert); break; case "string=int": case "string=double": case "string=bool": AddCastCall(states, TypeNames.ConvStr, tokenToInsert); break; default: throw new NotImplementedException(); } }
public override void OnVisitMatch(ParseNode node) { if (!node.Parent.NodeMatchesRule(RuleKind.FunctionDeclaration)) return; var cleanStates = new CleanupAstNodeStates(node.Children); var advancePosition = 1; while (advancePosition < cleanStates.Count - 1) { var currentNode = cleanStates.MappedNodes[advancePosition]; var tokenKind = currentNode.GetTokenKind(); switch (tokenKind) { case TokenKind.TypeName: cleanStates.ShiftVariableDeclaration(advancePosition); break; case TokenKind.Static: cleanStates.ShiftStaticVariableDeclaration(advancePosition); break; case TokenKind.Identifier: var isAssignment = CheckIsAssignment(cleanStates, advancePosition); if (isAssignment) { cleanStates.ShiftAssignment(advancePosition); } else { cleanStates.ShiftCall(advancePosition); } break; case TokenKind.CloseCurly: throw new InvalidDataException("Unmatched closed curly"); case TokenKind.None: break; default: throw new InvalidDataException("Input type not handled"); } advancePosition++; } }
static void TryHandleParameterNull(TypeData[] fnParams, int i, CleanupAstNodeStates blockStates, int startRange) { var token = blockStates[startRange]; var typeParam = fnParams[i]; var tmp = typeParam.Count != 1; if (tmp) return; var paramType = typeParam[0].Content; if (paramType == TypeNames.Unknown) return; switch (typeParam[0].Content) { case "double": token.Token = TokenKind.Float; token.Content = string.Format("0.0"); break; case "int": token.Token = TokenKind.Int; token.Content = string.Format("0"); break; } }
static void TryHandleParameter(TypeData[] fnParams, int i, CleanupAstNodeStates blockStates, int startRange) { var token = blockStates[startRange]; var typeParam = fnParams[i]; var tmp = typeParam.Count != 1; if (tmp) return; var paramType = typeParam[0].Content; if (paramType == TypeNames.Unknown) return; var formatType = string.Format("{0}={1}", paramType, token.Token); switch (formatType) { case "double=Int": var intValue = int.Parse(token.Content); token.Token = TokenKind.Float; token.Content = string.Format("{0}.0", intValue); break; case "int=Float": var floatValue = double.Parse(token.Content); token.Token = TokenKind.Int; token.Content = string.Format("{0}", (int)floatValue); break; case "string=Int": case "string=Float": var combinedText = string.Format("\"{0}\"", token.Content); token.Token = TokenKind.QuotedString; token.Content = combinedText; break; } }
public static void SetRequiredParen(CleanupAstNodeStates states) { for (var i = 2; i < states.Count; i++) { var closeToken = states[i]; if (closeToken.Token != TokenKind.CloseSquared) continue; var openToken = states[i]; if (openToken.Token != TokenKind.OpenSquared) continue; closeToken.Token = TokenKind.Comma; closeToken.Content = ","; } for (var i = states.Count - 1; i > 0; i--) { var openToken = states[i]; if (openToken.Token != TokenKind.OpenSquared) continue; var idToken = states[i - 1]; if (idToken.Token != TokenKind.Identifier) continue; var closeTokenId = states.GetNextMachingTokenKind(TokenKind.CloseSquared, TokenKind.OpenSquared, i); var toAdd = new List<ParseNode>(); for (var addRange = i; addRange <= closeTokenId; addRange++) { toAdd.Add(states[addRange].Clone()); } states.InsertRange(i - 1, toAdd); i += toAdd.Count; closeTokenId = states.GetNextMachingTokenKind(TokenKind.CloseSquared, TokenKind.OpenSquared, i); states.RemoveRange(i, closeTokenId); } }
void InterpretBlock(CleanupAstNodeStates cleanStates) { if (cleanStates[0].Token != TokenKind.OpenCurly) return; for (var advancePosition = 1; advancePosition < cleanStates.Count - 1; advancePosition++) { var currentNode = cleanStates.MappedNodes[advancePosition]; var tokenKind = currentNode.GetTokenKind(); switch (tokenKind) { case TokenKind.TypeName: cleanStates.ShiftVariableDeclaration(advancePosition); break; case TokenKind.Identifier: cleanStates.ShiftInstructionDeclaration(advancePosition); break; case TokenKind.SharpDefine: break; case TokenKind.SharpImport: cleanStates.ShiftSharpImports(advancePosition); break; case TokenKind.SharpProperty: case TokenKind.CloseCurly: break; case TokenKind.None: switch (currentNode.Rule) { case RuleKind.BlockCode: var blockStates = currentNode.States; InterpretBlock(blockStates); break; } break; case TokenKind.Break: cleanStates.ShiftBreak(advancePosition); break; case TokenKind.Continue: cleanStates.ShiftContinue(advancePosition); break; case TokenKind.If: case TokenKind.For: case TokenKind.While: InterpretIf(cleanStates, advancePosition); break; case TokenKind.Switch: InterpretIf(cleanStates, advancePosition); break; case TokenKind.Default: InterpretCase(cleanStates, advancePosition); break; case TokenKind.Case: InterpretCase(cleanStates, advancePosition); break; case TokenKind.Else: InterpretElseWhile(cleanStates, advancePosition); break; case TokenKind.Static: ShiftStaticDefinition(cleanStates, advancePosition); break; case TokenKind.Extern: ShiftExternDefinition(cleanStates, advancePosition); break; case TokenKind.Return: ShiftReturn(cleanStates, advancePosition); break; default: throw new InvalidDataException("Input type not handled"); } } }
public void Interpret() { var cleanStates = new CleanupAstNodeStates(_root); FoldBlocks(cleanStates); InterpretGlobal(cleanStates); }
static void ShiftReturn(CleanupAstNodeStates cleanStates, int advancePosition) { var rightColon = cleanStates.MappedNodes.GeNextTokenKind(TokenKind.SemiColon, advancePosition); cleanStates.ReduceRangeOfTokensAsParent(advancePosition, rightColon, RuleKind.Return); }