Пример #1
0
 /// <summary>
 ///		Initializes a new instance of this class and adds itself to 
 ///		the given scope's symbol list.
 /// </summary>
 /// <param name="scope">Scope that this symbol is in.</param>
 public EnumerationSymbol(Symbol scope)
 {
     _scope = scope;
     if (scope != null) scope.AddSymbol(this);
 }
Пример #2
0
 /// <summary>
 ///		Initializes a new instance of this class and adds itself to 
 ///		the given scope's symbol list.
 /// </summary>
 /// <param name="scope">Scope that this symbol is in.</param>
 public StateSymbol(Symbol scope)
 {
     _scope = scope;
     if (scope != null) scope.AddSymbol(this);
 }
Пример #3
0
 /// <summary>
 ///		Initializes a new instance of this class and adds itself to 
 ///		the given scope's symbol list.
 /// </summary>
 /// <param name="scope">Scope that this symbol is in.</param>
 /// <param name="ident">Contents of this string.</param>
 public StringSymbol(Symbol scope, string ident)
 {
     _scope = scope;
     if (scope != null) scope.AddSymbol(this);
     _ident = ident;
 }
Пример #4
0
        /// <summary>
        ///		Parses a single statement. A statement encompesses the highest level of parsing, things like
        ///		the while loop, the if statement and the return statement ... ecetera.
        /// </summary>
        private void ParseStatement()
        {
            // Check is is an empty statement.
            if (LookAheadToken() != null && LookAheadToken().ID == TokenID.CharSemiColon)
            {
                ExpectToken(TokenID.CharSemiColon);
                return;
            }

            // Check if there is an open block next, and if so parse it.
            if (LookAheadToken().ID == TokenID.CharOpenBrace)
            {
                ParseBlock(TokenID.CharOpenBrace, TokenID.CharCloseBrace);
                return;
            }

            // Check if we have a chunk of meta data next.
            bool foundThisParse = true;
            if (LookAheadToken().ID == TokenID.CharOpenBracket)
            {
                _lastMetaDataSymbol = null;
                foundThisParse = true;
                ParseMetaData();
            }

            // Emit a enter statement opcode if in debug.
            bool isBreakpoint = (LookAheadToken().ID == TokenID.KeywordBreakpoint);
            if ((_compileFlags & CompileFlags.Debug) != 0 && _currentPass == 1 && isBreakpoint == false)
                CreateInstruction(OpCode.ENTER_STATEMENT, _currentScope, (Token)_tokenList[_tokenIndex]);

            // Parse based on starting token.
            switch (NextToken().ID)
            {
                // General statements.
                case TokenID.KeywordDo:			ParseDo();			break;
                case TokenID.KeywordEnum:		ParseEnum();		break;
                case TokenID.KeywordIf:			ParseIf();			break;
                case TokenID.KeywordLock:		ParseLock();		break;
                case TokenID.KeywordAtom:		ParseAtom();		break;
                case TokenID.KeywordReturn:		ParseReturn();		break;
                case TokenID.KeywordSwitch:		ParseSwitch();		break;
                case TokenID.KeywordState:		ParseState();		break;
                case TokenID.KeywordWhile:		ParseWhile();		break;
                case TokenID.KeywordFor:		ParseFor();			break;
                case TokenID.KeywordGoto:		ParseGoto();		break;
                case TokenID.KeywordBreak:		ParseBreak();		break;
                case TokenID.KeywordContinue:	ParseContinue();	break;
                case TokenID.KeywordGotoState:	ParseGotoState();	break;
                case TokenID.KeywordBreakpoint: ParseBreakPoint();  break;
                case TokenID.KeywordNamespace:  ParseNamespace();   break;

                case TokenID.KeywordEditor:
                case TokenID.KeywordEngine:
                    ParseState();
                    break;
                /*
                case TokenID.KeywordStruct:		ParseStruct();		break;
                case TokenID.KeywordClass:		ParseClass();		break;
                */

                // Variable / function declarations.
                case TokenID.KeywordBool:
                case TokenID.KeywordByte:
                case TokenID.KeywordDouble:
                case TokenID.KeywordObject:
                case TokenID.KeywordFloat:
                case TokenID.KeywordInt:
                case TokenID.KeywordLong:
                case TokenID.KeywordShort:
                case TokenID.KeywordString:
                case TokenID.KeywordVoid:
                case TokenID.KeywordConst:
                case TokenID.KeywordStatic:
                case TokenID.KeywordProperty:
                case TokenID.KeywordImport:
                case TokenID.KeywordExport:
                case TokenID.KeywordThread:
                case TokenID.KeywordPublic:
                case TokenID.KeywordProtected:
                case TokenID.KeywordPrivate:
                case TokenID.KeywordEvent:
                case TokenID.KeywordConsole:

                    int offset = 0;
                    if (_currentToken.ID == TokenID.KeywordPublic || _currentToken.ID == TokenID.KeywordProtected || _currentToken.ID == TokenID.KeywordPrivate)
                        offset = 1;

                    if (_currentToken.ID == TokenID.KeywordConsole || _currentToken.ID == TokenID.KeywordEvent || _currentToken.ID == TokenID.KeywordExport || _currentToken.ID == TokenID.KeywordImport || _currentToken.ID == TokenID.KeywordThread || LookAheadToken(2 + offset).ID == TokenID.CharOpenParenthesis)
                        ParseFunction();

                    // If its not parenthesis its a variable declaration.
                    else
                        ParseVariable();

                    break;

                // Assignments and function calls.
                case TokenID.TypeIdentifier:

                    // Check if its a label.
                    if (LookAheadToken().ID == TokenID.CharColon)
                        ParseLabel();

                    // See if its a function or assignment.
                    else
                    {
                        int tokenIndex = _tokenIndex;
                        Token currentToken = _currentToken;
                        ResolveMemberScope();

                        // Ignore any array accessors.
                        if (LookAheadToken().ID == TokenID.CharOpenBracket)
                        {
                            NextToken();
                            int depth = 1;
                            while (depth != 0)
                            {
                                NextToken();
                                if (_currentToken.ID == TokenID.CharOpenBracket)
                                    depth++;
                                else if (_currentToken.ID == TokenID.CharCloseBracket)
                                    depth--;
                            }
                            //ExpectToken(TokenID.CharCloseBracket);
                        }

                        // Function
                        if (LookAheadToken().ID == TokenID.CharOpenParenthesis)
                        {
                            string functionName = _currentToken.Ident;
                            _tokenIndex = tokenIndex;
                            _currentToken = currentToken;

                            // Check we are in a valid scope.
                            if (_currentScope.Type != SymbolType.Function || _currentScope == _globalScope)
                                Error(ErrorCode.InvalidScope, "Function calls are only valid inside a function's or event's scope.", false, 0);

                            DataTypeValue functionDataType = ParseFunctionCall();

                            // Do we have a member call after?
                            if (LookAheadToken().ID == TokenID.OpMemberResolver)
                            {
                                NextToken();

                                // If its not an object how can we access it?
                                if (functionDataType != new DataTypeValue(DataType.Object, false, false))
                                    Error(ErrorCode.IllegalResolve, "Member accessing can only be preformed on objects.", false, 1);

                                // Parse the cast.
                                ExpectToken(TokenID.CharOpenParenthesis);
                                if (NextToken().IsDataType == false)
                                    Error(ErrorCode.InvalidCast, "Attempt to cast member to unknown type.", false, 0);

                                DataTypeValue castDataType = new DataTypeValue(DataTypeFromKeywordToken(_currentToken.ID), false, false);

                                // Is it an array?
                                if (LookAheadToken().ID == TokenID.CharCloseBracket)
                                {
                                    NextToken();
                                    ExpectToken(TokenID.CharCloseBracket);
                                    castDataType.IsArray = true;
                                }
                                ExpectToken(TokenID.CharCloseParenthesis);

                                ExpectToken(TokenID.TypeIdentifier);

                                if (LookAheadToken().ID == TokenID.CharOpenParenthesis)
                                    ParseMemberFunctionCall(_currentToken.Ident, castDataType);
                                else
                                    ParseMemberAssignment(_currentToken.Ident, castDataType);
                            }

                            ExpectToken(TokenID.CharSemiColon);
                        }

                        // Member function / assignment?
                        else if (LookAheadToken().ID == TokenID.OpMemberResolver)
                        {
                            ParseMemberAccessor();
                            ExpectToken(TokenID.CharSemiColon);
                        }

                        // Assignment.
                        else
                        {
                            _tokenIndex = tokenIndex;
                            _currentToken = currentToken;

                            ParseAssignment();
                            ExpectToken(TokenID.CharSemiColon);
                        }
                    }

                    break;

                // Its none of the above its invalid.
                default:
                    Error(ErrorCode.UnexpectedToken, "Encountered unexpected token \"" + _currentToken.ToString() + "\"", false, 0);

                    break;
            }

            // Emit a exit statement opcode if in debug.
            if ((_compileFlags & CompileFlags.Debug) != 0 && _currentPass == 1 && isBreakpoint == false)
                CreateInstruction(OpCode.EXIT_STATEMENT, _currentScope, _currentToken);

            // If we read in any meta data associated with this statement then destroy it now.
            if (_metaDataList.Count > 0 && foundThisParse == true)
            {
                Symbol symbolToAttachTo = null;
                if (_lastMetaDataSymbol != null)
                    symbolToAttachTo = _lastMetaDataSymbol;
                else
                    symbolToAttachTo = _currentScope;

                if (_currentPass == 0)
                {
                    foreach (MetaDataSymbol metaDataSymbol in _metaDataList)
                    {
                        metaDataSymbol.Scope = symbolToAttachTo;
                        symbolToAttachTo.AddSymbol(metaDataSymbol);
                    }
                }
                _metaDataList.Clear();
            }
        }
Пример #5
0
        /// <summary>
        ///		Parses a variable declaration. A variable is a place in memory that is used	
        ///		to store a value used by other statements.
        ///		Syntax:
        ///			DataType { Identifier [ "[" Expression "]" ] [ "=" Expression ] [ "," ] } ";"
        /// </summary>
        private void ParseVariable()
        {
            // Make sure we are in a valid scope.
            if (_currentScope.Type != SymbolType.Function &&
                _currentScope.Type != SymbolType.State &&
                _currentScope.Type != SymbolType.Namespace) Error(ErrorCode.InvalidScope, "Variables can't be declared in this scope.", false, 0);

            // Check if we are in a states scope.
            bool inState = (_currentScope.Type == SymbolType.State);
            bool inNamespace = (_currentScope.Type == SymbolType.Namespace);
            bool inEnumeration = (_currentScope.Type == SymbolType.Enumeration);

            // Read in each flag.
            bool isStatic = false;
            bool isConst = false;
            bool isProperty = false;
            SymbolAccessModifier modifier = SymbolAccessModifier.Private;
            bool gotModifier = false;
            while (EndOfTokenStream() != true)
            {
                switch (_currentToken.ID)
                {
                    case TokenID.KeywordStatic:
                        if (isStatic == true) Error(ErrorCode.DuplicateFlag, "\"" + _currentToken.Ident + "\" flag declared multiple times.", false, 0);
                        isStatic = true;
                        break;
                    case TokenID.KeywordConst:
                        if (isConst == true) Error(ErrorCode.DuplicateFlag, "\"" + _currentToken.Ident + "\" flag declared multiple times.", false, 0);
                        isConst = true;
                        break;
                    case TokenID.KeywordProperty:
                        if (isProperty == true) Error(ErrorCode.DuplicateFlag, "\"" + _currentToken.Ident + "\" flag declared multiple times.", false, 0);
                        isProperty = true;
                        break;
                    case TokenID.KeywordPublic:
                        if (gotModifier == true) Error(ErrorCode.DuplicateFlag, "Access modifier has already been declared.", false, 0);
                        modifier = SymbolAccessModifier.Public;
                        gotModifier = true;
                        break;
                    case TokenID.KeywordPrivate:
                        if (gotModifier == true) Error(ErrorCode.DuplicateFlag, "Access modifier has already been declared.", false, 0);
                        modifier = SymbolAccessModifier.Private;
                        gotModifier = true;
                        break;
                    case TokenID.KeywordProtected:
                        if (gotModifier == true) Error(ErrorCode.DuplicateFlag, "Access modifier has already been declared.", false, 0);
                        modifier = SymbolAccessModifier.Protected;
                        gotModifier = true;
                        break;
                    default:
                        goto outOfLoop;
                }
                NextToken();
            }
            outOfLoop:

            // Get data type by the current tokens id.
            DataType dataType = DataTypeFromKeywordToken(_currentToken.ID);
            if (dataType == DataType.Void || dataType == DataType.Invalid)
                Error(ErrorCode.InvalidDataType, "Variable can't be declared as \"" + _currentToken.Ident + "\".", false, 0);

            // Check if its an array.
            bool isArray = false;
            if (LookAheadToken().ID == TokenID.CharOpenBracket)
            {
                ExpectToken(TokenID.CharOpenBracket);
                isArray = true;
                ExpectToken(TokenID.CharCloseBracket);
            }

            // Parse all variables seperated by a comma.
            while (true)
            {
                // Read in variable identifier and store it for later use.
                ExpectToken(TokenID.TypeIdentifier);
                string variableIdent = _currentToken.Ident;

                // Create a new variable symbol.
                VariableSymbol variableSymbol = null;
                if (_currentPass == 0)
                {
                    if (_currentScope.FindSymbol(variableIdent, SymbolType.Variable) != null)
                        Error(ErrorCode.DuplicateSymbol, "Variable \"" + variableIdent + "\" declared multiple times.", false, 0);
                    variableSymbol = new VariableSymbol(_currentScope);
                    variableSymbol.Identifier = variableIdent;
                    variableSymbol.IsArray = isArray;
                    variableSymbol.IsConstant = isConst;
                    variableSymbol.IsProperty = isProperty;
                    variableSymbol.AccessModifier = modifier;
                    variableSymbol.DataType = new DataTypeValue(dataType, isArray, false);
                    variableSymbol.VariableType = isConst == true ? VariableType.Constant : (_currentScope == _globalScope || inState == true || isStatic == true || inEnumeration == true || inNamespace == true ? VariableType.Global : VariableType.Local);
                    if (variableSymbol.VariableType == VariableType.Constant || variableSymbol.VariableType == VariableType.Global)
                    {
                        variableSymbol.MemoryIndex = _memorySize;
                        _memorySize++;
                    }
                    else
                    {
                        if (_currentScope.Type == SymbolType.Function)
                        {
                            variableSymbol.StackIndex = -(((FunctionSymbol)_currentScope).LocalDataSize + 2);
                            ((FunctionSymbol)_currentScope).LocalDataSize++;
                        }
                    }
                }
                else if (_currentPass == 1)
                {
                    variableSymbol = _currentScope.FindSymbol(variableIdent, SymbolType.Variable) as VariableSymbol;
                    if (variableSymbol == null) variableSymbol = _globalScope.FindSymbol(variableIdent, SymbolType.Variable) as VariableSymbol;
                }

                _lastMetaDataSymbol = variableSymbol;

                // Check if there is an assignment.
                if (LookAheadToken().ID == TokenID.OpAssign)
                {
                    NextToken();

                    // If we are a constant then see if we are being assigned a literal value.
                    Token LAT = LookAheadToken();
                    if (isConst == true &&
                       (LAT.ID == TokenID.TypeBoolean || LAT.ID == TokenID.TypeByte ||
                        LAT.ID == TokenID.TypeDouble || LAT.ID == TokenID.TypeFloat ||
                        LAT.ID == TokenID.TypeInteger || LAT.ID == TokenID.TypeLong ||
                        LAT.ID == TokenID.TypeShort ||
                        LAT.ID == TokenID.TypeString) && LookAheadToken(2).ID == TokenID.CharSemiColon)
                    {
                        NextToken();
                        if (CanImplicitlyCast(variableSymbol.DataType, new DataTypeValue(DataTypeFromTypeToken(_currentToken.ID), false, false)) == true)
                            variableSymbol.ConstToken = _currentToken;
                        else
                            Error(ErrorCode.InvalidDataType, "Unable to implicitly cast from type \"" + DataTypeFromTypeToken(_currentToken.ID).ToString() + "\" to type \"" + variableSymbol.DataType.ToString() + "\".", false, 1);
                    }
                    else
                    {
                        // This will temporarily change the state if the variable is static.
                        Symbol previousScope = null;
                        if (isStatic == true || inState == true || inNamespace == true || inEnumeration == true)
                        {
                            previousScope = _overrideInstructionScope;
                            _overrideInstructionScope = _globalScope;
                        }

                        // Parse the assignment expression.
                        DataTypeValue expressionType = ParseExpression();

                        if (CanImplicitlyCast(variableSymbol.DataType, expressionType) == true)
                        {
                            if (_currentPass == 1)
                            {
                                // Pop the value out of the stack and assign it to this variable.
                                Instruction instruction = CreateInstruction(OpCodeByType(expressionType, OpCodeType.POP), _currentScope, _currentToken);
                                new Operand(instruction, Register.Arithmetic1);

                                // Cast arith register 1 into the variables type.
                                if (variableSymbol.DataType != expressionType)
                                {
                                    instruction = CreateInstruction(OpCodeByType(variableSymbol.DataType, OpCodeType.CAST), _currentScope, _currentToken);
                                    new Operand(instruction, Register.Arithmetic1);
                                }

                                // Move the resulting value (stored in arithmatic register 3)
                                // into the variable.
                                instruction = CreateInstruction(OpCodeByType(variableSymbol.DataType, OpCodeType.MOV), _currentScope, _currentToken);

                                Operand op1 = null;
                                if (variableSymbol.VariableType == VariableType.Global || variableSymbol.VariableType == VariableType.Constant)
                                    op1 = Operand.DirectMemoryOperand(instruction, variableSymbol.MemoryIndex);
                                else
                                    op1 = Operand.DirectStackOperand(instruction, variableSymbol.StackIndex);
                                new Operand(instruction, Register.Arithmetic1);
                            }
                        }
                        else
                        {
                            Error(ErrorCode.InvalidDataType, "Unable to implicitly cast from type \"" + expressionType.ToString() + "\" to type \"" + variableSymbol.DataType.ToString() + "\".", false, 1);
                        }

                        // If we have changed the scope then change back.
                        if (isStatic == true || inState == true || inNamespace == true || inEnumeration == true)
                        {
                            _overrideInstructionScope = previousScope;
                        }
                    }
                }

                else
                {
                    if (isConst == true) Error(ErrorCode.IllegalAssignment, "Constant must be assigned a value.", false, 0);
                }

                // Read in comma or break out of loop if there isn't one.
                if (LookAheadToken().ID == TokenID.CharComma)
                    NextToken();
                else
                    break;
            }

            // Read in semi-colon at end of declarations.
            ExpectToken(TokenID.CharSemiColon);
        }
Пример #6
0
 /// <summary>
 ///		Initializes a new instance of this class with the given identifier,
 ///		and add's itself to the given scope's symbol list.
 /// </summary>
 /// <param name="ident">Identifier used to identify this symbol.</param>
 /// <param name="scope">Scope that symbol is in.</param>
 public FunctionSymbol(string ident, Symbol scope)
 {
     _ident = ident;
     _scope = scope;
     if (scope != null) scope.AddSymbol(this);
 }
Пример #7
0
 /// <summary>
 ///		Initializes a new instance of this class and adds itself to 
 ///		the given scope's symbol list.
 /// </summary>
 /// <param name="scope">Scope that this symbol is in.</param>
 /// <param name="ident">Name of this meta data.</param>
 /// <param name="value">Value of this meta data.</param>
 public MetaDataSymbol(Symbol scope, string ident, string value)
 {
     _scope = scope;
     if (scope != null) scope.AddSymbol(this);
     _ident = ident;
     _value = value;
 }
Пример #8
0
        /// <summary>
        ///		Parses a enumeration declaration. An enumeration is a way of creating a list
        ///		of sequential integer constants without having to create and assign them.
        ///		Syntax:
        ///			"enum" "{" { Identifier [ "=" Expression ] [ "," ] } "}"
        /// </summary>
        private void ParseEnum()
        {
            // Make sure we are in a valid scope.
            if (_currentScope != _globalScope &&
                _currentScope.Type != SymbolType.Namespace)
                Error(ErrorCode.InvalidScope, "Enumerations are only valid in global scope.", false, 0);

            // Read in enumeration identifier.
            ExpectToken(TokenID.TypeIdentifier);

            // Create enumeration symbol.
            EnumerationSymbol mainEnumSymbol = null;
            if (_currentPass == 0)
            {
                if (_currentScope.FindSymbol(_currentToken.Ident) != null) Error(ErrorCode.DuplicateSymbol, "Encountered multiple declarations of the "+_currentToken.Ident+" symbol");
                mainEnumSymbol = new EnumerationSymbol(_currentScope);
                mainEnumSymbol.Identifier = _currentToken.Ident;
            }
            else
                mainEnumSymbol = _currentScope.FindSymbol(_currentToken.Ident) as EnumerationSymbol;

            // Read in opening brace.
            ExpectToken(TokenID.CharOpenBrace);

            // Read in each constant and its expression.
            int indexValue = 1;
            while (true)
            {

                // Read in constant identifier.
                ExpectToken(TokenID.TypeIdentifier);
                string enumIdentifier = _currentToken.Ident;

                // Create constant variable to store value into.
                VariableSymbol enumSymbol = null;
                if (_currentPass == 0)
                {
                    if (mainEnumSymbol.FindSymbol(_currentToken.Ident) != null) Error(ErrorCode.DuplicateSymbol, "Encountered multiple declarations of the " + _currentToken.Ident + " symbol");
                    enumSymbol = new VariableSymbol(mainEnumSymbol);
                    enumSymbol.Identifier = enumIdentifier;
                    enumSymbol.DataType = new DataTypeValue(DataType.Int, false, false);
                    enumSymbol.IsConstant = true;
                }
                else
                    enumSymbol = mainEnumSymbol.FindSymbol(enumIdentifier) as VariableSymbol;

                _lastMetaDataSymbol = enumSymbol;

                // Read in expression if its there.
                Instruction instruction;
                if (LookAheadToken().ID == TokenID.OpAssign)
                {
                    NextToken();

                    Token LAT = LookAheadToken();
                    Token LALAT = LookAheadToken(2);

                    if ((LAT.ID == TokenID.TypeBoolean || LAT.ID == TokenID.TypeByte ||
                        LAT.ID == TokenID.TypeDouble || LAT.ID == TokenID.TypeFloat ||
                        LAT.ID == TokenID.TypeInteger || LAT.ID == TokenID.TypeLong ||
                        LAT.ID == TokenID.TypeShort ||
                        LAT.ID == TokenID.TypeString) && (LALAT.ID == TokenID.CharComma || LALAT.ID == TokenID.CharCloseBrace))
                    {
                        NextToken();
                        if (CanImplicitlyCast(enumSymbol.DataType, new DataTypeValue(DataTypeFromTypeToken(_currentToken.ID), false, false)) == true)
                            enumSymbol.ConstToken = _currentToken;
                        else
                            Error(ErrorCode.InvalidDataType, "Unable to implicitly cast from type \"" + DataTypeFromTypeToken(_currentToken.ID).ToString() + "\" to type \"" + enumSymbol.DataType.ToString() + "\".", false, 1);
                    }
                    else
                    {
                        Symbol oldScope = _currentScope;
                        _currentScope = _globalScope;

                        // Parse the assignment expression.
                        DataTypeValue assignmentType = ParseExpression();

                        if (CanImplicitlyCast(new DataTypeValue(DataType.Int, false, false), assignmentType) == true)
                        {
                            // We need to allocate some memory space.
                            if (_currentPass == 0)
                            {
                                enumSymbol.MemoryIndex = _memorySize;
                                _memorySize++;
                            }

                            if (_currentPass == 1)
                            {
                                // Pop the expression value into arith register 1.
                                instruction = CreateInstruction(OpCodeByType(enumSymbol.DataType, OpCodeType.POP), _currentScope, _currentToken);
                                new Operand(instruction, Register.Arithmetic1);

                                // Move the value stored in arith register 1 into enums memory space.
                                instruction = CreateInstruction(OpCodeByType(enumSymbol.DataType, OpCodeType.MOV), _currentScope, _currentToken);
                                Operand.DirectMemoryOperand(instruction, enumSymbol.MemoryIndex);
                                new Operand(instruction, Register.Arithmetic1);
                            }
                        }
                        else
                            Error(ErrorCode.InvalidDataType, "Enumeration const of type \"" + enumSymbol.DataType.ToString() + "\" can't store type \"" + assignmentType.ToString() + "\".", false, 0);

                        _currentScope = oldScope;
                    }

                }
                else
                    enumSymbol.ConstToken = new Token(TokenID.TypeInteger, indexValue.ToString(), 0, 0, "");

                // Update index number in a *2 fashion so it can
                // be used as a bitmask.
                indexValue *= 2;

                // Read in comma if it exists.
                if (LookAheadToken().ID == TokenID.CharComma)
                    NextToken();
                else
                    break;

            }

            // Read in closing brace.
            ExpectToken(TokenID.CharCloseBrace);
        }
Пример #9
0
        /// <summary>
        ///		Parses a function declaration. A function is a way of isolating code that you want
        ///		to be able to call multiple times without rewriting it each time.
        ///		Syntax:
        ///			ReturnType Identifier "(" { Identifier ["=" Expression] [ "," ] } ")" Statement
        /// </summary>
        private void ParseFunction()
        {
            // Make sure we are in a state's scope.
            if (_currentToken.ID == TokenID.KeywordEvent &&
                _currentScope.Type != SymbolType.State)
                Error(ErrorCode.InvalidScope, "Events can only be declared within a state block.", false, 0);

            // Make sure we are in the global scopes as functions can't
            // be declared anywhere else.
            if (_currentScope.Type != SymbolType.State &&
                _currentScope.Type != SymbolType.Function &&
                _currentScope.Type != SymbolType.Namespace)
                Error(ErrorCode.InvalidScope, "Functions can only be declared in a function's, state's or event's scope.", false, 0);

            // Read in each flag.
            bool isThread = false;
            bool isEvent = false;
            bool isConsole = false;
            bool isExport = false;
            bool isImport = false;
            SymbolAccessModifier modifier = SymbolAccessModifier.Private;
            bool gotModifier = false;
            while (_currentToken.IsDataType == false && EndOfTokenStream() != true)
            {
                switch (_currentToken.ID)
                {
                    case TokenID.KeywordThread:
                        if (isThread == true) Error(ErrorCode.DuplicateFlag, "\"" + _currentToken.Ident + "\" flag declared multiple times.", false, 0);
                        isThread = true;
                        break;
                    case TokenID.KeywordEvent:
                        if (isEvent == true) Error(ErrorCode.DuplicateFlag, "\"" + _currentToken.Ident + "\" flag declared multiple times.", false, 0);
                        isEvent = true;
                        break;
                    case TokenID.KeywordConsole:
                        if (isConsole == true) Error(ErrorCode.DuplicateFlag, "\"" + _currentToken.Ident + "\" flag declared multiple times.", false, 0);
                        isConsole = true;
                        break;
                    case TokenID.KeywordImport:
                        if (isImport == true) Error(ErrorCode.DuplicateFlag, "\"" + _currentToken.Ident + "\" flag declared multiple times.", false, 0);
                        isImport = true;
                        break;
                    case TokenID.KeywordExport:
                        if (isExport == true) Error(ErrorCode.DuplicateFlag, "\"" + _currentToken.Ident + "\" flag declared multiple times.", false, 0);
                        isExport = true;
                        break;
                    case TokenID.KeywordPublic:
                        if (gotModifier == true) Error(ErrorCode.DuplicateFlag, "Access modifier has already been declared.", false, 0);
                        modifier = SymbolAccessModifier.Public;
                        gotModifier = true;
                        break;
                    case TokenID.KeywordPrivate:
                        if (gotModifier == true) Error(ErrorCode.DuplicateFlag, "Access modifier has already been declared.", false, 0);
                        modifier = SymbolAccessModifier.Private;
                        gotModifier = true;
                        break;
                    case TokenID.KeywordProtected:
                        if (gotModifier == true) Error(ErrorCode.DuplicateFlag, "Access modifier has already been declared.", false, 0);
                        modifier = SymbolAccessModifier.Protected;
                        gotModifier = true;
                        break;
                }
                NextToken();
            }
            if (isEvent == true && (isThread == true || isExport == true || isImport == true || isConsole == true))
                Error(ErrorCode.InvalidFlag, "Events can't be declared as native, threaded, exported, imported or console.");

            // Store the return type for later.
            DataTypeValue returnDataType = new DataTypeValue(DataTypeFromKeywordToken(_currentToken.ID), false, false);
            if (returnDataType.DataType == DataType.Invalid)
                Error(ErrorCode.InvalidDataType, "Functions can't be declared as \"" + _currentToken.Ident + "\".", false, 0);

            // Check for an array reference
            if (LookAheadToken().ID == TokenID.CharOpenBracket)
            {
                NextToken();
                returnDataType.IsArray = true;
                ExpectToken(TokenID.CharCloseBracket);
            }

            // Read in the functions identifier and store it
            // for layer use.
            ExpectToken(TokenID.TypeIdentifier);
            string functionIdentifier = _currentToken.Ident;

            // Read in the opening parenthesis used to define the paremeter list.
            ExpectToken(TokenID.CharOpenParenthesis);

            // Read in each paremeter.
            ArrayList functionParameterMask = new ArrayList();
            int parameterCount = 0;
            ArrayList paramList = new ArrayList();
            if (LookAheadToken().ID != TokenID.CharCloseParenthesis)
            {

                // Read in each parameter
                while (true)
                {

                    // Check if there is a constant keyword before this variable.
                    bool paramIsConst = false;
                    if (LookAheadToken().ID == TokenID.KeywordConst)
                    {
                        NextToken();
                        paramIsConst = true;
                    }

                    // Read in the data type keyword and store it.
                    NextToken();
                    DataTypeValue paramDataType = new DataTypeValue(DataTypeFromKeywordToken(_currentToken.ID), false, false);
                    if (paramDataType.DataType == DataType.Invalid) Error(ErrorCode.InvalidDataType, "Expecting data type keyword.", false, 0);

                    // Read in array declaration.
                    bool paramIsArray = false;
                    if (LookAheadToken().ID == TokenID.CharOpenBracket)
                    {
                        NextToken();
                        paramIsArray = true;
                        paramDataType.IsArray = true;
                        ExpectToken(TokenID.CharCloseBracket);
                    }

                    // Increase the parameter mask
                    functionParameterMask.Add(paramDataType);
                    parameterCount++;

                    // Read in the parameters identifier.
                    ExpectToken(TokenID.TypeIdentifier);
                    string paramIdentifier = _currentToken.Ident;

                    // Process parameters depending on current pass.
                    if (_currentPass == 0)
                    {
                        VariableSymbol variableSymbol = new VariableSymbol(null);
                        variableSymbol.DataType = paramDataType;
                        variableSymbol.Identifier = paramIdentifier;
                        variableSymbol.VariableType = VariableType.Parameter;
                        variableSymbol.IsArray = paramIsArray;
                        variableSymbol.IsConstant = paramIsConst;
                        paramList.Add(variableSymbol);
                    }

                    // Read in comma if it exists.
                    if (LookAheadToken().ID == TokenID.CharComma)
                        NextToken();
                    else
                        break;

                }

            }

            // *looks arounds shiftily* ... Ok its hack like but it works.
            functionParameterMask.Reverse();

            // Create a new function symbol.
            FunctionSymbol functionSymbol;
            if (_currentPass == 0)
            {
                if (_currentScope.FindFunctionByMask(functionIdentifier, functionParameterMask) != null)
                    Error(ErrorCode.DuplicateSymbol, "Function \"" + functionIdentifier + "\" redefinition.", false, 0);

                functionSymbol = new FunctionSymbol(functionIdentifier, _currentScope);
                functionSymbol.ReturnType = returnDataType;
                functionSymbol.ParameterCount = parameterCount;
                functionSymbol.IsThreadSpawner = isThread;
                functionSymbol.IsEvent = isEvent;
                functionSymbol.IsConsole = isConsole;
                functionSymbol.IsImport = isImport;
                functionSymbol.IsExport = isExport;
                functionSymbol.AccessModifier = modifier;

                if (isConsole == true && functionSymbol.ReturnType.DataType != DataType.Void)
                    Error(ErrorCode.InvalidDataType, "Console variables cannot return a value.");

                paramList.Reverse();
                int parameterIndex = 0;
                foreach (VariableSymbol variableSymbol in paramList)
                {
                    if (functionSymbol.FindSymbol(variableSymbol.Identifier, SymbolType.Variable) != null)
                        Error(ErrorCode.DuplicateSymbol, "Variable redefinition \"" + variableSymbol.Identifier + "\"");

                    // If we're a console function we can only accept bool, int, string or float
                    if (isConsole == true &&
                        (variableSymbol.DataType.IsArray == true ||
                        variableSymbol.DataType.DataType == DataType.Byte ||
                        variableSymbol.DataType.DataType == DataType.Double ||
                        variableSymbol.DataType.DataType == DataType.Object ||
                        variableSymbol.DataType.DataType == DataType.Short))
                        Error(ErrorCode.InvalidDataType, "Console variables can only accept bool, integer, string or float parameters.");

                    functionSymbol.AddSymbol(variableSymbol);
                    variableSymbol.Scope = functionSymbol;
                    parameterIndex++;
                }
            }
            else
            {
                functionSymbol = _currentScope.FindFunctionByMask(functionIdentifier, functionParameterMask) as FunctionSymbol;
                if (functionSymbol == null) functionSymbol = _globalScope.FindFunctionByMask(functionIdentifier, functionParameterMask) as FunctionSymbol;
                if (functionSymbol == null) Error(ErrorCode.InvalidFunction, "Attempt to call undeclared function \"" + functionIdentifier + "(" + functionParameterMask + ")\".");

                for (int i = 0; i < parameterCount; i++)
                {
                    VariableSymbol variableSymbol = (VariableSymbol)functionSymbol.Symbols[i];
                    variableSymbol.StackIndex = -(functionSymbol.LocalDataSize + 2 + (i + 1));
                }
            }
            _lastMetaDataSymbol = functionSymbol;

            // Read in the closing parenthesis used to define the end of the paremeter list.
            ExpectToken(TokenID.CharCloseParenthesis);

            // Read in this function's statement block.
            if (functionSymbol.IsImport == false)
            {
                Symbol scope = _currentScope;
                Instruction instruction = null;
                _currentScope = functionSymbol;
                ParseStatement();
                _currentScope = scope;

                // Append a mandatory return instruction if we are in pass 2.
                if (_currentPass == 1)
                {
                    // Cast the return registered into the return type.
                    if (functionSymbol.ReturnType.DataType != DataType.Void)
                    {
                        instruction = CreateInstruction(OpCodeByType(functionSymbol.ReturnType, OpCodeType.CAST), functionSymbol, _currentToken);
                        new Operand(instruction, Register.Return);
                    }

                    // Return from function.
                    instruction = CreateInstruction(OpCode.RETURN, functionSymbol, _currentToken);
                }
            }
            else
                ExpectToken(TokenID.CharSemiColon);
        }
Пример #10
0
        /// <summary>
        ///		Adds the given symbol and any sub symbols 
        ///		into the compiled symbol list.
        /// </summary>
        private void CompileSymbol(Symbol symbol)
        {
            _compiledSymbolList.Add(symbol);
            foreach (Symbol subSymbol in symbol.Symbols)
            {
                // Jump target?
                if (subSymbol.Type == SymbolType.JumpTarget) continue;

                // Dpn't compile unused import functions.
                if (subSymbol.Type == SymbolType.Function && ((FunctionSymbol)subSymbol).IsImport == true && ((FunctionSymbol)subSymbol).IsUsed == false) continue;

                CompileSymbol(subSymbol);
            }
        }
Пример #11
0
 /// <summary>
 ///     Creates a new byte code instruction.
 /// </summary>
 /// <param name="opcode">Opcode of instruction.</param>
 /// <param name="scope">Scope that instruction is in.</param>
 /// <param name="token">Token with line / offset data of instruction.</param>
 /// <returns>A new byte code instruction.</returns>
 private Instruction CreateInstruction(OpCode opcode, Symbol scope, Token token)
 {
     return new Instruction(opcode, _overrideInstructionScope != null ? _overrideInstructionScope : scope, token);
 }
Пример #12
0
        /// <summary>
        ///		Compiles a script from a string into byte code.
        /// </summary>
        /// <param name="data">Data of script to compile.</param>
        /// <param name="flags">Bitmask of flags defining how the script should be compiled.</param>
        /// <param name="defineList">A list of defines to use while preprocessing script.</param>
        /// <param name="includePaths">A list of directory paths to use when looking for include files.</param>
        /// <param name="fileUrl">Contains the url of the file this data comes from.</param>
        /// <returns>The number of errors or warning this script has generated duren compilation.</returns>
        public int CompileString(string data, CompileFlags flags, Define[] defineList, object[] includePaths, string fileUrl)
        {
            #if !DEBUG
            try
            {
            #endif
                // Reset all variables used to store compilation details.
                _errorList.Clear();
                _compiledSymbolList.Clear();
                _compiledInstructionList.Clear();
                _compiledDebugFileList.Clear();
                _compiledDefineList.Clear();
                _loopTrackerStack.Clear();
                _metaDataList.Clear();
                _currentToken = null;
                _currentPass = 0;
                _currentScope = null;
                _globalScope = new FunctionSymbol("$global", null); // Initialize global scope here.
                _memberScope = new FunctionSymbol("$member", null); // Initialize member scope here.
                _compileFlags = flags;
                _tokenList = null;
                _tokenIndex = 0;
                _memorySize = 1; // Reserve space for 'special' globals like 'this'.
                _internalVariableIndex = 0;
                _defaultEngineState = _defaultEditorState = null;
                _errorsOccured = false;
                _overrideInstructionScope = null;

                // Create the 'this' variable.
                VariableSymbol thisSymbol = new VariableSymbol(_globalScope);
                thisSymbol.DataType = new DataTypeValue(DataType.Object, false, false);
                thisSymbol.Identifier = "this";
                thisSymbol.IsConstant = true;
                thisSymbol.IsUsed = true;
                thisSymbol.MemoryIndex = 0;
                thisSymbol.VariableType = VariableType.Constant;

                // Create a lexer and convert script into a list
                // of tokens.
                DebugLogger.WriteLog("Preforming lexical analysis on script.");
                Lexer lexer = new Lexer();
                if (lexer.Analyse(data, _compileFlags, fileUrl) > 0)
                {
                    foreach (CompileError error in lexer.ErrorList)
                        _errorList.Add(error);
                }
                _tokenList = lexer.TokenList;

                // Add the script directory into the include path array.
                string includePath = Path.GetDirectoryName(fileUrl);
                string[] newIncludePaths = new string[includePaths.Length + 1];
                includePaths.CopyTo(newIncludePaths, 0);
                newIncludePaths[newIncludePaths.Length - 1] = includePath;
                includePaths = newIncludePaths;

                // Create a pre-processor and process the token list
                DebugLogger.WriteLog("Preforming preprocessing on script.");
                PreProcessor preProcessor = new PreProcessor();
                if (preProcessor.Process(_tokenList, _compileFlags, defineList, includePaths) > 0)
                {
                    foreach (CompileError error in preProcessor.ErrorList)
                        _errorList.Add(error);
                }
                _compiledDefineList = preProcessor.DefineList;
                _tokenList = preProcessor.TokenList;

                try
                {
                    // Pass 0: Collect infomation.
                    // Pass 1: Generate byte code.
                    DebugLogger.WriteLog("Compiling script in 2 passes.");

                    // Go over the source code in 2 passes.
                    for (int pass = 0; pass < 2; pass++)
                    {
                        _currentPass = pass;
                        _currentToken = null;
                        _tokenIndex = 0;
                        _currentScope = _globalScope;
                        _internalVariableIndex = 0; // This needs to be reset so statements using
                        // an internal variables can find them on the second pass.
                        while (!EndOfTokenStream())
                        {
                            try
                            {
                                ParseStatement();
                            }
                            catch (CompilePanicModeException)
                            {
                                DebugLogger.WriteLog("Panic mode initialized in script.");
                                // Don't do anything here, just allow the error to be
                                // forgoten and carry on as normal.
                            }

                            // If there are any errors quit compilation now.
                            if (_errorsOccured == true)
                                throw new CompileBreakException();
                        }
                    }

                    // Yell at user if no default state has been declared.
                    if (_defaultEngineState == null && (_compileFlags & CompileFlags.Library) == 0)
                        Error(ErrorCode.MissingDefaultState, "Default engine state is missing.");

                }
                catch (CompileBreakException)
                {
                    DebugLogger.WriteLog("Script compilation broken via CompileBreakException.");
                }

                // Check what errors occured.
                int fatalErrorCount = 0;
                int errorCount = 0;
                int warningCount = 0;
                int messageCount = 0;
                foreach (CompileError error in _errorList)
                {
                    switch (error.AlertLevel)
                    {
                        case ErrorAlertLevel.Error: errorCount++; break;
                        case ErrorAlertLevel.FatalError: fatalErrorCount++; break;
                        case ErrorAlertLevel.Message: messageCount++; break;
                        case ErrorAlertLevel.Warning: warningCount++; break;
                    }
                    DebugLogger.WriteLog(error.ToString(), LogAlertLevel.Warning);
                }

                DebugLogger.WriteLog("Script compiled with "+fatalErrorCount+" fatal errors, "+errorCount+" errors, "+warningCount+" warnings and "+messageCount+" messages.");

                // If there are any errors quit compilation now.
                if (_errorsOccured == true) return _errorList.Count;

                // Append an exit symbol onto the global scopes instruction list.
                CreateInstruction(OpCode.EXIT, _globalScope, _currentToken);

                DebugLogger.WriteLog("Optimizing and tweeking symbols and instructions.");

                // Compile symbol list.
                CompileSymbol(_globalScope);
                CompileSymbol(_memberScope);

                // Go through instruction list and replace placeholders with their values.
                int symbolIndex = 0;
                foreach (Symbol symbol in _compiledSymbolList)
                {
                    symbol.Index = symbolIndex;
                    symbolIndex++;

                    // Update the entry point if this is a function or event.
                    switch (symbol.Type)
                    {
                        case SymbolType.Function:
                            ((FunctionSymbol)symbol).EntryPoint = _compiledInstructionList.Count;
                            break;
                        case SymbolType.Variable:
                            bool check = true;
                            if (symbol.Scope.Type == SymbolType.Function)
                                if (((FunctionSymbol)symbol.Scope).IsImport == true) check = false;

                            // Should we remove it rather than warning?
                            if (((VariableSymbol)symbol).IsUsed == false && ((VariableSymbol)symbol).IsConstant == false && check == true)
                                Warning(ErrorCode.UnusedVariable, "Variable \"" + symbol.Identifier + "\" is declared but never used.");
                            break;
                    }

                    foreach (Instruction instruction in symbol.Instructions)
                    {
                        // Create a new debug file entry if this instruction
                        // was generated in a previously unknown file.
                        if (instruction.File != null && instruction.File != "")
                        {
                            bool found = false;
                            foreach (string file in _compiledDebugFileList)
                                if (file == instruction.File) found = true;
                            if (found == false) _compiledDebugFileList.Add(instruction.File);
                        }

                        // Go through each operand attach to this instruction
                        // and check for any trackers.
                        foreach (Operand operand in instruction.Operands)
                        {
                            if (operand == null) continue;

                            // Update operand based on type.
                            switch (operand.OpType)
                            {
                                case OperandType.JumpTarget:
                                    operand.OpType = OperandType.InstrIndex;
                                    switch (symbol.Type)
                                    {
                                        case SymbolType.Function:
                                            operand.InstrIndex = ((FunctionSymbol)symbol).EntryPoint + operand.JumpTarget.InstrIndex;
                                            break;
                                    }
                                    break;
                                case OperandType.SymbolIndexTracker:
                                    operand.OpType = OperandType.SymbolIndex;
                                    operand.SymbolIndex = _compiledSymbolList.IndexOf(operand.SymbolIndexTracker);
                                    break;
                            }
                        }
                        _compiledInstructionList.Add(instruction);
                    }
                }

                // Optimize this symbols instructions. (Currently somewhat error prone)
                //int instructionCount = _compiledInstructionList.Count;
                //ScriptOptimizer optimizer = new ScriptOptimizer();
                //optimizer.Optimize(_compiledInstructionList, _compiledSymbolList);
                //_compiledInstructionList = optimizer.OptimizedInstructions;
                //_compiledSymbolList = optimizer.OptimizedSymbols;

               // int index = 0;
                //foreach (Instruction instr in _compiledInstructionList)
                //{
                //    System.Console.WriteLine("\t"+instr.Decompile());
                //    index++;
                //}

            #if !DEBUG
            }
            catch (Exception)
            {
                _errorList.Add(new CompileError(ErrorCode.InternalError, "An internal compiler error occured.", ErrorAlertLevel.FatalError, 0, 0, ""));
            }
            #endif
            return _errorList.Count;
        }
Пример #13
0
 public Operand(Instruction instruction, Symbol symbol)
 {
     _opType = OperandType.SymbolIndexTracker;
     _symbolIndexTracker = symbol;
     instruction[instruction.OperandCount] = this;
 }
Пример #14
0
 /// <summary>
 ///		Initializes a new instance of this class and adds itself to 
 ///		the given scope's symbol list.
 /// </summary>
 /// <param name="scope">Scope that this symbol is in.</param>
 public NamespaceSymbol(Symbol scope)
 {
     _scope = scope;
     if (scope != null) scope.AddSymbol(this);
 }
Пример #15
0
 /// <summary>
 ///		Adds a symbol to this symbols scope.
 /// </summary>
 /// <param name="symbol">Symbol to add to this symbols scope.</param>
 public void AddSymbol(Symbol symbol)
 {
     symbol.Index = _symbolList.Count;
     _symbolList.Add(symbol);
 }
Пример #16
0
        /// <summary>
        ///		Parses a namespace declaration. 
        ///		Syntax:
        ///			"{" Block "}"
        /// </summary>
        private void ParseNamespace()
        {
            // Read in the identifier.
            ArrayList layers = new ArrayList();
            while (true)
            {
                ExpectToken(TokenID.TypeIdentifier);
                layers.Add(_currentToken.Ident);

                if (LookAheadToken().ID == TokenID.CharPeriod)
                    ExpectToken(TokenID.CharPeriod);
                else
                    break;
            }

            Symbol symbol = null;
            if (_currentPass == 0)
            {
                Symbol lastSymbol = _currentScope;
                foreach (String layer in layers)
                {
                    symbol = lastSymbol.FindSymbol(layer);
                    if (symbol == null)
                    {
                        symbol = new NamespaceSymbol(lastSymbol);
                        symbol.Identifier = layer;
                    }
                    lastSymbol = symbol;
                }
                symbol = lastSymbol;
            }
            else
            {
                Symbol lastSymbol = _currentScope;
                foreach (String layer in layers)
                    lastSymbol = lastSymbol.FindSymbol(layer);
                symbol = lastSymbol;
            }

            // Parse the namespaces block.
            Symbol scope = _currentScope;
            _currentScope = symbol;
            ParseStatement();
            _currentScope = scope;

            // And thats it! Simple huh?
        }
Пример #17
0
 /// <summary>
 ///		Initializes a new instance of this class and adds itself to 
 ///		the given scope's symbol list.
 /// </summary>
 /// <param name="scope">Scope that this symbol is in.</param>
 public VariableSymbol(Symbol scope)
 {
     if (scope == null) return;
     _scope = scope;
     scope.AddSymbol(this);
 }
Пример #18
0
        /// <summary>
        ///		Parses a state block. A state block is used to seperate events into specific
        ///		states to better emulate a state based machine.
        ///		Syntax:
        ///			"state" Identifier Statement
        /// </summary>
        private void ParseState()
        {
            // Make sure we are in a state's scope.
            if (_currentScope != _globalScope)
                Error(ErrorCode.InvalidScope, "States can only be declared within the global scope.", false, 0);

            // See if this is the engine or editor default state.
            bool isEngineDefault = false;
            bool isEditorDefault = false;
            int flagCount = 0;
            while (_currentToken.ID != TokenID.KeywordState && EndOfTokenStream() != true)
            {
                switch (_currentToken.ID)
                {
                    case TokenID.KeywordEngine:
                        if (_defaultEngineState != null) Error(ErrorCode.DuplicateDefault, "Default engine state declared multiple times.", false, 0);
                        if (isEngineDefault == true) Error(ErrorCode.DuplicateFlag, "\"" + _currentToken.Ident + "\" flag declared multiple times.", false, 0);
                        isEngineDefault = true;
                        break;

                    case TokenID.KeywordEditor:
                        if (_defaultEditorState != null) Error(ErrorCode.DuplicateDefault, "Default editor state declared multiple times.", false, 0);
                        if (isEditorDefault == true) Error(ErrorCode.DuplicateFlag, "\"" + _currentToken.Ident + "\" flag declared multiple times.", false, 0);
                        isEditorDefault = true;
                        break;
                }
                flagCount++;
                NextToken();
            }

            // Read in state keyword if there are previous flags.
            if (flagCount != 0) CheckToken(TokenID.KeywordState);

            // Validate the "state(Identifier)" section of the
            // the event declaration.
            ExpectToken(TokenID.TypeIdentifier);
            string stateIdent = _currentToken.Ident;

            // Create event's symbol.
            StateSymbol symbol = null;
            if (_currentPass == 0)
            {
                if (_currentScope.FindSymbol(stateIdent, SymbolType.State) != null)
                    Error(ErrorCode.DuplicateSymbol, "State \"" + stateIdent + "\" declared multiple times.", false, 0);
                symbol = new StateSymbol(_currentScope);
                symbol.Identifier = stateIdent;
                symbol.IsEngineDefault = isEngineDefault;
                symbol.IsEditorDefault = isEditorDefault;
                if (isEngineDefault == true)
                    _defaultEngineState = symbol;
                if (isEditorDefault == true)
                    _defaultEditorState = symbol;
            }
            else if (_currentPass == 1)
            {
                symbol = _currentScope.FindSymbol(stateIdent, SymbolType.State) as StateSymbol;
            }

            // Read in this event's contents.
            _lastMetaDataSymbol = symbol;
            Symbol scope = _currentScope;
            _currentScope = symbol;
            ParseStatement();
            _currentScope = scope;
        }
Пример #19
0
 /// <summary>
 ///		Initializes a new instruction and attachs it to the given scope.
 /// </summary>
 /// <param name="opCode">Operation code for this instruction.</param>
 /// <param name="scope">Scope this instruction should be added to.</param>
 /// <param name="token">Token to get debug infomation from.</param>
 public Instruction(OpCode opCode, Symbol scope, Token token)
 {
     scope.AddInstruction(this);
     _opCode = opCode;
     if (token != null)
     {
         _line = token.Line;
         _offset = token.Offset;
         _file = token.File;
     }
 }
Пример #20
0
 /// <summary>
 ///		Initializes a new jump target instance and adds itself to the given
 ///		scope's symbol list.
 /// </summary>
 /// <param name="scope">Scope that symbol is in.</param>
 public JumpTargetSymbol(Symbol scope)
 {
     _scope = scope;
     if (scope != null) _instrIndex = scope.Instructions.Count;
     if (scope != null) scope.AddSymbol(this);
 }