/// <summary> /// Génère une instruction d'affectation. /// </summary> /// <param name="instruction"></param> /// <returns></returns> string GenerateAffectationInstruction(AffectationInstruction instruction) { return(GenerateBinaryExpressionGroup(instruction.Expression, false) + ";"); }
/// <summary> /// Parse une intruction basique : appel de méthode ou affectation. /// La liste doit comprendre un seul jeton et pas de ; /// </summary> /// <returns></returns> static Instruction ParseInstruction(TokenList tokens, GlobalContext mainContext) { // Traitement spécial si return. if ((tokens.First().Type == TokenType.Statement)) { if (tokens.Count == 2) { InfoToken firstToken = (InfoToken)tokens[0]; switch (firstToken.Content) { case "return": ReturnInstruction returnInst = new ReturnInstruction(); returnInst.Expression = ParseExpression(tokens[1], mainContext); return(returnInst); case "patchkey": PatchkeyInstruction patchkeyInst = new PatchkeyInstruction(); patchkeyInst.Key = ((InfoToken)((OperandToken)tokens[1]).Tokens.First()).Content; return(patchkeyInst); default: throw new Exception("Unexpected instruction"); } } else if (tokens.Count == 1) { return(new ReturnInstruction()); } else { throw new Exception("Invalid 'return' expression"); } } if (tokens.Count != 1) { // TODO : traiter les using, etc... throw new Exception("Unexpected token list"); } Token token = tokens.First(); // On commence les deux types d'instructions habituels. if (token.Type == TokenType.ExpressionGroup) { // OperandGroup + ";" : c'est une affectation, s'il n'y a pas de signe 'égal' dedans, // bah c'est rien du tout. ExpressionGroupToken tok = (ExpressionGroupToken)token; AffectationInstruction ins = new AffectationInstruction(); List <string> validTokens = new List <string>() { "=", "+=", "-=", "/=", "*=" }; // Si on a pas de "=", on a une expression. if (!validTokens.Contains(((InfoToken)tok.Operator).Content)) { throw new Exception("An expression can't be used as instruction"); } ins.LeftMember = ParseSubExpression(((OperandToken)tok.Operand1).Tokens, mainContext); switch (((InfoToken)tok.Operator).Content) { case "=": ins.RightMember = ParseExpression(tok.Operand2, mainContext); break; case "+=": case "-=": case "/=": case "*=": string opString = ((InfoToken)tok.Operator).Content.Remove(1); Operator op = Operators.Mapping[opString]; ins.RightMember = new ExpressionGroup((IGettable)ins.LeftMember, op, ParseExpression(tok.Operand2, mainContext)); break; default: throw new Exception(); } //ParseOperand((OperandToken)tok.Operand2); return(ins); } else if (token.Type == TokenType.OperandTokens) { TokenList internalTokens = ((TokenContainer)token).Tokens; Token first = internalTokens.First(); // Instructions pré-faites. if (first.Type == TokenType.Noun) { InfoToken itoken = (InfoToken)first; switch (itoken.Content) { case "using": if (internalTokens.Count != 2 || internalTokens[1].Type != TokenType.String) { throw new Exception("Invalid using instruction"); } InfoToken itoken2 = (InfoToken)internalTokens[1]; mainContext.LoadedNamespaces.Add(itoken2.Content); return(new UseNamespaceInstruction(itoken2.Content)); case "include": if (internalTokens.Count != 2 || internalTokens[1].Type != TokenType.String) { throw new Exception("Invalid using instruction"); } InfoToken itoken3 = (InfoToken)internalTokens[1]; mainContext.LoadedAssemblies.Add(itoken3.Content, Assembly.LoadWithPartialName(itoken3.Content)); return(new LoadAssemblyInstruction(itoken3.Content)); } } // C'est un appel de méthode. return(new MethodCallInstruction(ParseSubExpression(internalTokens, mainContext))); } throw new Exception("Uncorrect instruction"); }