/// <summary>Creates a new string fragment by reading it from the given lexer.</summary>
		/// <param name="sr">The lexer to read it from.</param>
		public StringFragment(CodeLexer sr){
			sr.Literal=true;
			// Read off the quote:
			char Quote=sr.Read();
			char Char=sr.Read();
			bool Delimited=false;
			
			while( Delimited || Char!=Quote && Char!=StringReader.NULL){
				
				if(Char=='\\'&&!Delimited){
					Delimited=true;
				}else{
					Delimited=false;
					Value+=Char;
				}
				
				Char=sr.Read();
			}
			
			sr.Literal=false;
			
			// Read off any junk after the quote:
			while(sr.ReadJunk()){
				sr.DidReadJunk=true;
			}
			
			if(Char==StringReader.NULL){
				Error("Unterminated string found.");
			}
		}
		/// <summary>Creates a new type fragment by reading it from the given lexer.</summary>
		/// <param name="sr">The lexer to read it from.</param>
		/// <param name="hasColon">True if a colon (:) should be read from the lexer.</param>
		public TypeFragment(CodeLexer sr,bool hasColon){
			HasColon=hasColon;
			if(HasColon){
				// Read off the colon:
				sr.Read();
			}
			// Read until some other block can take over:
			while(true){
				char peek=sr.Peek();
				if(peek=='<'){
					List<TypeFragment> generics=new List<TypeFragment>();
					while(true){
						// Read off the < or the comma:
						sr.Read();
						generics.Add(new TypeFragment(sr,false));
						if(sr.Peek()=='>'){
							sr.Read();
							GenericSet=generics.ToArray();
							break;
						}
					}
					if(sr.Peek()=='['){
						SetArray(sr);
					}
					break;
				}else if(peek=='['){
					SetArray(sr);
					break;
				}else if(peek==','||peek==';'||peek==StringReader.NULL||BracketFragment.AnyBracket(peek)||Operator.IsOperator(peek)){
					// Pass control back to the operation:
					break;
				}
				Value+=char.ToLower(sr.Read());
			}
		}
		/// <summary>Creates and reads a new if(){} fragment. Note that the else section is not read.</summary>
		/// <param name="sr">The lexer to read the if condition and its true bracket block from.</param>
		public IfFragment(CodeLexer sr){
			ApplyElseTo=this;
			Condition=new BracketFragment(sr);
			IfTrue=new BracketFragment(sr);
			
			// Add them as children such that code tree iterators can visit them:
			AddChild(Condition);
			AddChild(IfTrue);
			
		}
		/// <summary>Creates and reads a new for/while loop fragment.</summary>
		/// <param name="sr">The lexer to read the loop content from.</param>
		/// <param name="name">This class represents while too. This is the name of the loop; either 'for' or 'while'.</param>
		public ForFragment(CodeLexer sr,string name){
			Value=name;
			Parameters=new BracketFragment(sr);
			Body=new BracketFragment(sr);
			
			// Add them as children such that code tree iterators can visit them:
			AddChild(Parameters);
			AddChild(Body);
			
		}
		public override AddResult AddTo(CodeFragment to,CodeLexer sr){
			if(to.LastChild==null){
				Error("A property (."+Value+") was found in an unexpected place.");
			}
			// Replace the last child with *THIS*:
			of=to.LastChild;
			of.Remove();
			to.AddChild(this);
			return AddResult.Ok;
		}
		/// <summary>Creates a new operator by reading one from given the lexer.</summary>
		/// <param name="sr">The lexer to read the operator from.</param>
		public OperatorFragment(CodeLexer sr){
			char operatorChar=sr.Read();
			// First check if this character plus the next one makes a valid operator (e.g. +=):
			char peek=sr.Peek();
			if(peek!=StringReader.NULL&&Set(""+operatorChar+peek)){
				// Yes it does - Make it official by reading it off:
				sr.Read();
				// We called set in the if so don't do it again:
				return;
			}
			
			Set(""+operatorChar);
		}
		public override AddResult AddTo(CodeFragment to,CodeLexer sr){
			if(MethodName.GetType()==typeof(VariableFragment)){
				VariableFragment vfrag=(VariableFragment)MethodName;
				if(vfrag.Value=="new"){
					CodeFragment p=to.LastChild;
					if(p==null||p.GetType()!=typeof(VariableFragment)||((VariableFragment)p).Value!="function"){
						// Constructor call.
						vfrag.Remove();
						return new ConstructorFragment(vfrag.GivenType,Brackets).AddTo(to,sr);
					}
				}
			}
			return base.AddTo(to,sr);
		}
Example #8
0
        /// <summary>Creates a new operator by reading one from given the lexer.</summary>
        /// <param name="sr">The lexer to read the operator from.</param>
        public OperatorFragment(CodeLexer sr)
        {
            char operatorChar = sr.Read();
            // First check if this character plus the next one makes a valid operator (e.g. +=):
            char peek = sr.Peek();

            if (peek != StringReader.NULL && Set("" + operatorChar + peek))
            {
                // Yes it does - Make it official by reading it off:
                sr.Read();
                // We called set in the if so don't do it again:
                return;
            }

            Set("" + operatorChar);
        }
		/// <summary>Creates a new BracketFragment.</summary>
		/// <param name="sr">The lexer to read the bracket content from.</param>
		/// <param name="readBracket">True if the brackets should be read off (i.e. the first thing done is read a single character). False otherwise.</param>
		public BracketFragment(CodeLexer sr,bool readBracket){
			
			if(readBracket){
				int type=IsBracket(sr.Read());
				
				if(type==-1){
					
					// Seek back just one - we want to re-read the thing we just tested for bracketness:
					sr.Position--;
					
					// No bracket; their implicit - read single operation:
					AddChild(new OperationFragment(sr,this));
					
					// And stop there:
					return;
					
				}else{
					
					// Grab the brackets:
					Bracket=Brackets[type];
					CloseBracket=EndBrackets[type];
				
				}
				
			}
			
			char peek=sr.Peek();
			bool bracket=(IsEndBracket(peek)!=-1);
			
			while(peek!=StringReader.NULL && !bracket){
				
				// Add the operation:
				AddChild(new OperationFragment(sr,this));
				
				// What's next?
				peek=sr.Peek();
				
				// Is it a bracket?
				bracket=(IsEndBracket(peek)!=-1);
			}
			
			if(bracket){
				// Read the last bracket off:
				sr.Read();
			}
			
		}
Example #10
0
 /// <summary>Creates a new type fragment by reading it from the given lexer.</summary>
 /// <param name="sr">The lexer to read it from.</param>
 /// <param name="hasColon">True if a colon (:) should be read from the lexer.</param>
 public TypeFragment(CodeLexer sr, bool hasColon)
 {
     HasColon = hasColon;
     if (HasColon)
     {
         // Read off the colon:
         sr.Read();
     }
     // Read until some other block can take over:
     while (true)
     {
         char peek = sr.Peek();
         if (peek == '<')
         {
             List <TypeFragment> generics = new List <TypeFragment>();
             while (true)
             {
                 // Read off the < or the comma:
                 sr.Read();
                 generics.Add(new TypeFragment(sr, false));
                 if (sr.Peek() == '>')
                 {
                     sr.Read();
                     GenericSet = generics.ToArray();
                     break;
                 }
             }
             if (sr.Peek() == '[')
             {
                 SetArray(sr);
             }
             break;
         }
         else if (peek == '[')
         {
             SetArray(sr);
             break;
         }
         else if (peek == ',' || peek == ';' || peek == StringReader.NULL || BracketFragment.AnyBracket(peek) || Operator.IsOperator(peek))
         {
             // Pass control back to the operation:
             break;
         }
         Value += char.ToLower(sr.Read());
     }
 }
Example #11
0
 /// <summary>Reads array indices (array[,,,] = 3 dimensions) from the given lexer and sets the dimensions from the number of them.</summary>
 /// <param name="sr">The lexer to read the indices from.</param>
 private void SetArray(CodeLexer sr)
 {
     IsArray = true;
     // Read off the [ :
     sr.Read();
     while (sr.Peek() != ']')
     {
         Dimensions++;
         char C = sr.Read();
         if (C != ',')
         {
             Error("Bad array type (" + ToString() + "). myArray:String[]=new String[](40); or myArray:String[]=new String[]{\"V1\",\"V2\"}; is the correct syntax.");
         }
     }
     // read off the ] :
     sr.Read();
 }
Example #12
0
        /// <summary>Creates a new BracketFragment.</summary>
        /// <param name="sr">The lexer to read the bracket content from.</param>
        /// <param name="readBracket">True if the brackets should be read off (i.e. the first thing done is read a single character). False otherwise.</param>
        public BracketFragment(CodeLexer sr, bool readBracket)
        {
            if (readBracket)
            {
                int type = IsBracket(sr.Read());

                if (type == -1)
                {
                    // Seek back just one - we want to re-read the thing we just tested for bracketness:
                    sr.Position--;

                    // No bracket; their implicit - read single operation:
                    AddChild(new OperationFragment(sr, this));

                    // And stop there:
                    return;
                }
                else
                {
                    // Grab the brackets:
                    Bracket      = Brackets[type];
                    CloseBracket = EndBrackets[type];
                }
            }

            char peek    = sr.Peek();
            bool bracket = (IsEndBracket(peek) != -1);

            while (peek != StringReader.NULL && !bracket)
            {
                // Add the operation:
                AddChild(new OperationFragment(sr, this));

                // What's next?
                peek = sr.Peek();

                // Is it a bracket?
                bracket = (IsEndBracket(peek) != -1);
            }

            if (bracket)
            {
                // Read the last bracket off:
                sr.Read();
            }
        }
		/// <summary>Creates a property fragment by reading it from the given lexer.</summary>
		/// <param name="sr">The lexer to read the fragment from.</param>
		public PropertyFragment(CodeLexer sr){
			// Skip the dot:
			sr.Read();
			// Read a 'variable':
			Value+=char.ToLower(sr.Read());
			while(true){
				char peek=sr.Peek();	
				if(peek==';'||peek==','||peek=='.'||peek==StringReader.NULL||BracketFragment.AnyBracket(peek)){
					// Pass control back to the operation:
					break;
				}
				Handler handle=Handlers.Find(peek);
				if(handle!=Handler.Stop&&handle!=Handler.Variable&&handle!=Handler.Number&&handle!=Handler.Property){
					break;
				}
				Value+=char.ToLower(sr.Read());
			}
		}
 public override AddResult AddTo(CodeFragment to, CodeLexer sr)
 {
     if (MethodName.GetType() == typeof(VariableFragment))
     {
         VariableFragment vfrag = (VariableFragment)MethodName;
         if (vfrag.Value == "new")
         {
             CodeFragment p = to.LastChild;
             if (p == null || p.GetType() != typeof(VariableFragment) || ((VariableFragment)p).Value != "function")
             {
                 // Constructor call.
                 vfrag.Remove();
                 return(new ConstructorFragment(vfrag.GivenType, Brackets).AddTo(to, sr));
             }
         }
     }
     return(base.AddTo(to, sr));
 }
		/// <summary>Reads a code fragment from the code using a known handler.</summary>
		/// <param name="handle">The handler to use.</param>
		/// <param name="sr">The raw code stream</param>
		/// <returns>A new code fragment, or null if told to stop with Handler.Stop.</returns>
		public static CodeFragment Handle(Handler handle,CodeLexer sr){
			if(handle==Handler.Brackets){
				return new BracketFragment(sr);
			}else if(handle==Handler.String){
				return new StringFragment(sr);
			}else if(handle==Handler.Type){
				return new TypeFragment(sr);
			}else if(handle==Handler.Operator){
				return new OperatorFragment(sr);
			}else if(handle==Handler.Number){
				return new NumberFragment(sr);
			}else if(handle==Handler.Variable){
				return new VariableFragment(sr);
			}else if(handle==Handler.Property){
				return new PropertyFragment(sr);
			}else{
				return null;
			}
		}
 /// <summary>Creates a property fragment by reading it from the given lexer.</summary>
 /// <param name="sr">The lexer to read the fragment from.</param>
 public PropertyFragment(CodeLexer sr)
 {
     // Skip the dot:
     sr.Read();
     // Read a 'variable':
     Value += char.ToLower(sr.Read());
     while (true)
     {
         char peek = sr.Peek();
         if (peek == ';' || peek == ',' || peek == '.' || peek == StringReader.NULL || BracketFragment.AnyBracket(peek))
         {
             // Pass control back to the operation:
             break;
         }
         Handler handle = Handlers.Find(peek);
         if (handle != Handler.Stop && handle != Handler.Variable && handle != Handler.Number && handle != Handler.Property)
         {
             break;
         }
         Value += char.ToLower(sr.Read());
     }
 }
		/// <summary>Creates a new variable fragment by reading it from the given lexer.</summary>
		/// <param name="sr">The lexer to read the variable from.</param>
		public VariableFragment(CodeLexer sr){
			Value+=char.ToLower(sr.Read());
			
			// Read until some other block can take over:
			while(true){
				char peek=sr.Peek();	
				if(peek==';'||peek==','||peek==StringReader.NULL||BracketFragment.AnyBracket(peek)){
					// Pass control back to the operation:
					break;
				}
				
				if(sr.PeekJunk()){
					// Is Value anything special?
					if(Value=="var"){
						break;
					}else if(Value=="private"){
						break;
					}else if(Value=="function"){
						break;
					}else if(Value=="class"){
						break;
					}else if(Value=="new"){
						GivenType=new TypeFragment(sr,false);
						break;
					}else if(IsKeyword()){
						break;
					}
				}
				
				Handler handle=Handlers.Find(peek);
				
				if(handle!=Handler.Stop&&handle!=Handler.Variable&&handle!=Handler.Number){
					break;
				}
				
				Value+=char.ToLower(sr.Read());
			}
			
		}
		/// <summary>Reads a new number fragment from the given lexer.</summary>
		/// <param name="sr">The lexer to read the number from.</param>
		public NumberFragment(CodeLexer sr){
			int index=IsOfType(Number,sr.Peek());
			while(index!=-1){
				Value+=sr.Read();
				if(index==0){
					// Got a dot in it - must be a float.
					Float=true;
				}
				char peek=sr.Peek();
				if(peek=='f'){
					Float=true;
					sr.Read();
					return;
				}else if(peek=='H'&&sr.Peek(1)=='z'){
					Float=true;
					sr.Read();
					sr.Read();
					return;
				}else{
					index=IsOfType(Number,peek);
				}
			}
		}
        /// <summary>Creates a new string fragment by reading it from the given lexer.</summary>
        /// <param name="sr">The lexer to read it from.</param>
        public StringFragment(CodeLexer sr)
        {
            sr.Literal = true;
            // Read off the quote:
            char Quote     = sr.Read();
            char Char      = sr.Read();
            bool Delimited = false;

            while (Delimited || Char != Quote && Char != StringReader.NULL)
            {
                if (Char == '\\' && !Delimited)
                {
                    Delimited = true;
                }
                else
                {
                    Delimited = false;
                    Value    += Char;
                }

                Char = sr.Read();
            }

            sr.Literal = false;

            // Read off any junk after the quote:
            while (sr.ReadJunk())
            {
                sr.DidReadJunk = true;
            }

            if (Char == StringReader.NULL)
            {
                Error("Unterminated string found.");
            }
        }
		/// <summary>Reads array indices (array[,,,] = 3 dimensions) from the given lexer and sets the dimensions from the number of them.</summary>
		/// <param name="sr">The lexer to read the indices from.</param>
		private void SetArray(CodeLexer sr){
			IsArray=true;
			// Read off the [ :
			sr.Read();
			while(sr.Peek()!=']'){
				Dimensions++;
				char C=sr.Read();
				if(C!=','){
					Error("Bad array type ("+ToString()+"). myArray:String[]=new String[](40); or myArray:String[]=new String[]{\"V1\",\"V2\"}; is the correct syntax.");
				}
			}
			// read off the ] :
			sr.Read();
		}
		public override AddResult AddTo(CodeFragment to,CodeLexer sr){
			if(Bracket=='['){
				
				if(to.LastChild==null){
					Error("Unexpected indexing. must be something[index].");
				}else{
					CodeFragment var=to.LastChild;
					var.Remove();
					
					return new IndexFragment(this,var).AddTo(to,sr);
				}
				
			}else if(Bracket=='{'&&to.LastChild!=null){
				// new TYPE[]{default,default..};
				
				if(to.LastChild.GetType()==typeof(VariableFragment)&&((VariableFragment)(to.LastChild)).Value=="new"){
					VariableFragment var=(VariableFragment)(to.LastChild);
					
					if(var.GivenType==null){
						Error("new must always be followed by a type name.");
					}else if(!var.GivenType.IsArray){
						Error("new Type{} only works when Type is an array and curley brackets define it's default values e.g. new int[]{1,2}");
					}else{
						var.Remove();
						return new ArrayFragment(var.GivenType,this).AddTo(to,sr);
					}
					
				}
				
			}else if(Bracket=='('&&to.LastChild!=null){
				Type type=to.LastChild.GetType();
				
				if(type==typeof(IndexFragment)||type==typeof(PropertyFragment)||(type==typeof(VariableFragment)&&!((VariableFragment)(to.LastChild)).IsKeyword())){
					// Method call!
					CodeFragment meth=to.LastChild;
					meth.Remove();
					
					return new MethodFragment(this,meth).AddTo(to,sr);
				}
				
			}
			
			return base.AddTo(to,sr);
		}
		/// <summary>Creates a new BracketFragment.</summary>
		/// <param name="sr">The lexer to read the bracket content from.</param>
		public BracketFragment(CodeLexer sr):this(sr,true){}
Example #23
0
        /// <summary>Compiles the given code now deriving from the given object.</summary>
        /// <param name="code">The code to compile</param>
        /// <param name="baseType">The type to inherit from. If null, the code will inherit from the default Script type.</param>
        /// <param name="aotFile">A DLL path to write the compiled code to (For e.g. AOT compilation).</param>
        public void Compile(string code, Type baseType, string aotFile, string aotAssemblyName)
        {
            Code = code;
            if (baseType == null)
            {
                baseType = typeof(Script);
            }

            // Are we compiling to a file?
            string aotFilename  = "";
            string assemblyPath = null;
            bool   aot          = !string.IsNullOrEmpty(aotFile);

            // The assembly name:
            AssemblyName assemblyName = null;

            if (aot)
            {
                // Grab the file name (used below too):
                aotFilename = System.IO.Path.GetFileName(aotFile);
                // Setup the assembly name:
                assemblyName = new AssemblyName(aotAssemblyName);
            }
            else
            {
                assemblyName = new AssemblyName("$SS_" + ModuleCounter);
            }

            // Assembly access:
            AssemblyBuilderAccess access = AssemblyBuilderAccess.Run;

            if (aot)
            {
                // We're ahead-of-time compiling this to a file.

                // Grab the directory the file must go in:
                assemblyPath = System.IO.Path.GetDirectoryName(aotFile);

                if (assemblyPath != null)
                {
                    if (!Directory.Exists(assemblyPath))
                    {
                        Directory.CreateDirectory(assemblyPath);
                    }
                }

                access = AssemblyBuilderAccess.Save;
            }

            // Create the assembly builder. If we're AOT compiling, it's saveable.
            AssemblyBuilder assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, access, assemblyPath);

            if (aot)
            {
                // Create the module:
                Builder = assemblyBuilder.DefineDynamicModule("SS-DMOD", aotFilename);
            }
            else
            {
                Builder = assemblyBuilder.DefineDynamicModule("SS-DMOD");
            }

            ModuleCounter++;

            // Ok - let's start compiling. Define a base class that all code goes into:
            BaseClass = new CompiledClass();

            // That class will be known as..
            BaseClass.StartType("NitroScriptCode", this, baseType);

            // Start parsing the code into a tree of fragments:
            CodeLexer sr = new CodeLexer(Code);

            BaseClass.ClassFragment = new BaseFragment(sr);

            // Search the fragments for any classes:
            FindClasses(BaseClass.ClassFragment);

            // Compile the classes we found:
            foreach (KeyValuePair <string, CompiledClass> kvp in Types)
            {
                kvp.Value.Compile();
            }

            // Compile the base class:
            BaseClass.Compile();
            CompiledType = BaseClass.compiledType;
            Types        = null;
            BaseClass    = null;

                        #if !UNITY_WEBPLAYER
            if (aot)
            {
                // Great - overwrite it.
                if (File.Exists(aotFile))
                {
                    if (OnAotFileExists == null)
                    {
                        File.Delete(aotFile);
                    }
                    else
                    {
                        OnAotFileExists(aotFile);
                    }
                }

                assemblyBuilder.Save(aotFilename);
            }
                        #endif
        }
Example #24
0
 public override AddResult AddTo(CodeFragment to, CodeLexer sr)
 {
     base.AddTo(to, sr);
     return(AddResult.Stop);
 }
		/// <summary>Creates a new type fragment by reading it and a preceeding colon from the given lexer.</summary>
		/// <param name="sr">The lexer to read from.</param>
		public TypeFragment(CodeLexer sr):this(sr,true){}
		public override AddResult AddTo(CodeFragment to,CodeLexer sr){
			
			if(Value==""){
				return AddResult.Ok;
			}else if(Value=="var"){
				
				// We're reading a local:
				return AddResult.Local;
				
			}else if(Value=="for" || Value=="while"){
				return new ForFragment(sr,Value).AddTo(to,sr);
			}else if(Value=="switch"){
				return new SwitchFragment(sr).AddTo(to,sr);
			}else if(Value=="if"){
				return new IfFragment(sr).AddTo(to,sr);
			}else if(Value=="else"){
				CodeFragment previous=to.ParentFragment;
				
				// Parent->prev operation->last object. Should be an IF.
				
				if(previous==null||((previous=previous.LastChild)==null)||((previous=previous.LastChild)==null)||previous.GetType()!=typeof(IfFragment)){
					Error("Else can only be applied to an if. E.g. if(){}else{}.");
				}
				
				IfFragment ifFrag=(IfFragment)previous;
				
				ifFrag.ApplyElseTo.SetIfFalse(new BracketFragment(sr));
				
				return AddResult.Stop;
			}else if(Value=="elseif"){
				CodeFragment previous=to.ParentFragment;
				// Parent->prev operation->last object. Should be an IF.
				
				if(previous==null||((previous=previous.LastChild)==null)||((previous=previous.LastChild)==null)||previous.GetType()!=typeof(IfFragment)){
					Error("Else if can only be applied to an if. E.g. if(){}else if{}..");
				}
				
				IfFragment ifFrag=(IfFragment)previous;
				IfFragment newfrag=new IfFragment(sr);
				
				 BracketFragment bf=new BracketFragment();
				  OperationFragment op=new OperationFragment();
				  op.AddChild(newfrag);
				 bf.AddChild(op);
				
				ifFrag.ApplyElseTo.SetIfFalse(bf);
				ifFrag.ApplyElseTo=newfrag;
				
				return AddResult.Stop;
				
			}else{
				return base.AddTo(to,sr);
			}
			
		}
		/// <summary>Reads a new operation from the given lexer.</summary>
		/// <param name="sr">The lexer to read the operation from.</param>
		/// <param name="parent">The fragment to parent the operation to.</param>
		public OperationFragment(CodeLexer sr,CodeFragment parent){
			ParentFragment=parent;
			LineNumber=sr.LineNumber;
			bool localMode=false;
			
			while(true){
				char peek=sr.Peek();
				
				if(peek==StringReader.NULL){
					return;
				}
				
				if(peek==';'||peek==','){
					// Read it off:
					sr.Read();
					return;
				}
				
				Handler handler=Handlers.Find(peek);
				
				if(handler==Handler.Stop){
					return;
				}
				
				// Handle the fragment:
				CodeFragment fragment;
				
				try{
					
					// Try to get the code fragment:
					fragment=Handlers.Handle(handler,sr);
					
				}catch(CompilationException e){
					
					if(e.LineNumber==-1){
						// Setup line number:
						e.LineNumber=LineNumber;
					}
					
					// Rethrow:
					throw e;
				}
				
				if(localMode){
					
					// Should always be a VariableFragment:
					
					if(fragment.GetType()==typeof(VariableFragment)){
						
						VariableFragment local=(VariableFragment)fragment;
						local.AfterVar=true;
						
					}
					
					localMode=false;
				}
				
				// Try adding the fragment to the operation:
				AddResult status=fragment.AddTo(this,sr);
				
				// What was the outcome?
				switch(status){
					case AddResult.Stop:
						// Halt.
						return;
					case AddResult.Local:
						// Local next:
						localMode=true;
					break;
					// Ok otherwise.
				}
				
			}
		}
Example #28
0
 public BaseFragment(CodeLexer sr) : base(sr, false)
 {
 }
		/// <summary>Creates and reads a new switch fragment.</summary>
		/// <param name="sr">The lexer to read the switch content from.</param>
		public SwitchFragment(CodeLexer sr){
			Parameters=new BracketFragment(sr);
			Body=new BracketFragment(sr);
		}
		/// <summary>Adds this fragment as a child to the given fragment.
		/// It may be overriden by some types of fragment as they may wish to handle it differently.</summary>
		/// <param name="to">The parent to add this fragment to.</param>
		/// <param name="sr">The lexer containing the original text code.</param>
		public virtual AddResult AddTo(CodeFragment to,CodeLexer sr){
			to.AddChild(this);
			return AddResult.Ok;
		}
Example #31
0
 /// <summary>Creates and reads a new switch fragment.</summary>
 /// <param name="sr">The lexer to read the switch content from.</param>
 public SwitchFragment(CodeLexer sr)
 {
     Parameters = new BracketFragment(sr);
     Body       = new BracketFragment(sr);
 }
Example #32
0
//--------------------------------------
Example #33
0
 /// <summary>Creates a new BracketFragment.</summary>
 /// <param name="sr">The lexer to read the bracket content from.</param>
 public BracketFragment(CodeLexer sr) : this(sr, true)
 {
 }
 /// <summary>Adds this fragment as a child to the given fragment.
 /// It may be overriden by some types of fragment as they may wish to handle it differently.</summary>
 /// <param name="to">The parent to add this fragment to.</param>
 /// <param name="sr">The lexer containing the original text code.</param>
 public virtual AddResult AddTo(CodeFragment to, CodeLexer sr)
 {
     to.AddChild(this);
     return(AddResult.Ok);
 }
		/// <summary>Compiles the given code now deriving from the given object.</summary>
		/// <param name="code">The code to compile</param>
		/// <param name="baseType">The type to inherit from. If null, the code will inherit from the default Script type.</param>
		/// <param name="aotFile">A DLL path to write the compiled code to (For e.g. AOT compilation).</param>
		public void Compile(string code,Type baseType,string aotFile,string aotAssemblyName){
			Code=code;
			if(baseType==null){
				baseType=typeof(Script);
			}
			
			// Are we compiling to a file?
			string aotFilename="";
			string assemblyPath=null;
			bool aot=!string.IsNullOrEmpty(aotFile);
			
			// The assembly name:
			AssemblyName assemblyName=null;
			
			if(aot){
				// Grab the file name (used below too):
				aotFilename=System.IO.Path.GetFileName(aotFile);
				// Setup the assembly name:
				assemblyName=new AssemblyName(aotAssemblyName);
			}else{
				assemblyName=new AssemblyName("$SS_"+ModuleCounter);
			}
			
			// Assembly access:
			AssemblyBuilderAccess access=AssemblyBuilderAccess.Run;
			
			if(aot){
				// We're ahead-of-time compiling this to a file.
				
				// Grab the directory the file must go in:
				assemblyPath=System.IO.Path.GetDirectoryName(aotFile);
				
				if(assemblyPath!=null){
					if(!Directory.Exists(assemblyPath)){
						Directory.CreateDirectory(assemblyPath);
					}
				}
				
				access=AssemblyBuilderAccess.Save;
			}
			
			// Create the assembly builder. If we're AOT compiling, it's saveable.
			AssemblyBuilder assemblyBuilder=AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName,access,assemblyPath);
			
			if(aot){
				// Create the module:
				Builder=assemblyBuilder.DefineDynamicModule("SS-DMOD",aotFilename);
			}else{
				Builder=assemblyBuilder.DefineDynamicModule("SS-DMOD");
			}
			
			ModuleCounter++;
			
			// Ok - let's start compiling. Define a base class that all code goes into:
			BaseClass=new CompiledClass();
			
			// That class will be known as..
			BaseClass.StartType("NitroScriptCode",this,baseType);
			
			// Start parsing the code into a tree of fragments:
			CodeLexer sr=new CodeLexer(Code);
			BaseClass.ClassFragment=new BaseFragment(sr);
			
			// Search the fragments for any classes:
			FindClasses(BaseClass.ClassFragment);
			
			// Compile the classes we found:
			foreach(KeyValuePair<string,CompiledClass>kvp in Types){
				kvp.Value.Compile();
			}
			
			// Compile the base class:
			BaseClass.Compile();
			CompiledType=BaseClass.compiledType;
			Types=null;
			BaseClass=null;
			
			if(aot){
				// Great - overwrite it.
				if(File.Exists(aotFile)){
					if(OnAotFileExists==null){
						File.Delete(aotFile);
					}else{
						OnAotFileExists(aotFile);
					}
				}
				
				assemblyBuilder.Save(aotFilename);
			}
		}
        public override AddResult AddTo(CodeFragment to, CodeLexer sr)
        {
            if (Value == "")
            {
                return(AddResult.Ok);
            }
            else if (Value == "var")
            {
                // We're reading a local:
                return(AddResult.Local);
            }
            else if (Value == "for" || Value == "while")
            {
                return(new ForFragment(sr, Value).AddTo(to, sr));
            }
            else if (Value == "switch")
            {
                return(new SwitchFragment(sr).AddTo(to, sr));
            }
            else if (Value == "if")
            {
                return(new IfFragment(sr).AddTo(to, sr));
            }
            else if (Value == "else")
            {
                CodeFragment previous = to.ParentFragment;

                // Parent->prev operation->last object. Should be an IF.

                if (previous == null || ((previous = previous.LastChild) == null) || ((previous = previous.LastChild) == null) || previous.GetType() != typeof(IfFragment))
                {
                    Error("Else can only be applied to an if. E.g. if(){}else{}.");
                }

                IfFragment ifFrag = (IfFragment)previous;

                ifFrag.ApplyElseTo.SetIfFalse(new BracketFragment(sr));

                return(AddResult.Stop);
            }
            else if (Value == "elseif")
            {
                CodeFragment previous = to.ParentFragment;
                // Parent->prev operation->last object. Should be an IF.

                if (previous == null || ((previous = previous.LastChild) == null) || ((previous = previous.LastChild) == null) || previous.GetType() != typeof(IfFragment))
                {
                    Error("Else if can only be applied to an if. E.g. if(){}else if{}..");
                }

                IfFragment ifFrag  = (IfFragment)previous;
                IfFragment newfrag = new IfFragment(sr);

                BracketFragment   bf = new BracketFragment();
                OperationFragment op = new OperationFragment();
                op.AddChild(newfrag);
                bf.AddChild(op);

                ifFrag.ApplyElseTo.SetIfFalse(bf);
                ifFrag.ApplyElseTo = newfrag;

                return(AddResult.Stop);
            }
            else
            {
                return(base.AddTo(to, sr));
            }
        }
Example #37
0
 /// <summary>Creates a new type fragment by reading it and a preceeding colon from the given lexer.</summary>
 /// <param name="sr">The lexer to read from.</param>
 public TypeFragment(CodeLexer sr) : this(sr, true)
 {
 }
		public BaseFragment(CodeLexer sr):base(sr,false){}
Example #39
0
        /// <summary>Reads a new operation from the given lexer.</summary>
        /// <param name="sr">The lexer to read the operation from.</param>
        /// <param name="parent">The fragment to parent the operation to.</param>
        public OperationFragment(CodeLexer sr, CodeFragment parent)
        {
            ParentFragment = parent;
            LineNumber     = sr.LineNumber;
            bool localMode = false;

            while (true)
            {
                char peek = sr.Peek();

                if (peek == StringReader.NULL)
                {
                    return;
                }

                if (peek == ';' || peek == ',')
                {
                    // Read it off:
                    sr.Read();
                    return;
                }

                Handler handler = Handlers.Find(peek);

                if (handler == Handler.Stop)
                {
                    return;
                }

                // Handle the fragment:
                CodeFragment fragment;

                try{
                    // Try to get the code fragment:
                    fragment = Handlers.Handle(handler, sr);
                }catch (CompilationException e) {
                    if (e.LineNumber == -1)
                    {
                        // Setup line number:
                        e.LineNumber = LineNumber;
                    }

                    // Rethrow:
                    throw e;
                }

                if (localMode)
                {
                    // Should always be a VariableFragment:

                    if (fragment.GetType() == typeof(VariableFragment))
                    {
                        VariableFragment local = (VariableFragment)fragment;
                        local.AfterVar = true;
                    }

                    localMode = false;
                }

                // Try adding the fragment to the operation:
                AddResult status = fragment.AddTo(this, sr);

                // What was the outcome?
                switch (status)
                {
                case AddResult.Stop:
                    // Halt.
                    return;

                case AddResult.Local:
                    // Local next:
                    localMode = true;
                    break;
                    // Ok otherwise.
                }
            }
        }
		public override AddResult AddTo(CodeFragment to,CodeLexer sr){
			base.AddTo(to,sr);
			return AddResult.Stop;
		}
		public override AddResult AddTo(CodeFragment to,CodeLexer sr){
			if(to.LastChild==null||!to.LastChild.Typeable()){
				Error("A type ("+ToString()+") was found in an unexpected place.");
			}
			to.LastChild.GivenType=this;
			return AddResult.Ok;
		}