private Expression ParseIncrementOrCast(TokenStream tokens) { Token prefix = null; if (tokens.IsNext("++") || tokens.IsNext("--")) { prefix = tokens.Pop(); } Expression expression; int tokenIndex = tokens.SnapshotState(); if (prefix == null && tokens.PeekValue() == "(" && IsValidName(tokens.PeekAhead(1))) { Token parenthesis = tokens.Pop(); PType castType = PType.TryParse(tokens); if (castType != null && tokens.PopIfPresent(")")) { expression = this.ParseIncrementOrCast(tokens); return(new CastExpression(parenthesis, castType, expression)); } tokens.RevertState(tokenIndex); } expression = this.ParseEntity(tokens); if (prefix != null) { expression = new InlineIncrement(prefix, prefix, expression, true); } if (tokens.IsNext("++") || tokens.IsNext("--")) { expression = new InlineIncrement(expression.FirstToken, tokens.Pop(), expression, false); } return(expression); }
private static Expression ParseAtomWithSuffix(ParserContext context, TokenStream tokens, TopLevelEntity parent) { Expression root; if (tokens.IsNext("(")) { Token openParen = tokens.Pop(); switch (IdentifyParenthesisSituation(tokens)) { case ParenthesisSituation.CAST: CSharpType castType = CSharpType.Parse(tokens); tokens.PopExpected(")"); Expression castValue = ParseAtomWithSuffix(context, tokens, parent); return(new CastExpression(openParen, castType, castValue, parent)); case ParenthesisSituation.LAMBDA_ARG: List <Token> lambdaArgs = new List <Token>() { tokens.PopWord() }; while (tokens.PopIfPresent(",")) { lambdaArgs.Add(tokens.PopWord()); } tokens.PopExpected(")"); Token arrowToken = tokens.PopExpected("=>"); Executable[] lambdaBody; if (tokens.IsNext("{")) { lambdaBody = ExecutableParser.ParseCodeBlock(context, tokens, parent, true); } else { Expression expr = Parse(context, tokens, parent); lambdaBody = new Executable[] { new ReturnStatement(expr.FirstToken, expr, parent) }; } return(new Lambda(openParen, lambdaArgs, arrowToken, lambdaBody, parent)); case ParenthesisSituation.WRAPPED_EXPRESSION: root = Parse(context, tokens, parent); tokens.PopExpected(")"); break; default: throw new Exception(); // not valid } } else { root = ParseAtom(context, tokens, parent); } bool anythingInteresting = true; string next = tokens.PeekValue(); while (anythingInteresting) { switch (next) { case ".": Token dotToken = tokens.Pop(); Token fieldName = tokens.PopWord(); root = new DotField(root.FirstToken, root, dotToken, fieldName, parent); break; case "[": Token openBracket = tokens.Pop(); Expression index = Parse(context, tokens, parent); tokens.PopExpected("]"); root = new BracketIndex(root, openBracket, index, parent); break; case "<": if (root is DotField) { CSharpType[] functionInvocationTypeSpecification = MaybeParseOutOneOfThoseInlineTypeSpecificationsForFunctionInvocations(tokens); if (functionInvocationTypeSpecification != null) { ((DotField)root).InlineTypeSpecification = functionInvocationTypeSpecification; } else { anythingInteresting = false; } } else { anythingInteresting = false; } break; case "(": Token openParen = tokens.Pop(); List <Expression> args = new List <Expression>(); List <Token> outTokens = new List <Token>(); while (!tokens.PopIfPresent(")")) { if (args.Count > 0) { tokens.PopExpected(","); } if (tokens.IsNext("out")) { outTokens.Add(tokens.Pop()); } else { outTokens.Add(null); } args.Add(Parse(context, tokens, parent)); } root = new FunctionInvocation(root.FirstToken, root, openParen, args, outTokens, parent); break; case "{": // e.g. new List<int>() { 1, 2, 3 }. This only follows a constructor. FunctionInvocation fi = root as FunctionInvocation; ConstructorInvocationFragment cif = fi == null ? null : (ConstructorInvocationFragment)fi.Root; if (root is FunctionInvocation && ((FunctionInvocation)root).Root is ConstructorInvocationFragment) { tokens.Pop(); // { ConstructorSuffixData format = DetermineConstructorSuffixDataFormat(tokens); bool nextAllowed = true; List <Expression> values = new List <Expression>(); List <Expression> kvpKeys = new List <Expression>(); List <Token> propertyNames = new List <Token>(); while (!tokens.PopIfPresent("}")) { if (!nextAllowed) { tokens.PopExpected("}"); // intentionally throw } switch (format) { case ConstructorSuffixData.KVP_ENTRIES: tokens.PopExpected("{"); kvpKeys.Add(Parse(context, tokens, parent)); tokens.PopExpected(","); values.Add(Parse(context, tokens, parent)); tokens.PopExpected("}"); break; case ConstructorSuffixData.PROPERTIES: propertyNames.Add(tokens.PopWord()); tokens.PopExpected("="); values.Add(Parse(context, tokens, parent)); break; case ConstructorSuffixData.SEQUENTIAL_ITEMS: values.Add(Parse(context, tokens, parent)); break; } nextAllowed = tokens.PopIfPresent(","); } cif.InitialDataValues = values.ToArray(); int t = cif.InitialDataValues.Length; if (kvpKeys.Count == t) { cif.InitialDataKeys = kvpKeys.ToArray(); } if (propertyNames.Count == t) { cif.InitialDataPropertyNames = propertyNames.ToArray(); } } else { throw new ParserException(tokens.Peek(), "Unexpected '{'"); } break; default: anythingInteresting = false; break; } next = tokens.PeekValue(); } if (next == "++" || next == "--") { Token incrementToken = tokens.Pop(); root = new InlineIncrement(root.FirstToken, incrementToken, false, root, parent); } return(root); }
public void TranslateExpression(StringBuilder sb, Expression expression) { string typeName = expression.GetType().Name; switch (typeName) { case "CastExpression": this.TranslateCast(sb, ((CastExpression)expression).Type, ((CastExpression)expression).Expression); break; case "FunctionReference": this.TranslateFunctionReference(sb, (FunctionReference)expression); break; case "NativeFunctionInvocation": this.TranslateNativeFunctionInvocation(sb, (NativeFunctionInvocation)expression); break; case "OpChain": this.TranslateOpChain(sb, (OpChain)expression); break; case "LibraryNativeFunctionInvocation": this.TranslateLibraryNativeFunctionInvocation(sb, (LibraryNativeFunctionInvocation)expression); break; case "InlineIncrement": InlineIncrement ii = (InlineIncrement)expression; this.TranslateInlineIncrement(sb, ii.Expression, ii.IsPrefix, ii.IncrementToken.Value == "++"); break; case "FunctionInvocation": FunctionInvocation funcInvocation = (FunctionInvocation)expression; bool specifyInterpreterScope = false; if (funcInvocation.FirstToken.FileName.StartsWith("LIB:") && funcInvocation.Root is FunctionReference) { FunctionDefinition funcDef = ((FunctionReference)funcInvocation.Root).Function; if (!funcDef.NameToken.FileName.StartsWith("LIB:")) { specifyInterpreterScope = true; } } if (specifyInterpreterScope) { this.TranslateFunctionInvocationInterpreterScoped(sb, (FunctionReference)funcInvocation.Root, funcInvocation.Args); } else { this.TranslateFunctionInvocationLocallyScoped(sb, (FunctionReference)funcInvocation.Root, funcInvocation.Args); } break; case "Variable": Variable v = (Variable)expression; string name = v.Name; char firstChar = name[0]; if (firstChar >= 'A' && firstChar <= 'Z' && name.Contains('_') && name.ToUpper() == name) { this.TranslateGlobalVariable(sb, v); } else { this.TranslateVariable(sb, v); } break; case "ConstructorInvocation": ConstructorInvocation constructor = (ConstructorInvocation)expression; string rootType = constructor.Type.RootValue; switch (rootType) { case "Array": if (constructor.Type.Generics.Length != 1) { throw new Pastel.ParserException(constructor.Type.FirstToken, "Array constructor requires exactly 1 generic type."); } this.TranslateArrayNew(sb, constructor.Type.Generics[0], constructor.Args[0]); break; case "List": if (constructor.Type.Generics.Length != 1) { throw new Pastel.ParserException(constructor.Type.FirstToken, "List constructor requires exactly 1 generic type."); } this.TranslateListNew(sb, constructor.Type.Generics[0]); break; case "Dictionary": if (constructor.Type.Generics.Length != 2) { throw new Pastel.ParserException(constructor.Type.FirstToken, "Dictionary constructor requires exactly 2 generic types."); } PType dictionaryKeyType = constructor.Type.Generics[0]; PType dictionaryValueType = constructor.Type.Generics[1]; this.TranslateDictionaryNew(sb, dictionaryKeyType, dictionaryValueType); break; default: // TODO: throw an exception (in the parser) if generics exist. this.TranslateConstructorInvocation(sb, constructor); break; } break; case "DotField": DotField df = (DotField)expression; StructDefinition structDef = df.StructType; if (structDef == null) { throw new InvalidOperationException(); // should have been thrown by the compiler } string fieldName = df.FieldName.Value; int fieldIndex = structDef.ArgIndexByName[fieldName]; this.TranslateStructFieldDereference(sb, df.Root, structDef, fieldName, fieldIndex); break; case "InlineConstant": InlineConstant ic = (InlineConstant)expression; switch (ic.ResolvedType.RootValue) { case "bool": this.TranslateBooleanConstant(sb, (bool)ic.Value); break; case "char": this.TranslateCharConstant(sb, ((string)ic.Value)[0]); break; case "double": this.TranslateFloatConstant(sb, (double)ic.Value); break; case "int": this.TranslateIntegerConstant(sb, (int)ic.Value); break; case "null": this.TranslateNullConstant(sb); break; case "string": this.TranslateStringConstant(sb, (string)ic.Value); break; default: throw new NotImplementedException(); } break; case "UnaryOp": UnaryOp uo = (UnaryOp)expression; if (uo.OpToken.Value == "-") { this.TranslateNegative(sb, uo); } else { this.TranslateBooleanNot(sb, uo); } break; case "ForcedParenthesis": sb.Append('('); this.TranslateExpression(sb, ((ForcedParenthesis)expression).Expression); sb.Append(')'); break; default: throw new NotImplementedException(typeName); } }
public void TranslateExpression(TranspilerContext sb, Expression expression) { string typeName = expression.GetType().Name; switch (typeName) { case "CastExpression": this.TranslateCast(sb, ((CastExpression)expression).Type, ((CastExpression)expression).Expression); break; case "FunctionReference": this.TranslateFunctionReference(sb, (FunctionReference)expression); break; case "FunctionPointerInvocation": this.TranslateFunctionPointerInvocation(sb, (FunctionPointerInvocation)expression); break; case "CoreFunctionInvocation": this.TranslateCoreFunctionInvocation(sb, (CoreFunctionInvocation)expression); break; case "OpChain": OpChain oc = (OpChain)expression; if (oc.IsStringConcatenation) { this.TranslateStringConcatenation(sb, oc.Expressions); } else { this.TranslateOpChain(sb, oc); } break; case "ExtensibleFunctionInvocation": this.TranslateExtensibleFunctionInvocation( sb, (ExtensibleFunctionInvocation)expression); break; case "InlineIncrement": InlineIncrement ii = (InlineIncrement)expression; this.TranslateInlineIncrement(sb, ii.Expression, ii.IsPrefix, ii.IncrementToken.Value == "++"); break; case "FunctionInvocation": FunctionInvocation funcInvocation = (FunctionInvocation)expression; string prefix = null; FunctionDefinition funcDef = ((FunctionReference)funcInvocation.Root).Function; PastelContext targetContext = funcDef.Context; PastelContext callerContext = funcInvocation.Owner.Context; if (targetContext != callerContext) { prefix = callerContext.GetDependencyExportPrefix(targetContext); } if (prefix != null) { this.TranslateFunctionInvocationWithPrefix(sb, prefix, (FunctionReference)funcInvocation.Root, funcInvocation.Args); } else { this.TranslateFunctionInvocation(sb, (FunctionReference)funcInvocation.Root, funcInvocation.Args); } break; case "Variable": Variable v = (Variable)expression; this.TranslateVariable(sb, v); break; case "ConstructorInvocation": ConstructorInvocation constructor = (ConstructorInvocation)expression; string rootType = constructor.Type.RootValue; switch (rootType) { case "Array": if (constructor.Type.Generics.Length != 1) { throw new Pastel.ParserException(constructor.Type.FirstToken, "Array constructor requires exactly 1 generic type."); } this.TranslateArrayNew(sb, constructor.Type.Generics[0], constructor.Args[0]); break; case "List": if (constructor.Type.Generics.Length != 1) { throw new Pastel.ParserException(constructor.Type.FirstToken, "List constructor requires exactly 1 generic type."); } this.TranslateListNew(sb, constructor.Type.Generics[0]); break; case "Dictionary": if (constructor.Type.Generics.Length != 2) { throw new Pastel.ParserException(constructor.Type.FirstToken, "Dictionary constructor requires exactly 2 generic types."); } PType dictionaryKeyType = constructor.Type.Generics[0]; PType dictionaryValueType = constructor.Type.Generics[1]; this.TranslateDictionaryNew(sb, dictionaryKeyType, dictionaryValueType); break; case "StringBuilder": if (constructor.Type.Generics.Length != 0) { throw new ParserException(constructor.Type.FirstToken, "StringBuilder constructor does not have any generics."); } this.TranslateStringBuilderNew(sb); break; default: // TODO: throw an exception (in the parser) if generics exist. this.TranslateConstructorInvocation(sb, constructor); break; } break; case "DotField": DotField df = (DotField)expression; StructDefinition structDef = df.StructType; ClassDefinition classDef = df.ClassType; string fieldName = df.FieldName.Value; if (classDef != null) { this.TranslateInstanceFieldDereference(sb, df.Root, classDef, fieldName); } else if (structDef != null) { int fieldIndex = structDef.FlatFieldIndexByName[fieldName]; this.TranslateStructFieldDereference(sb, df.Root, structDef, fieldName, fieldIndex); } else { throw new InvalidOperationException(); // should have been thrown by the compiler } break; case "InlineConstant": InlineConstant ic = (InlineConstant)expression; switch (ic.ResolvedType.RootValue) { case "bool": this.TranslateBooleanConstant(sb, (bool)ic.Value); break; case "char": this.TranslateCharConstant(sb, ((string)ic.Value)[0]); break; case "double": this.TranslateFloatConstant(sb, (double)ic.Value); break; case "int": this.TranslateIntegerConstant(sb, (int)ic.Value); break; case "null": this.TranslateNullConstant(sb); break; case "string": this.TranslateStringConstant(sb, (string)ic.Value); break; default: throw new NotImplementedException(); } break; case "ThisExpression": this.TranslateThis(sb, (ThisExpression)expression); break; case "UnaryOp": UnaryOp uo = (UnaryOp)expression; if (uo.OpToken.Value == "-") { this.TranslateNegative(sb, uo); } else { this.TranslateBooleanNot(sb, uo); } break; case "ForcedParenthesis": sb.Append('('); this.TranslateExpression(sb, ((ForcedParenthesis)expression).Expression); sb.Append(')'); break; default: throw new NotImplementedException(typeName); } }