Пример #1
0
        //todo nullability
        //     type checking
        //     language consts (WORLD,SELF,SCRIPT)
        //     scope
        /// <summary>
        /// Parses a variable declaration
        /// </summary>
        /// <param name="at">position to start parsing in the ast</param>
        /// <returns>Declaration node</returns>
        private bool ParseVarDeclaration(ref int at)
        {
            DeclarationNode dNode = new DeclarationNode();

            //at 0 is always Signature.TYPENAME
            dNode.Variable.ValueNodeType = ValueNodeType.VARIABLE;
            string declTypeName = Ast[at].Word;

            at++;

            if (Ast[at].Signature != Signature.IDENTIFIER)
            {
                return(false);
            }

            //Search tree for existing declaration
            var varDecl = SeekVariableDeclarationWithName(Ast[at].Word, true);

            if (varDecl != null)
            {
                _logger.LogFatal("Redeclaration of variable");
                return(false);
            }
            dNode.Variable.VarName = Ast[at].Word;

            at++;

            if (Ast[at].Signature != Signature.OP_ASSIGN)
            {
                //not assignation case;
                _logger.LogFatal("Variable declaration without assignation");
                return(false);
            }

            //Right side value
            at++;

            switch (Ast[at].Signature)
            {
            case Signature.IDENTIFIER:
                //Search tree for existing declaration
                var r_varDecl = SeekVariableDeclarationWithName(Ast[at].Word);
                if (r_varDecl == null)
                {
                    _logger.LogFatal("No declaration of right side identifier");
                    goto default;
                }

                string varName = dNode.Variable.VarName;
                dNode.Variable         = r_varDecl.Variable;
                dNode.Variable.VarName = varName;
                break;

            case Signature.I_CONST:
            case Signature.F_CONST:
            case Signature.STRINGLITTERAL:
                dNode.Variable.ValueNodeType = ValueNodeType.CONSTLITERAL;
                dNode.Variable.IsNull        = false;
                bool badTypeflag = false;

                if (Ast[at].Signature == Signature.I_CONST)
                {
                    if (int.TryParse(Ast[at].Word, out int intValue) &&
                        declTypeName == "int")
                    {
                        dNode.Variable.Value     = intValue;
                        dNode.Variable.ValueType = TypesEnum.INT;
                    }
                    else
                    {
                        badTypeflag = true;
                    }
                }
                else if (Ast[at].Signature == Signature.F_CONST)
                {
                    if (float.TryParse(Ast[at].Word, out float floatValue) &&
                        declTypeName == "float")
                    {
                        dNode.Variable.Value     = floatValue;
                        dNode.Variable.ValueType = TypesEnum.FLOAT;
                    }
                    else
                    {
                        badTypeflag = true;
                    }
                }
                else /*STRINGLITTERAL*/   {
                    {
                        dNode.Variable.Value     = Ast[at].Word;
                        dNode.Variable.ValueType = TypesEnum.STRING;
                    }
                }

                if (badTypeflag)
                {
                    _logger.LogFatal("Mismatched type");
                }
                break;

            case Signature.KW_TRUE:
            case Signature.KW_FALSE:
                dNode.Variable.ValueNodeType = ValueNodeType.CONSTLITERAL;
                dNode.Variable.IsNull        = false;
                dNode.Variable.ValueType     = TypesEnum.BOOL;

                if (Ast[at].Signature == Signature.KW_TRUE)
                {
                    dNode.Variable.Value = true;
                }
                else if (Ast[at].Signature == Signature.KW_FALSE)
                {
                    dNode.Variable.Value = false;
                }
                break;

            case Signature.CONST_SELF:
            case Signature.CONST_WORLD:
            case Signature.CONST_SCRIPT:
                //Todo verify that the accessed const returns the valid type

                dNode.Variable.ValueNodeType = ValueNodeType.VARIABLE;
                dNode.Variable.IsNull        = true;
                break;

            case Signature.KW_NULL:
                dNode.Variable.ValueNodeType = ValueNodeType.CONSTLITERAL;
                dNode.Variable.IsNull        = true;
                dNode.Variable.ValueType     = TypesEnum.VOID;
                dNode.Variable.Value         = null;
                break;

            default:
                return(false);
            }

            at++;

            if (Ast[at].Signature != Signature.END)
            {
                return(false);
            }

            Tree.Current.AddChild(dNode);

            //TODO not best way of doing that
            Tree.VariableStack.Add(dNode);

            //TODO check that we return a valid position in the AST
            return(true);
        }
Пример #2
0
        private void ExtractTokens()
        {
            if (string.IsNullOrEmpty(Script))
            {
                Logger.LogFatal("Invalid Script file");
                return;
            }

            if (!AreOpenCloseStatementsPaired())
            {
                return;
            }


            for (int i = 0; i < Script.Length; i++)
            {
                switch (Script[i])
                {
                case ' ':
                case '\r':
                case '\n':
                case '\t':
                    break;

                case '(':
                    Tokens.Add(new Token()
                    {
                        Signature = Signature.LPAREN
                    });
                    break;

                case ')':
                    Tokens.Add(new Token()
                    {
                        Signature = Signature.RPAREN
                    });
                    break;

                case '{':
                    Tokens.Add(new Token()
                    {
                        Signature = Signature.LBRACE
                    });
                    break;

                case '}':
                    Tokens.Add(new Token()
                    {
                        Signature = Signature.RBRACE
                    });
                    break;

                case '[':
                    Tokens.Add(new Token()
                    {
                        Signature = Signature.LBRACKET
                    });
                    break;

                case ']':
                    Tokens.Add(new Token()
                    {
                        Signature = Signature.RBRACKET
                    });
                    break;

                case ',':
                    Tokens.Add(new Token()
                    {
                        Signature = Signature.COMMA
                    });
                    break;

                case '#':
                    Tokens.Add(new Token()
                    {
                        Signature = Signature.PREPROCESSOR
                    });
                    break;

                case ';':
                    Tokens.Add(new Token()
                    {
                        Signature = Signature.END
                    });
                    break;

                case '.':
                    Tokens.Add(new Token()
                    {
                        Signature = Signature.OP_DOT
                    });
                    break;

                case '>':
                    if (Script[i + 1] == '=')
                    {
                        Tokens.Add(new Token()
                        {
                            Signature = Signature.OP_GREATER_THAN_OR_EQUALS
                        });

                        i += 2;
                    }
                    else
                    {
                        Tokens.Add(new Token()
                        {
                            Signature = Signature.OP_GREATER_THAN
                        });
                    }
                    break;

                case '<':
                    if (IsNextIndexValid(i))
                    {
                        if (Script[i + 1] == '=')
                        {
                            Tokens.Add(new Token()
                            {
                                Signature = Signature.OP_LESS_THAN_OR_EQUALS
                            });

                            i += 2;
                        }
                        else
                        {
                            Tokens.Add(new Token()
                            {
                                Signature = Signature.OP_LESS_THAN
                            });
                        }
                    }
                    break;

                case '/':
                    if (IsNextIndexValid(i))
                    {
                        switch (Script[i + 1])
                        {
                        case '=':
                            Tokens.Add(new Token()
                            {
                                Signature = Signature.OP_DIVIDE_ASSIGN
                            });
                            i += 1;
                            break;

                        default:
                            Tokens.Add(new Token()
                            {
                                Signature = Signature.OP_DIVIDE
                            });
                            break;
                        }
                    }
                    break;

                case '*':
                    if (IsNextIndexValid(i))
                    {
                        switch (Script[i + 1])
                        {
                        case '=':
                            Tokens.Add(new Token()
                            {
                                Signature = Signature.OP_MUL_ASSIGN
                            });
                            i += 1;
                            break;

                        default:
                            Tokens.Add(new Token()
                            {
                                Signature = Signature.OP_MUL
                            });
                            break;
                        }
                    }
                    break;

                case '+':
                    if (IsNextIndexValid(i))
                    {
                        switch (Script[i + 1])
                        {
                        case '+':
                            Tokens.Add(new Token()
                            {
                                Signature = Signature.OP_INCREMENT
                            });
                            i += 1;
                            break;

                        case '=':
                            Tokens.Add(new Token()
                            {
                                Signature = Signature.OP_PLUS_ASSIGN
                            });
                            i += 1;
                            break;

                        default:
                            Tokens.Add(new Token()
                            {
                                Signature = Signature.OP_PLUS
                            });
                            break;
                        }
                    }
                    break;

                case '-':
                    if (IsNextIndexValid(i))
                    {
                        switch (Script[i + 1])
                        {
                        case '-':
                            Tokens.Add(new Token()
                            {
                                Signature = Signature.OP_DECREMENT
                            });
                            i += 1;
                            break;

                        case '=':
                            Tokens.Add(new Token()
                            {
                                Signature = Signature.OP_MINUS_ASSIGN
                            });
                            i += 1;
                            break;

                        default:
                            Tokens.Add(new Token()
                            {
                                Signature = Signature.OP_MINUS
                            });
                            break;
                        }
                    }
                    break;

                case '=':
                    if (IsNextIndexValid(i))
                    {
                        if (Script[i + 1] == '=')
                        {
                            Tokens.Add(new Token()
                            {
                                Signature = Signature.OP_EQUALS
                            });
                            i += 1;
                            if (IsNextIndexValid(i))
                            {
                                if (char.IsWhiteSpace(Script[i + 1]))
                                {
                                    i += 1;
                                }
                            }
                            break;
                        }
                        else
                        {
                            Tokens.Add(new Token()
                            {
                                Signature = Signature.OP_ASSIGN
                            });
                        }
                    }

                    break;

                case '!':
                    if (IsNextIndexValid(i))
                    {
                        if (Script[i + 1] == '=')
                        {
                            Tokens.Add(new Token()
                            {
                                Signature = Signature.OP_NOTEQUALS
                            });
                            i += 1;
                            break;
                        }
                        else
                        {
                            Tokens.Add(new Token()
                            {
                                Signature = Signature.OP_NOT
                            });
                        }
                    }

                    break;

                case '&':
                    if (IsNextIndexValid(i))
                    {
                        if (Script[i + 1] == '&')
                        {
                            Tokens.Add(new Token()
                            {
                                Signature = Signature.OP_AND
                            });
                            Console.WriteLine("returns at: " + (i + 2) + " char: " + Script[i + 2]);
                            i += 1;
                            break;
                        }
                        else
                        {
                            Logger.LogFatal("Invalid symbol");
                            return;
                        }
                    }
                    break;

                case '|':
                    if (IsNextIndexValid(i))
                    {
                        if (Script[i + 1] == '|')
                        {
                            Tokens.Add(new Token()
                            {
                                Signature = Signature.OP_OR
                            });
                            i += 1;
                            break;
                        }
                        else
                        {
                            Logger.LogFatal("Invalid symbol");
                            return;
                        }
                    }
                    break;

                case '"':
                    var word = new StringBuilder();
                    for (int j = i + 1; j < Script.Length; j++)
                    {
                        if (Script[j] == '"')
                        {
                            i = j;
                            break;
                        }
                        else
                        {
                            word.Append(Script[j]);
                        }
                    }

                    Tokens.Add(new Token()
                    {
                        Word      = word.ToString(),
                        Signature = Signature.STRINGLITTERAL
                    });
                    break;

                default:
                    if (char.IsDigit(Script[i]))
                    {
                        int numberScanResult = ScanNumber(i);

                        if (numberScanResult >= Script.Length ||
                            numberScanResult == -1)
                        {
                            return;
                        }
                        else
                        {
                            i = numberScanResult;
                        }
                    }
                    else if (char.IsLetter(Script[i]))
                    {
                        int identifierScanResult = ScanIdentifier(i);
                        if (identifierScanResult >= Script.Length)
                        {
                            return;
                        }
                        else
                        {
                            i = identifierScanResult;
                        }
                    }
                    else
                    {
                        Logger.LogFatal("Illegal char: " + Script[i]);
                        return;
                    }
                    break;
                }
            }
        }