private static void HandleNextOperator( OperatorToken opToken, List <ParsingUnit> units, IEnumerator <Token> tokens, CompilationContext context) { switch (opToken.operatorType) { case Operator.Assignment: case Operator.PlusEquals: case Operator.MinusEquals: case Operator.TimesEquals: case Operator.DivideEquals: case Operator.PowerEquals: case Operator.ModuloEquals: case Operator.AndEquals: case Operator.OrEquals: case Operator.Plus: case Operator.Minus: case Operator.Times: case Operator.Divide: case Operator.Power: case Operator.Modulo: case Operator.CastDouble: case Operator.CastInteger: case Operator.Increment: case Operator.Decrement: case Operator.Not: case Operator.IsEqualTo: case Operator.IsNotEqualTo: case Operator.IsGreaterThan: case Operator.IsGreaterThanOrEqualTo: case Operator.IsLessThan: case Operator.IsLessThanOrEqualTo: case Operator.And: case Operator.Or: case Operator.Negate: //Add and continue units.Add(new TokenUnit(opToken)); tokens.CautiousAdvance(); break; case Operator.Ternary: //Add the ternary Operator units.Add(new TokenUnit(opToken)); tokens.CautiousAdvance(); //Add the first expected expression Token firstToken = tokens.Current; units.Add(new ParsedValuedUnit( value: ParseNextExpression(tokens, context), firstToken: firstToken)); //Colon tokens.AssertAndSkip(Separator.Colon); //Add the second expected expression firstToken = tokens.Current; units.Add(new ParsedValuedUnit( value: ParseNextExpression(tokens, context), firstToken: firstToken)); break; case Operator.MemberAccess: tokens.CautiousAdvance(); IdentifierToken nameToken = tokens.GetTokenAndAdvance <IdentifierToken>(); if (tokens.TestWithoutSkipping(Separator.OpenParen)) { //Method units.Add(new MemberAccessUnit( identifier: nameToken.identifier, args: ParseArguments(tokens, context), firstToken: opToken)); } else { //Value units.Add(new MemberAccessUnit( identifier: nameToken.identifier, args: null, firstToken: opToken)); } break; case Operator.AmbiguousMinus: default: throw new ArgumentException($"Unsupported Operator: {opToken.operatorType}"); } }
private static void HandleNextKeyword( KeywordToken keywordToken, List <ParsingUnit> units, IEnumerator <Token> tokens, CompilationContext context) { switch (keywordToken.keyword) { case Keyword.New: { tokens.CautiousAdvance(); Type newObjectType = tokens.ReadType(); IValueGetter[] args = ParseArguments(tokens, context); if (tokens.TestWithoutSkipping(Separator.OpenCurlyBoi)) { Type itemType = newObjectType.GetInitializerItemType(); if (itemType == null) { throw new ScriptParsingException( source: keywordToken, message: $"Initializer Lists only function on collections. " + $"Did you enter the wrong type, or possibly omit a semicolon at the end of the expression?"); } //Initializer Syntax IValueGetter[] items = ParseItems(tokens, itemType, context); units.Add(new ParsedValuedUnit( value: new ConstructInitializedCollectionExpression( objectType: newObjectType, args: args, items: items, source: keywordToken), firstToken: keywordToken)); } else { units.Add(new ParsedValuedUnit( value: new ConstructObjectExpression( objectType: newObjectType, args: args), firstToken: keywordToken)); } } break; case Keyword.System: case Keyword.User: case Keyword.Math: case Keyword.Debug: { tokens.CautiousAdvance(); tokens.AssertAndSkip(Operator.MemberAccess); IdentifierToken identifierToken = tokens.GetTokenAndAdvance <IdentifierToken>(); if (tokens.TestWithoutSkipping(Operator.IsLessThan)) { //Generic Method Type[] internalTypes = tokens.ReadTypeArguments(); units.Add(new ParsedValuedUnit( value: MemberManagement.HandleStaticGenericMethodExpression( keywordToken: keywordToken, args: ParseArguments(tokens, context), identifier: identifierToken.identifier, genericTypes: internalTypes), firstToken: keywordToken)); } else if (tokens.TestWithoutSkipping(Separator.OpenParen)) { //Method units.Add(new ParsedValuedUnit( value: MemberManagement.HandleStaticMethodExpression( keywordToken: keywordToken, args: ParseArguments(tokens, context), identifier: identifierToken.identifier), firstToken: keywordToken)); } else { //Member units.Add(new ParsedValuedUnit( value: MemberManagement.HandleStaticMemberExpression( keywordToken: keywordToken, identifier: identifierToken.identifier), firstToken: keywordToken)); } } break; default: units.Add(new TokenUnit(tokens.Current)); tokens.CautiousAdvance(); break; } }
public void ParseNextGlobal( IEnumerator <Token> scriptTokens, ScriptCompilationContext context) { switch (scriptTokens.Current) { case KeywordToken kwToken: //Valid operations: // Global declaration // Extern declaration // Member declaration // Class declaration switch (kwToken.keyword) { case Keyword.Global: case Keyword.Extern: //Parse Global Declaration { scriptTokens.CautiousAdvance(); Type valueType = scriptTokens.ReadType(); IdentifierToken identToken = scriptTokens.GetTokenAndAdvance <IdentifierToken>(); IValueGetter initializerExpression = null; if (scriptTokens.TestAndConditionallySkip(Operator.Assignment)) { initializerExpression = Expression.ParseNextGetterExpression(scriptTokens, context); } scriptTokens.AssertAndSkip(Separator.Semicolon, false); scriptDeclarations.Add( new GlobalDeclaration( identifierToken: identToken, valueType: valueType, isExtern: kwToken.keyword == Keyword.Extern, initializer: initializerExpression, context: context)); } return; case Keyword.Const: { scriptTokens.CautiousAdvance(); Type valueType = scriptTokens.ReadType(); IdentifierToken identToken = scriptTokens.GetTokenAndAdvance <IdentifierToken>(); scriptTokens.AssertAndSkip(Operator.Assignment); IValueGetter initializerExpression = Expression.ParseNextGetterExpression(scriptTokens, context); scriptTokens.AssertAndSkip(Separator.Semicolon, false); if (!(initializerExpression is LiteralToken litToken)) { throw new ScriptParsingException( source: kwToken, message: $"The value of Const declarations must be constant"); } object value = litToken.GetAs <object>(); if (!valueType.IsAssignableFrom(litToken.GetValueType())) { value = Convert.ChangeType(value, valueType); } context.DeclareConstant( identifierToken: identToken, type: valueType, value: value); } return; case Keyword.Void: case Keyword.Bool: case Keyword.Double: case Keyword.Integer: case Keyword.String: case Keyword.List: case Keyword.Queue: case Keyword.Stack: case Keyword.DepletableBag: case Keyword.DepletableList: case Keyword.RingBuffer: case Keyword.Dictionary: case Keyword.HashSet: case Keyword.Random: case Keyword.DataFile: //Parse Function or Member Declaration { Type valueType = scriptTokens.ReadType(); IdentifierToken identToken = scriptTokens.GetTokenAndAdvance <IdentifierToken>(); if (scriptTokens.TestWithoutSkipping(Separator.OpenParen)) { VariableData[] arguments = ParseArgumentsDeclaration(scriptTokens); if (scriptFunctions.ContainsKey(identToken.identifier)) { throw new ScriptParsingException( source: identToken, message: $"Two declarations of function {identToken.identifier} found."); } scriptFunctions.Add(identToken.identifier, new ScriptFunction( functionTokens: scriptTokens, functionSignature: new FunctionSignature( identifierToken: identToken, returnType: valueType, arguments: arguments), context: context)); } else { //Member declaration if (kwToken.keyword == Keyword.Void) { throw new ScriptParsingException( source: kwToken, message: $"Cannot declare a member of type Void"); } IValueGetter initializerExpression = null; if (scriptTokens.TestAndConditionallySkip(Operator.Assignment)) { initializerExpression = Expression.ParseNextGetterExpression(scriptTokens, context); } scriptTokens.AssertAndSkip(Separator.Semicolon, false); scriptDeclarations.Add( new MemberDeclaration( identifierToken: identToken, valueType: valueType, initializer: initializerExpression, context: context)); } } return; default: throw new ScriptParsingException( source: kwToken, message: $"Token not valid for global context: {kwToken}."); } default: throw new ScriptParsingException( source: scriptTokens.Current, message: $"Token not valid for global context: {scriptTokens.Current}."); } }