Пример #1
0
        public Token(string str, string fileName, int lineIndex, int lineOffset, NmProgram program,
                     bool isString = false)
        {
            FileName    = fileName;
            LineIndex   = lineIndex;
            LineOffset  = lineOffset;
            StringValue = str;

            if (!isString)
            {
                if (!TokenDict.TryGetValue(str, out Type))
                {
                    if (LineIndex == -1)
                    {
                        Type = TokenType.Identifier;
                        return;
                    }

                    bool found = false;
                    foreach (var constantFormat in ConstantFormats)
                    {
                        if (constantFormat.Verify(StringValue))
                        {
                            Constant = constantFormat.Parse(this, program);

                            if (!constantFormat.VerifyBounds(Constant))
                            {
                                throw new CompileException(CompileErrorType.OutOfBoundsConstant, this);
                            }

                            Type  = Constant.ToTokenType();
                            found = true;
                            break;
                        }
                    }

                    if (!found)
                    {
                        if (IdentifierFormat.Match(StringValue))
                        {
                            Type = TokenType.Identifier;
                        }
                        else
                        {
                            throw new CompileException(CompileErrorType.WrongIdentifierFormat, this);
                        }
                    }
                }
            }
            else
            {
                var chars = new List <int>();
                CompileErrorType error;
                if ((error = StringFormat.CheckEscapeSymbols(StringValue, out chars)) != 0)
                {
                    throw new CompileException(error, this);
                }

                Constant = new Constant(this, program, chars);

                Type = TokenType.StringToken;
            }
        }
Пример #2
0
        private void ResolveLocals(BlockLexeme parent, out CompileError error, ref int index)
        {
            error = null;
            if (parent == null)
            {
                return;
            }

            foreach (var lexeme in parent.ChildLexemes)
            {
                if (lexeme.Type == LexemeType.Var)
                {
                    var varLexeme = (VarLexeme)lexeme;
                    if (!IdentifierFormat.Match(varLexeme.VarName.StringValue))
                    {
                        error = new CompileError(CompileErrorType.WrongIdentifierFormat, varLexeme.VarName);
                        return;
                    }

                    var varWithSameName = LocalVariables.Find(p => p.Name == varLexeme.VarName.StringValue);
                    if (varWithSameName != null)
                    {
                        if (HasInStack(parent, varWithSameName.Scope))
                        {
                            error = new CompileError(CompileErrorType.VariableRedeclaration, varLexeme.VarName);
                            return;
                        }
                    }

                    if (Program.ProgramGlobals.Find(p => p.Name == varLexeme.VarName.StringValue) != null)
                    {
                        error = new CompileError(CompileErrorType.VariableRedeclaration, varLexeme.VarName);
                        return;
                    }

                    Type t;
                    if ((error = Type.GetType(Program, varLexeme.TypeTokens, out t)) != null)
                    {
                        return;
                    }
                    LocalVariables.Add(new Variable(t, varLexeme.VarName.StringValue, parent.Scope, varLexeme.VarName, index++, VariableType.Variable));
                    varLexeme.Index = index - 1;
                }

                if (lexeme.RequireBlock)
                {
                    ResolveLocals(((ComplexLexeme)lexeme).Block, out error, ref index);
                    if (error != null)
                    {
                        return;
                    }
                }

                if (lexeme.Type == LexemeType.Block)
                {
                    ResolveLocals((BlockLexeme)lexeme, out error, ref index);
                    if (error != null)
                    {
                        return;
                    }
                }
            }
        }
        public static CompileError Parse(NmProgram program, bool prototypesOnly)
        {
            CompileError error;
            var          moduleLexeme = (ModuleLexeme)program.Lexemes.Find(p => p.Type == LexemeType.Module);

            if (moduleLexeme != null)
            {
                if (!IdentifierFormat.Match(moduleLexeme.ModuleName.StringValue))
                {
                    return(new CompileError(CompileErrorType.WrongModuleNameFormat, moduleLexeme.ModuleName));
                }

                program.IsModule = true;
                program.Module   = new Module(moduleLexeme.ModuleName.StringValue, program);
            }

            var attributes    = new List <Attribute>();
            var functionIndex = 0;

            foreach (var lex in program.Lexemes)
            {
                if (lex.Type == LexemeType.Function)
                {
                    var lexeme = (FunctionLexeme)lex;
                    if (!IdentifierFormat.Match(lexeme.Name.StringValue))
                    {
                        return(new CompileError(CompileErrorType.WrongFunctionNameFormat, lexeme.Name));
                    }

                    foreach (var parameter in lexeme.Parameters)
                    {
                        if (!IdentifierFormat.Match(parameter.Name.StringValue))
                        {
                            return(new CompileError(CompileErrorType.WrongFunctionParameterNameFormat, parameter.Name));
                        }
                    }

                    if (program.Functions.Count(p => p.Name == lexeme.Name.StringValue) != 0)
                    {
                        return(new CompileError(CompileErrorType.MultipleFunctionsWithSameName, lexeme.Name));
                    }

                    Function func;
                    if ((error = lexeme.ToFunc(program, out func)) != null)
                    {
                        return(error);
                    }

                    func.Index = functionIndex++;
                    program.Functions.Add(func);

                    func.Attributes = attributes.ToList();
                    attributes.Clear();

                    if (!prototypesOnly)
                    {
                        if ((error = program.Functions.Last().ResolveLexemes()) != null)
                        {
                            return(error);
                        }
                    }

                    if (lexeme.Modifier == FunctionModifier.Initialization)
                    {
                        if (program.Module.InitializationFunc != null)
                        {
                            return(new CompileError(CompileErrorType.MultipleInitializationFunctions, lexeme.Name));
                        }
                        program.Module.InitializationFunc = program.Functions.Last();
                    }

                    if (lexeme.Modifier == FunctionModifier.Finalization)
                    {
                        if (program.Module.FinalizationFunc != null)
                        {
                            return(new CompileError(CompileErrorType.MultipleFinalizationFunctions, lexeme.Name));
                        }
                        program.Module.FinalizationFunc = program.Functions.Last();
                    }

                    if (lexeme.Modifier == FunctionModifier.Entrypoint)
                    {
                        if (program.EntrypointFunction != null)
                        {
                            return(new CompileError(CompileErrorType.MultipleEntrypointFunctions, lexeme.Name));
                        }
                        program.EntrypointFunction = program.Functions.Last();
                    }
                }
                else if (lex.Type == LexemeType.Var)
                {
                    var lexeme = (VarLexeme)lex;
                    if (!IdentifierFormat.Match(lexeme.VarName.StringValue))
                    {
                        return(new CompileError(CompileErrorType.WrongIdentifierFormat, lexeme.VarName));
                    }

                    if (program.ProgramGlobals.Find(p => p.Name == lexeme.VarName.StringValue) != null)
                    {
                        return(new CompileError(CompileErrorType.VariableRedeclaration, lexeme.VarName));
                    }

                    Type t;
                    if ((error = Type.GetType(program, lexeme.TypeTokens, out t)) != null)
                    {
                        return(error);
                    }
                    program.ProgramGlobals.Add(new Variable(t, lexeme.VarName.StringValue, -1, lexeme.VarName, -1, VariableType.Variable));
                }
                else if (lex.Type == LexemeType.Import)
                {
                    var importName = (lex as ImportLexeme).ImportName.StringValue;

                    var matchedFile = program.Source.ModuleNames.Find(p => new FileInfo(p).Name == importName + ".nmm");
                    if (matchedFile == null)
                    {
                        return(new CompileError(CompileErrorType.UnknownModuleName, lex.Tokens?[0]));
                    }

                    Import import;
                    if ((error = Import.CreateImport(out import, importName, matchedFile, program, lex.Tokens[0])) != null)
                    {
                        return(error);
                    }

                    program.Imports.Add(import);

                    if ((error = import.Parse(program, lex.Tokens[0])) != null)
                    {
                        return(error);
                    }
                }
                else if (lex.Type == LexemeType.Module)
                {
                    program.IsModule = true;
                    program.Module   = new Module((lex as ModuleLexeme).ModuleName.StringValue, program)
                    {
                        IsLibrary = (lex as ModuleLexeme).IsLibrary
                    };
                }
                else if (lex.Type == LexemeType.Attribute)
                {
                    Attribute attribute;
                    if ((error = Attribute.CreateAttribute(lex.Tokens, out attribute)) != null)
                    {
                        return(error);
                    }

                    attributes.Add(attribute);
                }
                else
                {
                    return(new CompileError(CompileErrorType.UnexpectedLexeme, lex.Tokens?[0]));
                }
            }


            if (program.IsModule)
            {
                if (program.Module.InitializationFunc == null)
                {
                    return(new CompileError(CompileErrorType.NoInitializationFunction, new Token(program.Source.FileName)));
                }
                if (program.Module.FinalizationFunc == null)
                {
                    return(new CompileError(CompileErrorType.NoFinalizationFunction, new Token(program.Source.FileName)));
                }
                if (program.EntrypointFunction != null)
                {
                    return(new CompileError(CompileErrorType.ModuleWithEntrypointFunction, new Token(program.Source.FileName)));
                }
            }
            else
            {
                if (program.EntrypointFunction == null)
                {
                    return(new CompileError(CompileErrorType.NoEntrypointFunction, new Token(program.Source.FileName)));
                }
            }

            return(null);
        }