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; } }
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); }