Ejemplo n.º 1
0
		public static Expression Parse(TokenStream tokens, Executable owner)
		{
			Dictionary<string, Annotation> annotations = null;
			if (tokens.IsNext("@"))
			{
				annotations = new Dictionary<string, Annotation>();
				while (tokens.IsNext("@"))
				{
					Annotation annotation = AnnotationParser.ParseAnnotation(tokens);
					annotations[annotation.Type] = annotation;
				}
			}
			Expression output = ParseTernary(tokens, owner);
			output.Annotations = annotations;
			return output;
		}
Ejemplo n.º 2
0
        private static Executable ParseStruct(TokenStream tokens, Executable owner)
        {
            Token structToken     = tokens.PopExpected("struct");
            Token structNameToken = tokens.Pop();

            Parser.VerifyIdentifier(structNameToken);

            tokens.PopExpected("{");

            List <Token>      fieldTokens     = new List <Token>();
            List <Annotation> typeAnnotations = new List <Annotation>();
            bool nextForbidden = false;

            while (!tokens.PopIfPresent("}"))
            {
                if (nextForbidden)
                {
                    tokens.PopExpected("}");                // crash
                }
                Annotation annotation = tokens.IsNext("@") ? AnnotationParser.ParseAnnotation(tokens) : null;

                Token fieldToken = tokens.Pop();
                Parser.VerifyIdentifier(fieldToken);
                nextForbidden = !tokens.PopIfPresent(",");
                fieldTokens.Add(fieldToken);
                typeAnnotations.Add(annotation);
            }

            return(new StructDefinition(structToken, structNameToken, fieldTokens, typeAnnotations, owner));
        }
Ejemplo n.º 3
0
        public void ParseInterpretedCode(string filename, string code)
        {
            FileScope fileScope = new FileScope(filename);
            int       fileId    = this.GetNextFileId();

            this.RegisterFileUsed(filename, code, fileId);
            Token[]     tokenList = Tokenizer.Tokenize(filename, code, fileId, true);
            TokenStream tokens    = new TokenStream(tokenList, filename);

            List <string> namespaceImportsBuilder = new List <string>();

            tokens.InsertTokens(this.GetImplicitCoreImport());

            if (this.CurrentLibrary != null && this.CurrentLibrary.CanonicalKey != "en:Core")
            {
                Library coreLibrary = this.LibraryManager.GetCoreLibrary(this);
                this.CurrentLibrary.AddLibraryDependency(coreLibrary);
            }

            List <CompilationScope> scopesAdded = new List <CompilationScope>();

            while (tokens.HasMore && tokens.IsNext(this.Keywords.IMPORT))
            {
                ImportStatement importStatement = this.ExecutableParser.ParseTopLevel(tokens, null, fileScope) as ImportStatement;
                if (importStatement == null)
                {
                    throw new Exception();
                }
                namespaceImportsBuilder.Add(importStatement.ImportPath);
                Library library = this.LibraryManager.ImportLibrary(this, importStatement.FirstToken, importStatement.ImportPath);
                if (library == null)
                {
                    this.unresolvedImports.Add(importStatement);
                }
                else
                {
                    if (this.CurrentLibrary != null)
                    {
                        this.CurrentLibrary.AddLibraryDependency(library);
                    }
                    scopesAdded.Add(library.Scope);
                }
            }

            string[] namespaceImports = namespaceImportsBuilder.ToArray();

            while (tokens.HasMore)
            {
                TopLevelConstruct executable = this.ExecutableParser.ParseTopLevel(tokens, null, fileScope);

                if (executable is ImportStatement)
                {
                    throw new ParserException(
                              executable.FirstToken,
                              this.CurrentLocale.Strings.Get("ALL_IMPORTS_MUST_OCCUR_AT_BEGINNING_OF_FILE"));
                }

                this.CurrentScope.AddExecutable(executable);
            }
        }
Ejemplo n.º 4
0
        public Executable[] ParseInterpretedCode(string filename, string code, string libraryName)
        {
            int fileId = this.GetNextFileId();

            this.RegisterFileUsed(filename, code, fileId);
            Token[]     tokenList = Tokenizer.Tokenize(filename, code, fileId, true);
            TokenStream tokens    = new TokenStream(tokenList);

            List <Executable> executables = new List <Executable>();

            List <string> namespaceImportsBuilder = new List <string>();

            tokens.InsertTokens(implicitCoreImport);

            while (tokens.HasMore && tokens.IsNext("import"))
            {
                ImportStatement importStatement = ExecutableParser.Parse(this, tokens, false, true, true, null) as ImportStatement;
                if (importStatement == null)
                {
                    throw new Exception();
                }
                namespaceImportsBuilder.Add(importStatement.ImportPath);
                Executable[] libraryEmbeddedCode = this.SystemLibraryManager.ImportLibrary(this, importStatement.FirstToken, importStatement.ImportPath);
                executables.AddRange(libraryEmbeddedCode);
            }

            string[] namespaceImports = namespaceImportsBuilder.ToArray();

            while (tokens.HasMore)
            {
                Executable executable;
                try
                {
                    executable = ExecutableParser.Parse(this, tokens, false, true, true, null);
                }
                catch (EofException)
                {
                    throw new ParserException(null, "Unexpected EOF encountered while parsing " + filename + ". Did you forget a closing curly brace?");
                }

                if (executable is ImportStatement)
                {
                    throw new ParserException(executable.FirstToken, "All imports must occur at the beginning of the file.");
                }

                executable.NamespacePrefixSearch = namespaceImports;
                executable.LibraryName           = libraryName;

                if (executable is Namespace)
                {
                    ((Namespace)executable).GetFlattenedCode(executables, namespaceImports, libraryName);
                }
                else
                {
                    executables.Add(executable);
                }
            }

            return(executables.ToArray());
        }
Ejemplo n.º 5
0
        public static Expression Parse(TokenStream tokens, Executable owner)
        {
            Dictionary <string, Annotation> annotations = null;

            if (tokens.IsNext("@"))
            {
                annotations = new Dictionary <string, Annotation>();
                while (tokens.IsNext("@"))
                {
                    Annotation annotation = AnnotationParser.ParseAnnotation(tokens);
                    annotations[annotation.Type] = annotation;
                }
            }
            Expression output = ParseTernary(tokens, owner);

            output.Annotations = annotations;
            return(output);
        }
Ejemplo n.º 6
0
        private Expression ParseIncrement(TokenStream tokens, TopLevelConstruct owner)
        {
            Expression root;

            if (tokens.IsNext("++") || tokens.IsNext("--"))
            {
                Token incrementToken = tokens.Pop();
                root = this.ParseEntity(tokens, owner);
                return(new Increment(incrementToken, incrementToken, incrementToken.Value == "++", true, root, owner));
            }

            root = this.ParseEntity(tokens, owner);
            if (tokens.IsNext("++") || tokens.IsNext("--"))
            {
                Token incrementToken = tokens.Pop();
                return(new Increment(root.FirstToken, incrementToken, incrementToken.Value == "++", false, root, owner));
            }

            return(root);
        }
Ejemplo n.º 7
0
        private static Expression ParseIncrement(TokenStream tokens, Executable owner)
        {
            Expression root;

            if (tokens.IsNext("++") || tokens.IsNext("--"))
            {
                Token incrementToken = tokens.Pop();
                root = ParseEntity(tokens, owner);
                return(new Increment(incrementToken, incrementToken, incrementToken.Value == "++", true, root, owner));
            }

            root = ParseEntity(tokens, owner);
            if (tokens.IsNext("++") || tokens.IsNext("--"))
            {
                Token incrementToken = tokens.Pop();
                return(new Increment(root.FirstToken, incrementToken, incrementToken.Value == "++", false, root, owner));
            }

            return(root);
        }
Ejemplo n.º 8
0
        private static Executable ParseTry(Parser parser, TokenStream tokens, Executable owner)
        {
            Token tryToken = tokens.PopExpected("try");
            IList <Executable> tryBlock     = Parser.ParseBlock(parser, tokens, true, owner);
            Token catchToken                = null;
            IList <Executable> catchBlock   = null;
            Token exceptionToken            = null;
            Token finallyToken              = null;
            IList <Executable> finallyBlock = null;

            if (tokens.IsNext("catch"))
            {
                catchToken = tokens.Pop();
                if (tokens.PopIfPresent("("))
                {
                    exceptionToken = tokens.Pop();
                    char firstChar = exceptionToken.Value[0];
                    if (firstChar != '_' &&
                        !(firstChar >= 'a' && firstChar <= 'z') &&
                        !(firstChar >= 'A' && firstChar <= 'Z'))
                    {
                        throw new ParserException(exceptionToken, "Invalid name for variable.");
                    }
                    tokens.PopExpected(")");
                }

                catchBlock = Parser.ParseBlock(parser, tokens, true, owner);
            }

            if (tokens.IsNext("finally"))
            {
                finallyToken = tokens.Pop();
                finallyBlock = Parser.ParseBlock(parser, tokens, true, owner);
            }

            return(new TryStatement(tryToken, tryBlock, catchToken, exceptionToken, catchBlock, finallyToken, finallyBlock, owner));
        }
Ejemplo n.º 9
0
        private void Initialize(Token annotationToken, TokenStream proxyTokenStream)
        {
            this.Token = annotationToken;

            Token token = proxyTokenStream.Pop();

            if (!Parser.IsValidIdentifier(token.Value))
            {
                throw new ParserException(annotationToken, "Invalid type");
            }

            this.Name = token.Value;

            while (proxyTokenStream.PopIfPresent("."))
            {
                this.Name += ".";
                this.Name += proxyTokenStream.PopValue();
            }

            List <AnnotatedType> generics = new List <AnnotatedType>();

            if (proxyTokenStream.PopIfPresent("<"))
            {
                while (proxyTokenStream.HasMore && !proxyTokenStream.IsNext(">"))
                {
                    if (generics.Count > 0 && !proxyTokenStream.PopIfPresent(","))
                    {
                        throw new ParserException(annotationToken, "Expected comma in generic list");
                    }

                    AnnotatedType genericItem = new AnnotatedType(annotationToken, proxyTokenStream);
                    generics.Add(genericItem);
                }

                if (!proxyTokenStream.PopIfPresent(">"))
                {
                    throw new ParserException(annotationToken, "Unclosed generic bracket.");
                }
            }

            this.Generics = generics.ToArray();
        }
Ejemplo n.º 10
0
		private void Initialize(Token annotationToken, TokenStream proxyTokenStream)
		{
			this.Token = annotationToken;

			Token token = proxyTokenStream.Pop();
			if (!Parser.IsValidIdentifier(token.Value)) throw new ParserException(annotationToken, "Invalid type");

			this.Name = token.Value;

			while (proxyTokenStream.PopIfPresent("."))
			{
				this.Name += ".";
				this.Name += proxyTokenStream.PopValue();
			}

			List<AnnotatedType> generics = new List<AnnotatedType>();
			if (proxyTokenStream.PopIfPresent("<"))
			{
				while (proxyTokenStream.HasMore && !proxyTokenStream.IsNext(">"))
				{
					if (generics.Count > 0 && !proxyTokenStream.PopIfPresent(","))
					{
						throw new ParserException(annotationToken, "Expected comma in generic list");
					}

					AnnotatedType genericItem = new AnnotatedType(annotationToken, proxyTokenStream);
					generics.Add(genericItem);
				}

				if (!proxyTokenStream.PopIfPresent(">"))
				{
					throw new ParserException(annotationToken, "Unclosed generic bracket.");
				}
			}

			this.Generics = generics.ToArray();
		}
Ejemplo n.º 11
0
        private ClassDefinition ParseClassDefinition(TokenStream tokens, TopLevelConstruct owner, Token staticToken, Token finalToken, FileScope fileScope)
        {
            Token classToken     = tokens.PopExpected(this.parser.Keywords.CLASS);
            Token classNameToken = tokens.Pop();

            this.parser.VerifyIdentifier(classNameToken);
            List <Token>  baseClassTokens  = new List <Token>();
            List <string> baseClassStrings = new List <string>();

            if (tokens.PopIfPresent(":"))
            {
                if (baseClassTokens.Count > 0)
                {
                    tokens.PopExpected(",");
                }

                Token  baseClassToken = tokens.Pop();
                string baseClassName  = baseClassToken.Value;

                this.parser.VerifyIdentifier(baseClassToken);
                while (tokens.PopIfPresent("."))
                {
                    Token baseClassTokenNext = tokens.Pop();
                    this.parser.VerifyIdentifier(baseClassTokenNext);
                    baseClassName += "." + baseClassTokenNext.Value;
                }

                baseClassTokens.Add(baseClassToken);
                baseClassStrings.Add(baseClassName);
            }

            ClassDefinition cd = new ClassDefinition(
                classToken,
                classNameToken,
                baseClassTokens,
                baseClassStrings,
                parser.CurrentNamespace,
                owner,
                parser.CurrentLibrary,
                staticToken,
                finalToken,
                fileScope);

            tokens.PopExpected("{");
            List <FunctionDefinition> methods              = new List <FunctionDefinition>();
            List <FieldDeclaration>   fields               = new List <FieldDeclaration>();
            ConstructorDefinition     constructorDef       = null;
            ConstructorDefinition     staticConstructorDef = null;

            while (!tokens.PopIfPresent("}"))
            {
                Dictionary <string, List <Annotation> > annotations = null;

                while (tokens.IsNext("@"))
                {
                    annotations = annotations ?? new Dictionary <string, List <Annotation> >();
                    Annotation annotation = this.parser.AnnotationParser.ParseAnnotation(tokens);
                    if (!annotations.ContainsKey(annotation.Type))
                    {
                        annotations[annotation.Type] = new List <Annotation>();
                    }

                    annotations[annotation.Type].Add(annotation);
                }

                if (tokens.IsNext(this.parser.Keywords.FUNCTION) ||
                    tokens.AreNext(this.parser.Keywords.STATIC, this.parser.Keywords.FUNCTION))
                {
                    methods.Add((FunctionDefinition)this.parser.ExecutableParser.ParseFunction(tokens, cd, fileScope));
                }
                else if (tokens.IsNext(this.parser.Keywords.CONSTRUCTOR))
                {
                    if (constructorDef != null)
                    {
                        throw new ParserException(tokens.Pop(), "Multiple constructors are not allowed. Use optional arguments.");
                    }

                    constructorDef = (ConstructorDefinition)this.parser.ExecutableParser.ParseConstructor(tokens, cd);

                    if (annotations != null && annotations.ContainsKey(this.parser.Keywords.PRIVATE))
                    {
                        constructorDef.PrivateAnnotation = annotations[this.parser.Keywords.PRIVATE][0];
                        annotations[this.parser.Keywords.PRIVATE].RemoveAt(0);
                    }
                }
                else if (tokens.AreNext(this.parser.Keywords.STATIC, this.parser.Keywords.CONSTRUCTOR))
                {
                    tokens.Pop(); // static token
                    if (staticConstructorDef != null)
                    {
                        throw new ParserException(tokens.Pop(), "Multiple static constructors are not allowed.");
                    }

                    staticConstructorDef = (ConstructorDefinition)this.parser.ExecutableParser.ParseConstructor(tokens, cd);
                }
                else if (tokens.IsNext(this.parser.Keywords.FIELD) ||
                         tokens.AreNext(this.parser.Keywords.STATIC, this.parser.Keywords.FIELD))
                {
                    fields.Add(this.parser.ExecutableParser.ParseField(tokens, cd));
                }
                else
                {
                    tokens.PopExpected("}");
                }

                if (annotations != null)
                {
                    foreach (List <Annotation> annotationsOfType in annotations.Values)
                    {
                        if (annotationsOfType.Count > 0)
                        {
                            throw new ParserException(annotationsOfType[0].FirstToken, "Unused or extra annotation.");
                        }
                    }
                }
            }

            cd.Methods           = methods.ToArray();
            cd.Constructor       = constructorDef;
            cd.StaticConstructor = staticConstructorDef;
            cd.Fields            = fields.ToArray();

            return(cd);
        }
Ejemplo n.º 12
0
		private static Expression ParseEntity(TokenStream tokens, Executable owner)
		{
			Expression root;
			if (tokens.PopIfPresent("("))
			{
				root = Parse(tokens, owner);
				tokens.PopExpected(")");
			}
			else
			{
				root = ParseEntityWithoutSuffixChain(tokens, owner);
			}
			bool anySuffixes = true;
			while (anySuffixes)
			{
				if (tokens.IsNext("."))
				{
					Token dotToken = tokens.Pop();
					Token stepToken = tokens.Pop();
					Parser.VerifyIdentifier(stepToken);
					root = new DotStep(root, dotToken, stepToken, owner);
				}
				else if (tokens.IsNext("["))
				{
					Token openBracket = tokens.Pop();
					List<Expression> sliceComponents = new List<Expression>();
					if (tokens.IsNext(":"))
					{
						sliceComponents.Add(null);
					}
					else
					{
						sliceComponents.Add(Parse(tokens, owner));
					}

					for (int i = 0; i < 2; ++i)
					{
						if (tokens.PopIfPresent(":"))
						{
							if (tokens.IsNext(":") || tokens.IsNext("]"))
							{
								sliceComponents.Add(null);
							}
							else
							{
								sliceComponents.Add(Parse(tokens, owner));
							}
						}
					}

					tokens.PopExpected("]");

					if (sliceComponents.Count == 1)
					{
						Expression index = sliceComponents[0];
						root = new BracketIndex(root, openBracket, index, owner);
					}
					else
					{
						root = new ListSlice(root, sliceComponents, openBracket, owner);
					}
				}
				else if (tokens.IsNext("("))
				{
					Token openParen = tokens.Pop();
					List<Expression> args = new List<Expression>();
					while (!tokens.PopIfPresent(")"))
					{
						if (args.Count > 0)
						{
							tokens.PopExpected(",");
						}

						args.Add(Parse(tokens, owner));
					}
					root = new FunctionCall(root, openParen, args, owner);
				}
				else
				{
					anySuffixes = false;
				}
			}
			return root;
		}
Ejemplo n.º 13
0
        private static Expression ParseEntityWithoutSuffixChain(TokenStream tokens, Executable owner)
        {
            string next = tokens.PeekValue();

            if (next == "null")
            {
                return(new NullConstant(tokens.Pop(), owner));
            }
            if (next == "true")
            {
                return(new BooleanConstant(tokens.Pop(), true, owner));
            }
            if (next == "false")
            {
                return(new BooleanConstant(tokens.Pop(), false, owner));
            }

            Token peekToken = tokens.Peek();

            if (next.StartsWith("'"))
            {
                return(new StringConstant(tokens.Pop(), StringConstant.ParseOutRawValue(peekToken), owner));
            }
            if (next.StartsWith("\""))
            {
                return(new StringConstant(tokens.Pop(), StringConstant.ParseOutRawValue(peekToken), owner));
            }
            if (next == "new")
            {
                return(ParseInstantiate(tokens, owner));
            }

            char firstChar = next[0];

            if (VARIABLE_STARTER.Contains(firstChar))
            {
                Token varToken = tokens.Pop();
                return(new Variable(varToken, varToken.Value, owner));
            }

            if (firstChar == '[')
            {
                Token             bracketToken = tokens.PopExpected("[");
                List <Expression> elements     = new List <Expression>();
                bool previousHasCommaOrFirst   = true;
                while (!tokens.PopIfPresent("]"))
                {
                    if (!previousHasCommaOrFirst)
                    {
                        tokens.PopExpected("]");                           // throws appropriate error
                    }
                    elements.Add(Parse(tokens, owner));
                    previousHasCommaOrFirst = tokens.PopIfPresent(",");
                }
                return(new ListDefinition(bracketToken, elements, owner));
            }

            if (firstChar == '{')
            {
                Token             braceToken = tokens.PopExpected("{");
                List <Expression> keys       = new List <Expression>();
                List <Expression> values     = new List <Expression>();
                bool previousHasCommaOrFirst = true;
                while (!tokens.PopIfPresent("}"))
                {
                    if (!previousHasCommaOrFirst)
                    {
                        tokens.PopExpected("}");                           // throws appropriate error
                    }
                    keys.Add(Parse(tokens, owner));
                    tokens.PopExpected(":");
                    values.Add(Parse(tokens, owner));
                    previousHasCommaOrFirst = tokens.PopIfPresent(",");
                }
                return(new DictionaryDefinition(braceToken, keys, values, owner));
            }

            if (next.Length > 2 && next.Substring(0, 2) == "0x")
            {
                Token intToken = tokens.Pop();
                int   intValue = IntegerConstant.ParseIntConstant(intToken, intToken.Value);
                return(new IntegerConstant(intToken, intValue, owner));
            }

            if (Parser.IsInteger(next))
            {
                Token  numberToken = tokens.Pop();
                string numberValue = numberToken.Value;

                if (tokens.IsNext("."))
                {
                    Token decimalToken = tokens.Pop();
                    if (decimalToken.HasWhitespacePrefix)
                    {
                        throw new ParserException(decimalToken, "Decimals cannot have whitespace before them.");
                    }

                    Token afterDecimal = tokens.Pop();
                    if (afterDecimal.HasWhitespacePrefix)
                    {
                        throw new ParserException(afterDecimal, "Cannot have whitespace after the decimal.");
                    }
                    if (!Parser.IsInteger(afterDecimal.Value))
                    {
                        throw new ParserException(afterDecimal, "Decimal must be followed by an integer.");
                    }

                    numberValue += "." + afterDecimal.Value;

                    double floatValue = FloatConstant.ParseValue(numberToken, numberValue);
                    return(new FloatConstant(numberToken, floatValue, owner));
                }

                int intValue = IntegerConstant.ParseIntConstant(numberToken, numberToken.Value);
                return(new IntegerConstant(numberToken, intValue, owner));
            }

            if (tokens.IsNext("."))
            {
                Token  dotToken    = tokens.PopExpected(".");
                string numberValue = "0.";
                Token  postDecimal = tokens.Pop();
                if (postDecimal.HasWhitespacePrefix || !Parser.IsInteger(postDecimal.Value))
                {
                    throw new ParserException(dotToken, "Unexpected dot.");
                }

                numberValue += postDecimal.Value;

                double floatValue;
                if (double.TryParse(numberValue, out floatValue))
                {
                    return(new FloatConstant(dotToken, floatValue, owner));
                }

                throw new ParserException(dotToken, "Invalid float literal.");
            }

            throw new ParserException(tokens.Peek(), "Encountered unexpected token: '" + tokens.PeekValue() + "'");
        }
Ejemplo n.º 14
0
        private static Expression ParseEntity(TokenStream tokens, Executable owner)
        {
            Expression root;

            if (tokens.PopIfPresent("("))
            {
                root = Parse(tokens, owner);
                tokens.PopExpected(")");
            }
            else
            {
                root = ParseEntityWithoutSuffixChain(tokens, owner);
            }
            bool anySuffixes = true;

            while (anySuffixes)
            {
                if (tokens.IsNext("."))
                {
                    Token dotToken  = tokens.Pop();
                    Token stepToken = tokens.Pop();
                    Parser.VerifyIdentifier(stepToken);
                    root = new DotStep(root, dotToken, stepToken, owner);
                }
                else if (tokens.IsNext("["))
                {
                    Token             openBracket     = tokens.Pop();
                    List <Expression> sliceComponents = new List <Expression>();
                    if (tokens.IsNext(":"))
                    {
                        sliceComponents.Add(null);
                    }
                    else
                    {
                        sliceComponents.Add(Parse(tokens, owner));
                    }

                    for (int i = 0; i < 2; ++i)
                    {
                        if (tokens.PopIfPresent(":"))
                        {
                            if (tokens.IsNext(":") || tokens.IsNext("]"))
                            {
                                sliceComponents.Add(null);
                            }
                            else
                            {
                                sliceComponents.Add(Parse(tokens, owner));
                            }
                        }
                    }

                    tokens.PopExpected("]");

                    if (sliceComponents.Count == 1)
                    {
                        Expression index = sliceComponents[0];
                        root = new BracketIndex(root, openBracket, index, owner);
                    }
                    else
                    {
                        root = new ListSlice(root, sliceComponents, openBracket, owner);
                    }
                }
                else if (tokens.IsNext("("))
                {
                    Token             openParen = tokens.Pop();
                    List <Expression> args      = new List <Expression>();
                    while (!tokens.PopIfPresent(")"))
                    {
                        if (args.Count > 0)
                        {
                            tokens.PopExpected(",");
                        }

                        args.Add(Parse(tokens, owner));
                    }
                    root = new FunctionCall(root, openParen, args, owner);
                }
                else if (tokens.IsNext("is"))
                {
                    Token  isToken    = tokens.Pop();
                    Token  classToken = tokens.Pop();
                    string className  = PopClassName(tokens, classToken);
                    root = new IsComparison(root, isToken, classToken, className, owner);
                }
                else
                {
                    anySuffixes = false;
                }
            }
            return(root);
        }
Ejemplo n.º 15
0
        private Expression ParseEntity(TokenStream tokens, Executable owner)
        {
            Expression root;

            if (tokens.PopIfPresent("("))
            {
                root = this.Parse(tokens, owner);
                tokens.PopExpected(")");
            }
            else
            {
                root = ParseEntityWithoutSuffixChain(tokens, owner);
            }
            bool anySuffixes = true;

            while (anySuffixes)
            {
                if (tokens.IsNext("."))
                {
                    Token dotToken  = tokens.Pop();
                    Token stepToken = tokens.Pop();
                    // HACK alert: "class" is a valid field on a class.
                    // ParserVerifyIdentifier is invoked downstream for non-resolved fields.
                    if (stepToken.Value != this.parser.Keywords.CLASS)
                    {
                        this.parser.VerifyIdentifier(stepToken);
                    }
                    root = new DotStep(root, dotToken, stepToken, owner);
                }
                else if (tokens.IsNext("["))
                {
                    Token             openBracket     = tokens.Pop();
                    List <Expression> sliceComponents = new List <Expression>();
                    if (tokens.IsNext(":"))
                    {
                        sliceComponents.Add(null);
                    }
                    else
                    {
                        sliceComponents.Add(Parse(tokens, owner));
                    }

                    for (int i = 0; i < 2; ++i)
                    {
                        if (tokens.PopIfPresent(":"))
                        {
                            if (tokens.IsNext(":") || tokens.IsNext("]"))
                            {
                                sliceComponents.Add(null);
                            }
                            else
                            {
                                sliceComponents.Add(Parse(tokens, owner));
                            }
                        }
                    }

                    tokens.PopExpected("]");

                    if (sliceComponents.Count == 1)
                    {
                        Expression index = sliceComponents[0];
                        root = new BracketIndex(root, openBracket, index, owner);
                    }
                    else
                    {
                        root = new ListSlice(root, sliceComponents, openBracket, owner);
                    }
                }
                else if (tokens.IsNext("("))
                {
                    Token             openParen = tokens.Pop();
                    List <Expression> args      = new List <Expression>();
                    while (!tokens.PopIfPresent(")"))
                    {
                        if (args.Count > 0)
                        {
                            tokens.PopExpected(",");
                        }

                        args.Add(Parse(tokens, owner));
                    }
                    root = new FunctionCall(root, openParen, args, owner);
                }
                else if (tokens.IsNext(this.parser.Keywords.IS))
                {
                    Token  isToken    = tokens.Pop();
                    Token  classToken = tokens.Pop();
                    string className  = this.parser.PopClassNameWithFirstTokenAlreadyPopped(tokens, classToken);
                    root = new IsComparison(root, isToken, classToken, className, owner);
                }
                else
                {
                    anySuffixes = false;
                }
            }
            return(root);
        }
Ejemplo n.º 16
0
		private static Executable ParseSwitch(Parser parser, TokenStream tokens, Executable owner)
		{
			Token switchToken = tokens.PopExpected("switch");

			Expression explicitMax = null;
			Token explicitMaxToken = null;
			if (tokens.IsNext("{"))
			{
				explicitMaxToken = tokens.Pop();
				explicitMax = ExpressionParser.Parse(tokens, owner);
				tokens.PopExpected("}");
			}

			tokens.PopExpected("(");
			Expression condition = ExpressionParser.Parse(tokens, owner);
			tokens.PopExpected(")");
			tokens.PopExpected("{");
			List<List<Expression>> cases = new List<List<Expression>>();
			List<Token> firstTokens = new List<Token>();
			List<List<Executable>> code = new List<List<Executable>>();
			char state = '?'; // ? - first, O - code, A - case
			bool defaultEncountered = false;
			while (!tokens.PopIfPresent("}"))
			{
				if (tokens.IsNext("case"))
				{
					if (defaultEncountered)
					{
						throw new ParserException(tokens.Peek(), "default condition in a switch statement must be the last condition.");
					}

					Token caseToken = tokens.PopExpected("case");
					if (state != 'A')
					{
						cases.Add(new List<Expression>());
						firstTokens.Add(caseToken);
						code.Add(null);
						state = 'A';
					}
					cases[cases.Count - 1].Add(ExpressionParser.Parse(tokens, owner));
					tokens.PopExpected(":");
				}
				else if (tokens.IsNext("default"))
				{
					Token defaultToken = tokens.PopExpected("default");
					if (state != 'A')
					{
						cases.Add(new List<Expression>());
						firstTokens.Add(defaultToken);
						code.Add(null);
						state = 'A';
					}
					cases[cases.Count - 1].Add(null);
					tokens.PopExpected(":");
					defaultEncountered = true;
				}
				else
				{
					if (state != 'O')
					{
						cases.Add(null);
						firstTokens.Add(null);
						code.Add(new List<Executable>());
						state = 'O';
					}
					code[code.Count - 1].Add(ExecutableParser.Parse(parser, tokens, false, true, false, owner));
				}
			}

			return new SwitchStatement(switchToken, condition, firstTokens, cases, code, explicitMax, explicitMaxToken, owner);
		}
Ejemplo n.º 17
0
		private static Executable ParseFunction(Parser parser, TokenStream tokens, Executable nullableOwner)
		{
			bool isStatic = 
				nullableOwner != null && 
				nullableOwner is ClassDefinition && 
				tokens.PopIfPresent("static");

			Token functionToken = tokens.PopExpected("function");

			List<Annotation> functionAnnotations = new List<Annotation>();

			while (tokens.IsNext("@"))
			{
				functionAnnotations.Add(AnnotationParser.ParseAnnotation(tokens));
			}

			Token functionNameToken = tokens.Pop();
			Parser.VerifyIdentifier(functionNameToken);

			FunctionDefinition fd = new FunctionDefinition(functionToken, nullableOwner, isStatic, functionNameToken, functionAnnotations, parser.CurrentNamespace);

			tokens.PopExpected("(");
			List<Token> argNames = new List<Token>();
			List<Expression> defaultValues = new List<Expression>();
			List<Annotation> argAnnotations = new List<Annotation>();
			bool optionalArgFound = false;
			while (!tokens.PopIfPresent(")"))
			{
				if (argNames.Count > 0) tokens.PopExpected(",");

				Annotation annotation = tokens.IsNext("@") ? AnnotationParser.ParseAnnotation(tokens) : null;
				Token argName = tokens.Pop();
				Expression defaultValue = null;
				Parser.VerifyIdentifier(argName);
				if (tokens.PopIfPresent("="))
				{
					optionalArgFound = true;
					defaultValue = ExpressionParser.Parse(tokens, fd);
				}
				else if (optionalArgFound)
				{
					throw new ParserException(argName, "All optional arguments must come at the end of the argument list.");
				}
				argAnnotations.Add(annotation);
				argNames.Add(argName);
				defaultValues.Add(defaultValue);
			}

			IList<Executable> code = Parser.ParseBlock(parser, tokens, true, fd);

			fd.ArgNames = argNames.ToArray();
			fd.DefaultValues = defaultValues.ToArray();
			fd.ArgAnnotations = argAnnotations.ToArray();
			fd.Code = code.ToArray();

			return fd;
		}
Ejemplo n.º 18
0
		private static Expression ParseIncrement(TokenStream tokens, Executable owner)
		{
			Expression root;
			if (tokens.IsNext("++") || tokens.IsNext("--"))
			{
				Token incrementToken = tokens.Pop();
				root = ParseEntity(tokens, owner);
				return new Increment(incrementToken, incrementToken, incrementToken.Value == "++", true, root, owner);
			}

			root = ParseEntity(tokens, owner);
			if (tokens.IsNext("++") || tokens.IsNext("--"))
			{
				Token incrementToken = tokens.Pop();
				return new Increment(root.FirstToken, incrementToken, incrementToken.Value == "++", false, root, owner);
			}

			return root;
		}
Ejemplo n.º 19
0
        private Executable ParseTry(TokenStream tokens, TopLevelConstruct owner)
        {
            Token tryToken = tokens.PopExpected(this.parser.Keywords.TRY);
            IList <Executable> tryBlock = Parser.ParseBlock(parser, tokens, true, owner);

            List <Token>        catchTokens         = new List <Token>();
            List <string[]>     exceptionTypes      = new List <string[]>();
            List <Token[]>      exceptionTypeTokens = new List <Token[]>();
            List <Token>        exceptionVariables  = new List <Token>();
            List <Executable[]> catchBlocks         = new List <Executable[]>();

            Token finallyToken = null;
            IList <Executable> finallyBlock = null;

            while (tokens.IsNext(this.parser.Keywords.CATCH))
            {
                /*
                 *  Parse patterns:
                 *      All exceptions:
                 *          1a: catch { ... }
                 *          1b: catch (e) { ... }
                 *
                 *      A certain exception:
                 *          2a: catch (ExceptionName) { ... }
                 *          2b: catch (ExceptionName e) { ... }
                 *
                 *      Certain exceptions:
                 *          3a: catch (ExceptionName1 | ExceptionName2) { ... }
                 *          3b: catch (ExceptionName1 | ExceptionName2 e) { ... }
                 *
                 *  Non-Context-Free alert:
                 *      Note that if the exception variable does not contain a '.' character, 1b and 2a are
                 *      ambiguous at parse time. Treat them both as 1b and then if the classname resolution
                 *      fails, treat this as a variable.
                 *
                 *      This is actually kind of bad because a typo in the classname will not be known.
                 *      e.g "catch (Excpetion) {" will compile as a variable called "Excpetion"
                 *
                 *      End-user workarounds:
                 *      - always use a variable name OR
                 *      - always fully qualify exception types e.g. Core.Exception
                 *      Long-term plan:
                 *      - add warning support and emit warnings for:
                 *          - unused variables
                 *          - style-breaking uppercase variables.
                 */

                Token catchToken = tokens.PopExpected(this.parser.Keywords.CATCH);

                List <string> classNames    = new List <string>();
                List <Token>  classTokens   = new List <Token>();
                Token         variableToken = null;

                if (tokens.PopIfPresent("("))
                {
                    // This first one might actually be a variable. Assume class for now and sort it out later.
                    // (and by "later" I mean the ResolveNames phase)
                    Token  classFirstToken = tokens.Pop();
                    string className       = this.parser.PopClassNameWithFirstTokenAlreadyPopped(tokens, classFirstToken);
                    classNames.Add(className);
                    classTokens.Add(classFirstToken);

                    while (tokens.PopIfPresent("|"))
                    {
                        classFirstToken = tokens.Pop();
                        className       = this.parser.PopClassNameWithFirstTokenAlreadyPopped(tokens, classFirstToken);
                        classNames.Add(className);
                        classTokens.Add(classFirstToken);
                    }

                    if (!tokens.IsNext(")"))
                    {
                        variableToken = tokens.Pop();
                        this.parser.VerifyIdentifier(variableToken);
                    }

                    tokens.PopExpected(")");
                }
                else
                {
                    classNames.Add(null);
                    classTokens.Add(null);
                }

                Executable[] catchBlockCode = Parser.ParseBlock(parser, tokens, true, owner).ToArray();


                catchTokens.Add(catchToken);
                exceptionTypes.Add(classNames.ToArray());
                exceptionTypeTokens.Add(classTokens.ToArray());
                exceptionVariables.Add(variableToken);
                catchBlocks.Add(catchBlockCode);
            }

            if (tokens.IsNext(this.parser.Keywords.FINALLY))
            {
                finallyToken = tokens.Pop();
                finallyBlock = Parser.ParseBlock(parser, tokens, true, owner);
            }

            return(new TryStatement(tryToken, tryBlock, catchTokens, exceptionVariables, exceptionTypeTokens, exceptionTypes, catchBlocks, finallyToken, finallyBlock, owner));
        }
Ejemplo n.º 20
0
        private FunctionDefinition ParseFunction(TokenStream tokens, TopLevelConstruct nullableOwner, FileScope fileScope)
        {
            bool isStatic =
                nullableOwner != null &&
                nullableOwner is ClassDefinition &&
                tokens.PopIfPresent(this.parser.Keywords.STATIC);

            Token functionToken = tokens.PopExpected(this.parser.Keywords.FUNCTION);

            List <Annotation> functionAnnotations = new List <Annotation>();

            while (tokens.IsNext("@"))
            {
                functionAnnotations.Add(this.parser.AnnotationParser.ParseAnnotation(tokens));
            }

            Token functionNameToken = tokens.Pop();

            this.parser.VerifyIdentifier(functionNameToken);

            FunctionDefinition fd = new FunctionDefinition(functionToken, parser.CurrentLibrary, nullableOwner, isStatic, functionNameToken, functionAnnotations, parser.CurrentNamespace, fileScope);

            tokens.PopExpected("(");
            List <Token>      argNames       = new List <Token>();
            List <Expression> defaultValues  = new List <Expression>();
            List <Annotation> argAnnotations = new List <Annotation>();
            bool optionalArgFound            = false;

            while (!tokens.PopIfPresent(")"))
            {
                if (argNames.Count > 0)
                {
                    tokens.PopExpected(",");
                }

                Annotation annotation   = tokens.IsNext("@") ? this.parser.AnnotationParser.ParseAnnotation(tokens) : null;
                Token      argName      = tokens.Pop();
                Expression defaultValue = null;
                this.parser.VerifyIdentifier(argName);
                if (tokens.PopIfPresent("="))
                {
                    optionalArgFound = true;
                    defaultValue     = this.parser.ExpressionParser.Parse(tokens, fd);
                }
                else if (optionalArgFound)
                {
                    throw new ParserException(argName, "All optional arguments must come at the end of the argument list.");
                }
                argAnnotations.Add(annotation);
                argNames.Add(argName);
                defaultValues.Add(defaultValue);
            }

            IList <Executable> code = Parser.ParseBlock(parser, tokens, true, fd);

            fd.ArgNames       = argNames.ToArray();
            fd.DefaultValues  = defaultValues.ToArray();
            fd.ArgAnnotations = argAnnotations.ToArray();
            fd.Code           = code.ToArray();

            return(fd);
        }
Ejemplo n.º 21
0
		private static Expression ParseEntityWithoutSuffixChain(TokenStream tokens, Executable owner)
		{
			string next = tokens.PeekValue();

			if (next == "null") return new NullConstant(tokens.Pop(), owner);
			if (next == "true") return new BooleanConstant(tokens.Pop(), true, owner);
			if (next == "false") return new BooleanConstant(tokens.Pop(), false, owner);

			Token peekToken = tokens.Peek();
			if (next.StartsWith("'")) return new StringConstant(tokens.Pop(), StringConstant.ParseOutRawValue(peekToken), owner);
			if (next.StartsWith("\"")) return new StringConstant(tokens.Pop(), StringConstant.ParseOutRawValue(peekToken), owner);
			if (next == "new") return ParseInstantiate(tokens, owner);

			char firstChar = next[0];
			if (VARIABLE_STARTER.Contains(firstChar))
			{
				Token varToken = tokens.Pop();
				return new Variable(varToken, varToken.Value, owner);
			}

			if (firstChar == '[')
			{
				Token bracketToken = tokens.PopExpected("[");
				List<Expression> elements = new List<Expression>();
				bool previousHasCommaOrFirst = true;
				while (!tokens.PopIfPresent("]"))
				{
					if (!previousHasCommaOrFirst) tokens.PopExpected("]"); // throws appropriate error
					elements.Add(Parse(tokens, owner));
					previousHasCommaOrFirst = tokens.PopIfPresent(",");
				}
				return new ListDefinition(bracketToken, elements, owner);
			}

			if (firstChar == '{')
			{
				Token braceToken = tokens.PopExpected("{");
				List<Expression> keys = new List<Expression>();
				List<Expression> values = new List<Expression>();
				bool previousHasCommaOrFirst = true;
				while (!tokens.PopIfPresent("}"))
				{
					if (!previousHasCommaOrFirst) tokens.PopExpected("}"); // throws appropriate error
					keys.Add(Parse(tokens, owner));
					tokens.PopExpected(":");
					values.Add(Parse(tokens, owner));
					previousHasCommaOrFirst = tokens.PopIfPresent(",");
				}
				return new DictionaryDefinition(braceToken, keys, values, owner);
			}

			if (next.Length > 2 && next.Substring(0, 2) == "0x")
			{
				Token intToken = tokens.Pop();
				int intValue = IntegerConstant.ParseIntConstant(intToken, intToken.Value);
				return new IntegerConstant(intToken, intValue, owner);
			}

			if (Parser.IsInteger(next))
			{
				Token numberToken = tokens.Pop();
				string numberValue = numberToken.Value;

				if (tokens.IsNext("."))
				{
					Token decimalToken = tokens.Pop();
					if (decimalToken.HasWhitespacePrefix)
					{
						throw new ParserException(decimalToken, "Decimals cannot have whitespace before them.");
					}

					Token afterDecimal = tokens.Pop();
					if (afterDecimal.HasWhitespacePrefix) throw new ParserException(afterDecimal, "Cannot have whitespace after the decimal.");
					if (!Parser.IsInteger(afterDecimal.Value)) throw new ParserException(afterDecimal, "Decimal must be followed by an integer.");

					numberValue += "." + afterDecimal.Value;

					double floatValue = FloatConstant.ParseValue(numberToken, numberValue);
					return new FloatConstant(numberToken, floatValue, owner);
				}

				int intValue = IntegerConstant.ParseIntConstant(numberToken, numberToken.Value);
				return new IntegerConstant(numberToken, intValue, owner);
			}

			if (tokens.IsNext("."))
			{
				Token dotToken = tokens.PopExpected(".");
				string numberValue = "0.";
				Token postDecimal = tokens.Pop();
				if (postDecimal.HasWhitespacePrefix || !Parser.IsInteger(postDecimal.Value))
				{
					throw new ParserException(dotToken, "Unexpected dot.");
				}

				numberValue += postDecimal.Value;

				double floatValue;
				if (double.TryParse(numberValue, out floatValue))
				{
					return new FloatConstant(dotToken, floatValue, owner);
				}

				throw new ParserException(dotToken, "Invalid float literal.");
			}

			throw new ParserException(tokens.Peek(), "Encountered unexpected token: '" + tokens.PeekValue() + "'");
		}
Ejemplo n.º 22
0
        private static Executable ParseClassDefinition(Parser parser, TokenStream tokens, Executable owner, Token staticToken, Token finalToken)
        {
            Token classToken     = tokens.PopExpected("class");
            Token classNameToken = tokens.Pop();

            Parser.VerifyIdentifier(classNameToken);
            List <Token>  baseClassTokens  = new List <Token>();
            List <string> baseClassStrings = new List <string>();

            if (tokens.PopIfPresent(":"))
            {
                if (baseClassTokens.Count > 0)
                {
                    tokens.PopExpected(",");
                }

                Token  baseClassToken = tokens.Pop();
                string baseClassName  = baseClassToken.Value;

                Parser.VerifyIdentifier(baseClassToken);
                while (tokens.PopIfPresent("."))
                {
                    Token baseClassTokenNext = tokens.Pop();
                    Parser.VerifyIdentifier(baseClassTokenNext);
                    baseClassName += "." + baseClassTokenNext.Value;
                }

                baseClassTokens.Add(baseClassToken);
                baseClassStrings.Add(baseClassName);
            }

            ClassDefinition cd = new ClassDefinition(
                classToken,
                classNameToken,
                baseClassTokens,
                baseClassStrings,
                parser.CurrentNamespace,
                owner,
                staticToken,
                finalToken);

            tokens.PopExpected("{");
            List <FunctionDefinition> methods              = new List <FunctionDefinition>();
            List <FieldDeclaration>   fields               = new List <FieldDeclaration>();
            ConstructorDefinition     constructorDef       = null;
            ConstructorDefinition     staticConstructorDef = null;

            while (!tokens.PopIfPresent("}"))
            {
                Dictionary <string, List <Annotation> > annotations = null;

                while (tokens.IsNext("@"))
                {
                    annotations = annotations ?? new Dictionary <string, List <Annotation> >();
                    Annotation annotation = AnnotationParser.ParseAnnotation(tokens);
                    if (!annotations.ContainsKey(annotation.Type))
                    {
                        annotations[annotation.Type] = new List <Annotation>();
                    }

                    annotations[annotation.Type].Add(annotation);
                }

                if (tokens.IsNext("function") || tokens.AreNext("static", "function"))
                {
                    methods.Add((FunctionDefinition)ExecutableParser.ParseFunction(parser, tokens, cd));
                }
                else if (tokens.IsNext("constructor"))
                {
                    if (constructorDef != null)
                    {
                        throw new ParserException(tokens.Pop(), "Multiple constructors are not allowed. Use optional arguments.");
                    }

                    constructorDef = (ConstructorDefinition)ExecutableParser.ParseConstructor(parser, tokens, cd);

                    if (annotations != null && annotations.ContainsKey("private"))
                    {
                        constructorDef.PrivateAnnotation = annotations["private"][0];
                        annotations["private"].RemoveAt(0);
                    }
                }
                else if (tokens.AreNext("static", "constructor"))
                {
                    tokens.Pop(); // static token
                    if (staticConstructorDef != null)
                    {
                        throw new ParserException(tokens.Pop(), "Multiple static constructors are not allowed.");
                    }

                    staticConstructorDef = (ConstructorDefinition)ExecutableParser.ParseConstructor(parser, tokens, cd);
                }
                else if (tokens.IsNext("field") || tokens.AreNext("static", "field"))
                {
                    fields.Add(ExecutableParser.ParseField(tokens, cd));
                }
                else
                {
                    tokens.PopExpected("}");
                }

                if (annotations != null)
                {
                    foreach (List <Annotation> annotationsOfType in annotations.Values)
                    {
                        if (annotationsOfType.Count > 0)
                        {
                            throw new ParserException(annotationsOfType[0].FirstToken, "Unused or extra annotation.");
                        }
                    }
                }
            }

            cd.Methods           = methods.ToArray();
            cd.Constructor       = constructorDef;
            cd.StaticConstructor = staticConstructorDef;
            cd.Fields            = fields.ToArray();

            return(cd);
        }
Ejemplo n.º 23
0
        private Executable ParseSwitch(TokenStream tokens, TopLevelConstruct owner)
        {
            Token switchToken = tokens.PopExpected(this.parser.Keywords.SWITCH);

            Expression explicitMax      = null;
            Token      explicitMaxToken = null;

            if (tokens.IsNext("{"))
            {
                explicitMaxToken = tokens.Pop();
                explicitMax      = this.parser.ExpressionParser.Parse(tokens, owner);
                tokens.PopExpected("}");
            }

            tokens.PopExpected("(");
            Expression condition = this.parser.ExpressionParser.Parse(tokens, owner);

            tokens.PopExpected(")");
            tokens.PopExpected("{");
            List <List <Expression> > cases = new List <List <Expression> >();
            List <Token> firstTokens        = new List <Token>();
            List <List <Executable> > code  = new List <List <Executable> >();
            char state = '?'; // ? - first, O - code, A - case
            bool defaultEncountered = false;

            while (!tokens.PopIfPresent("}"))
            {
                if (tokens.IsNext(this.parser.Keywords.CASE))
                {
                    if (defaultEncountered)
                    {
                        throw new ParserException(tokens.Peek(), "default condition in a switch statement must be the last condition.");
                    }

                    Token caseToken = tokens.PopExpected(this.parser.Keywords.CASE);
                    if (state != 'A')
                    {
                        cases.Add(new List <Expression>());
                        firstTokens.Add(caseToken);
                        code.Add(null);
                        state = 'A';
                    }
                    cases[cases.Count - 1].Add(this.parser.ExpressionParser.Parse(tokens, owner));
                    tokens.PopExpected(":");
                }
                else if (tokens.IsNext(this.parser.Keywords.DEFAULT))
                {
                    Token defaultToken = tokens.PopExpected(this.parser.Keywords.DEFAULT);
                    if (state != 'A')
                    {
                        cases.Add(new List <Expression>());
                        firstTokens.Add(defaultToken);
                        code.Add(null);
                        state = 'A';
                    }
                    cases[cases.Count - 1].Add(null);
                    tokens.PopExpected(":");
                    defaultEncountered = true;
                }
                else
                {
                    if (state != 'O')
                    {
                        cases.Add(null);
                        firstTokens.Add(null);
                        code.Add(new List <Executable>());
                        state = 'O';
                    }
                    code[code.Count - 1].Add(this.parser.ExecutableParser.Parse(tokens, false, true, owner));
                }
            }

            return(new SwitchStatement(switchToken, condition, firstTokens, cases, code, explicitMax, explicitMaxToken, owner));
        }
Ejemplo n.º 24
0
		private static Executable ParseClassDefinition(Parser parser, TokenStream tokens, Executable owner)
		{
			Token classToken = tokens.PopExpected("class");
			Token classNameToken = tokens.Pop();
			Parser.VerifyIdentifier(classNameToken);
			List<Token> baseClassTokens = new List<Token>();
			List<string> baseClassStrings = new List<string>();
			if (tokens.PopIfPresent(":"))
			{
				if (baseClassTokens.Count > 0)
				{
					tokens.PopExpected(",");
				}

				Token baseClassToken = tokens.Pop();
				string baseClassName = baseClassToken.Value;

				Parser.VerifyIdentifier(baseClassToken);
				while (tokens.PopIfPresent("."))
				{
					Token baseClassTokenNext = tokens.Pop();
					Parser.VerifyIdentifier(baseClassTokenNext);
					baseClassName += "." + baseClassTokenNext.Value;
				}

				baseClassTokens.Add(baseClassToken);
				baseClassStrings.Add(baseClassName);
			}

			ClassDefinition cd = new ClassDefinition(
				classToken,
				classNameToken,
				baseClassTokens,
				baseClassStrings,
				parser.CurrentNamespace,
				owner);

			tokens.PopExpected("{");
			List<FunctionDefinition> methods = new List<FunctionDefinition>();
			List<FieldDeclaration> fields = new List<FieldDeclaration>();
			ConstructorDefinition constructorDef = null;
			ConstructorDefinition staticConstructorDef = null;

			while (!tokens.PopIfPresent("}"))
			{
				if (tokens.IsNext("function") || tokens.AreNext("static", "function"))
				{
					methods.Add((FunctionDefinition)ExecutableParser.ParseFunction(parser, tokens, cd));
				}
				else if (tokens.IsNext("constructor"))
				{
					if (constructorDef != null)
					{
						throw new ParserException(tokens.Pop(), "Multiple constructors are not allowed. Use optional arguments.");
					}

					constructorDef = (ConstructorDefinition)ExecutableParser.ParseConstructor(parser, tokens, cd);
				}
				else if (tokens.AreNext("static", "constructor"))
				{
					tokens.Pop(); // static token
					if (staticConstructorDef != null)
					{
						throw new ParserException(tokens.Pop(), "Multiple static constructors are not allowed.");
					}

					staticConstructorDef = (ConstructorDefinition)ExecutableParser.ParseConstructor(parser, tokens, cd);
				}
				else if (tokens.IsNext("field") || tokens.AreNext("static", "field"))
				{
					fields.Add(ExecutableParser.ParseField(tokens, cd));
				}
				else
				{
					tokens.PopExpected("}");
				}
			}

			cd.Methods = methods.ToArray();
			cd.Constructor = constructorDef;
			cd.StaticConstructor = staticConstructorDef;
			cd.Fields = fields.ToArray();

			return cd;
		}
Ejemplo n.º 25
0
        public Executable[] ParseInterpretedCode(string filename, string code, string libraryName)
        {
            int fileId = this.GetNextFileId();

            this.RegisterFileUsed(filename, code, fileId);
            Token[]     tokenList = Tokenizer.Tokenize(filename, code, fileId, true);
            TokenStream tokens    = new TokenStream(tokenList, filename);

            List <Executable> executables = new List <Executable>();

            List <string> namespaceImportsBuilder = new List <string>();

            tokens.InsertTokens(this.GetImplicitCoreImport());

            Library activeLibrary = libraryName == null ? null : this.LibraryManager.GetLibraryFromName(libraryName);

            if (libraryName != null && libraryName != "Core")
            {
                activeLibrary.AddLibraryDependency(this.LibraryManager.GetLibraryFromName("Core"));
            }

            while (tokens.HasMore && tokens.IsNext(this.Keywords.IMPORT))
            {
                ImportStatement importStatement = this.ExecutableParser.Parse(tokens, false, true, true, null) as ImportStatement;
                if (importStatement == null)
                {
                    throw new Exception();
                }
                namespaceImportsBuilder.Add(importStatement.ImportPath);
                List <Executable> libraryEmbeddedCode = new List <Executable>();
                Library           library             = this.LibraryManager.ImportLibrary(this, importStatement.FirstToken, importStatement.ImportPath, libraryEmbeddedCode);
                if (library == null)
                {
                    this.unresolvedImports.Add(importStatement);
                }
                else
                {
                    if (activeLibrary != null)
                    {
                        activeLibrary.AddLibraryDependency(library);
                    }
                    executables.AddRange(libraryEmbeddedCode);
                }
            }

            string[] namespaceImports = namespaceImportsBuilder.ToArray();

            while (tokens.HasMore)
            {
                Executable executable = this.ExecutableParser.Parse(tokens, false, true, true, null);

                if (executable is ImportStatement)
                {
                    throw new ParserException(
                              executable.FirstToken,
                              this.Locale.Strings.Get("ALL_IMPORTS_MUST_OCCUR_AT_BEGINNING_OF_FILE"));
                }

                executable.NamespacePrefixSearch = namespaceImports;
                executable.LibraryName           = libraryName;

                if (executable is Namespace)
                {
                    ((Namespace)executable).GetFlattenedCode(executables, namespaceImports, libraryName);
                }
                else
                {
                    executables.Add(executable);
                }
            }

            return(executables.ToArray());
        }
Ejemplo n.º 26
0
		private static Executable ParseStruct(TokenStream tokens, Executable owner)
		{
			Token structToken = tokens.PopExpected("struct");
			Token structNameToken = tokens.Pop();
			Parser.VerifyIdentifier(structNameToken);

			tokens.PopExpected("{");

			List<Token> fieldTokens = new List<Token>();
			List<Annotation> typeAnnotations = new List<Annotation>();
			bool nextForbidden = false;
			while (!tokens.PopIfPresent("}"))
			{
				if (nextForbidden) tokens.PopExpected("}"); // crash

				Annotation annotation = tokens.IsNext("@") ? AnnotationParser.ParseAnnotation(tokens) : null;

				Token fieldToken = tokens.Pop();
				Parser.VerifyIdentifier(fieldToken);
				nextForbidden = !tokens.PopIfPresent(",");
				fieldTokens.Add(fieldToken);
				typeAnnotations.Add(annotation);
			}

			return new StructDefinition(structToken, structNameToken, fieldTokens, typeAnnotations, owner);
		}