Example #1
0
        /// <summary>
        ///     Validates the code content of a TextReader and returns the top of the compilation unit syntax tree.
        ///     If parsing resulted in syntax errors the result will be <c>null</c>.
        /// </summary>
        /// <param name="stream">The TextReader to parse code from.</param>
        /// <returns>Top level node of an LSL syntax tree.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="stream"/> is <c>null</c>.</exception>
        public ILSLCompilationUnitNode Validate(TextReader stream)
        {
            if (stream == null)
            {
                throw new ArgumentNullException("stream");
            }

            HasSyntaxErrors = false;
            var inputStream = new AntlrInputStream(stream);

            var lexer = new LSLLexer(inputStream);

            lexer.RemoveErrorListeners();

            var tokenStream = new CommonTokenStream(lexer);

            var parser = new LSLParser(tokenStream);

            parser.RemoveErrorListeners();

            parser.AddErrorListener(_antlrParserErrorHandler);

            var parseTree = parser.compilationUnit();


            if (parser.NumberOfSyntaxErrors > 0)
            {
                HasSyntaxErrors = true;
                return(null);
            }

            try
            {
                var tree = _validatorVisitor.ValidateAndBuildTree(parseTree, lexer.Comments);

                if (_validatorVisitor.HasSyntaxWarnings)
                {
                    HasSyntaxWarnings = true;
                }

                if (tree.HasErrors)
                {
                    HasSyntaxErrors = true;
                    return(null);
                }

                return(tree);
            }
            finally
            {
                _validatorVisitor.Reset();
            }
        }
Example #2
0
        public VM.CompiledScript Compile(ICharStream input)
        {
            try
            {
                LSLTreeAdaptor lslAdaptor = new LSLTreeAdaptor();


                //
                // Initial parse and AST creation
                //
                LSLLexer          lex    = new LSLLexer(input);
                CommonTokenStream tokens = new CommonTokenStream(lex);
                LSLParser         p      = new LSLParser(tokens);
                p.TreeAdaptor        = lslAdaptor;
                p.TraceDestination   = _traceRedirect;
                lex.TraceDestination = _traceRedirect;
                LSLParser.prog_return r = p.prog();

                if (p.NumberOfSyntaxErrors > 0)
                {
                    _listener.Error(Convert.ToString(p.NumberOfSyntaxErrors) + " syntax error(s)");
                    return(null);
                }


                //
                // Definitions
                //
                CommonTree           t     = (CommonTree)r.Tree;
                CommonTreeNodeStream nodes = new CommonTreeNodeStream(lslAdaptor, t);
                nodes.TokenStream = tokens;

                SymbolTable symtab = new SymbolTable(tokens, Defaults.SystemMethods.Values, DefaultConstants.Constants.Values);
                symtab.StatusListener = _listener;

                Def def = new Def(nodes, symtab);
                def.TraceDestination = _traceRedirect;
                def.Downup(t);

                nodes.Reset();

                if (_listener.HasErrors() || def.NumberOfSyntaxErrors > 0)
                {
                    return(null);
                }


                //
                // Type and more semantic checks
                //
                Compiler.Types types = new Compiler.Types(nodes, symtab);
                types.TraceDestination = _traceRedirect;
                types.Downup(t);

                nodes.Reset();

                if (_listener.HasErrors() || types.NumberOfSyntaxErrors > 0)
                {
                    return(null);
                }


                StringTemplateGroup templates;
                using (TextReader fr = new StreamReader(Path.Combine(_templatePath, "ByteCode.stg")))
                {
                    templates = new StringTemplateGroup(fr);
                    fr.Close();
                }

                if (_outputAstGraph)
                {
                    DotTreeGenerator dotgen = new DotTreeGenerator();
                    string           dot    = dotgen.ToDot(t);

                    TextWriter tw = new StreamWriter("ast.txt");
                    tw.WriteLine(dot);
                    tw.Close();
                }

                Analyze analyze = new Analyze(nodes, symtab);
                analyze.TraceDestination = _traceRedirect;
                analyze.Downup(t);

                nodes.Reset();

                foreach (Compiler.BranchAnalyze.FunctionBranch b in analyze.FunctionBranches.Where(pred => pred.Type != null))
                {
                    if (!b.AllCodePathsReturn())
                    {
                        if (_listener != null)
                        {
                            _listener.Error("line: " + b.Node.Line + ":" +
                                            b.Node.CharPositionInLine + " " + b.Node.Text + "(): Not all control paths return a value");
                        }
                    }
                }

                if (_listener.HasErrors() || analyze.NumberOfSyntaxErrors > 0)
                {
                    return(null);
                }


                //
                // Bytecode generation
                //
                Gen g = new Gen(nodes, symtab);
                g.TemplateGroup    = templates;
                g.TraceDestination = _traceRedirect;

                Gen.script_return ret = g.script();

                if (_listener.HasErrors() || g.NumberOfSyntaxErrors > 0)
                {
                    return(null);
                }

                if (ret.Template == null)
                {
                    return(null);
                }

                StringTemplate template = ret.Template;

                if (_byteCodeDebugging)
                {
                    _byteCode = template.ToString();
                }

                //
                // Bytecode compilation
                //
                AssemblerLexer    alex    = new AssemblerLexer(new ANTLRStringStream(template.ToString()));
                CommonTokenStream atokens = new CommonTokenStream(alex);
                AssemblerParser   ap      = new AssemblerParser(atokens);
                BytecodeGenerator bcgen   = new BytecodeGenerator(Defaults.SystemMethods.Values);

                ap.SetGenerator(bcgen);
                ap.TraceDestination = _traceRedirect;

                try
                {
                    ap.program();

                    if (_listener.HasErrors() || p.NumberOfSyntaxErrors > 0)
                    {
                        _listener.Error(Convert.ToString(ap.NumberOfSyntaxErrors) + " bytecode generation error(s)");
                        return(null);
                    }

                    return(bcgen.Result);
                }
                catch (GenerationException e)
                {
                    _listener.Error(e.Message);
                }

                return(null);
            }
            catch (TooManyErrorsException e)
            {
                _listener.Error(String.Format("Too many errors {0}", e.InnerException.Message));
            }
            catch (RecognitionException e)
            {
                _listener.Error("line: " + e.Line.ToString() + ":" + e.CharPositionInLine.ToString() + " " + e.Message);
            }
            catch (Exception e)
            {
                string message = e.Message;

                while ((e = e.InnerException) != null)
                {
                    message += "\n" + e.Message;
                }

                _listener.Error(message);
            }

            return(null);
        }
Example #3
0
        public string Compile(ICharStream input)
        {
            try
            {
                LSLTreeAdaptor lslAdaptor = new LSLTreeAdaptor();

                LSLLexer          lex    = new LSLLexer(input);
                CommonTokenStream tokens = new CommonTokenStream(lex);
                LSLParser         p      = new LSLParser(tokens);
                p.TreeAdaptor        = lslAdaptor;
                p.TraceDestination   = _traceDestination;
                lex.TraceDestination = _traceDestination;
                LSLParser.prog_return r = p.prog();

                if (p.NumberOfSyntaxErrors > 0)
                {
                    if (_listener != null)
                    {
                        _listener.Error(Convert.ToString(p.NumberOfSyntaxErrors) + " syntax error(s)");
                    }

                    return(null);
                }

                CommonTree           t     = (CommonTree)r.Tree;
                CommonTreeNodeStream nodes = new CommonTreeNodeStream(lslAdaptor, t);
                nodes.TokenStream = tokens;

                SymbolTable symtab = new SymbolTable(tokens, Defaults.SystemMethods.Values, DefaultConstants.Constants.Values);

                if (this.Listener != null)
                {
                    symtab.StatusListener = this.Listener;
                }

                Def def = new Def(nodes, symtab);
                def.TraceDestination = _traceDestination;
                def.Downup(t);

                CommonTreeNodeStream nodes2 = new CommonTreeNodeStream(lslAdaptor, t);
                nodes2.TokenStream = tokens;

                Types types = new Types(nodes2, symtab);
                types.TraceDestination = _traceDestination;
                types.Downup(t);

                if (_listener != null)
                {
                    if (_listener.HasErrors())
                    {
                        return(null);
                    }
                }

                CommonTreeNodeStream nodes4 = new CommonTreeNodeStream(lslAdaptor, t);
                nodes4.TokenStream = tokens;

                CommonTreeNodeStream nodes3 = new CommonTreeNodeStream(lslAdaptor, t);
                nodes3.TokenStream = tokens;

                TextReader          fr        = new StreamReader("ByteCode.stg");
                StringTemplateGroup templates = new StringTemplateGroup(fr);
                fr.Close();

                DotTreeGenerator dotgen = new DotTreeGenerator();
                string           dot    = dotgen.ToDot(t);

                TextWriter tw = new StreamWriter("ast.txt");
                tw.WriteLine(dot);
                tw.Close();

                Analyze analyze = new Analyze(nodes4, symtab);
                types.TraceDestination = _traceDestination;
                analyze.Downup(t);

                foreach (FunctionBranch b in analyze.FunctionBranches.Where(pred => pred.Type != null))
                {
                    if (!b.AllCodePathsReturn())
                    {
                        if (_listener != null)
                        {
                            _listener.Error("line: " + b.Node.Line + ":" +
                                            b.Node.CharPositionInLine + " " + b.Node.Text + "(): Not all control paths return a value");
                        }
                    }
                }

                Gen g = new Gen(nodes3, symtab);
                g.TemplateGroup    = templates;
                g.TraceDestination = _traceDestination;
                StringTemplate template = g.script().Template;


                if (template != null)
                {
                    string bcOut = template.ToString();
                    Console.WriteLine("** byte code **\n" + bcOut);
                    return(bcOut);
                }
            }
            catch (TooManyErrorsException e)
            {
                if (_listener != null)
                {
                    _listener.Error(String.Format("Too many errors {0}", e.InnerException.Message));
                }
            }
            catch (RecognitionException e)
            {
                if (_listener != null)
                {
                    _listener.Error("line: " + e.Line.ToString() + ":" + e.CharPositionInLine.ToString() + " " + e.Message);
                }
            }
            catch (Exception e)
            {
                if (_listener != null)
                {
                    _listener.Error(e.Message);
                }
            }

            return(null);
        }
Example #4
0
        /// <summary>
        ///     Parses an LSL list from a string and returns the simple expressions it contains as an enumerable.
        ///     <remarks>
        ///         Take note that parsing wont start to occur until you begin enumerating the returned value.
        ///     </remarks>
        /// </summary>
        /// <param name="list">The string containing the list.</param>
        /// <param name="parsingFlags">Optional parsing flags.</param>
        /// <returns>An enumerable of <see cref="ILSLListExpr"/> nodes parsed from the list string.</returns>
        /// <exception cref="LSLListParserOptionsConstraintException">
        ///     When an
        ///     <see cref="LSLListParsingFlags" /> constraint is violated.
        /// </exception>
        /// <exception cref="LSLListParserSyntaxException">
        ///     Rotations must contain only literal values to be parsed, and cannot contain these types of expressions: rotations,
        ///     vectors, lists or strings.
        ///     or
        ///     Vectors must contain only literal values to be parsed, and cannot contain these types of expressions: rotations,
        ///     vectors, lists or strings.
        ///     or
        ///     Lists cannot contain other lists.
        ///     or
        ///     Cast expressions can only be used to specify that a list element is a 'key' and not a 'string'
        ///     or
        ///     Encountered an un-parseable expression in the list, only literal values and possibly variable names are acceptable
        ///     when parsing.
        /// </exception>
        public static IEnumerable <ILSLListExpr> ParseList(string list,
                                                           LSLListParsingFlags parsingFlags = LSLListParsingFlags.None)
        {
            var strm  = new AntlrInputStream(new StringReader(list));
            var lex   = new LSLLexer(strm);
            var parse = new LSLParser(new CommonTokenStream(lex));

            parse.ErrorListeners.Clear();
            lex.ErrorListeners.Clear();

            var errorListener = new ErrorListener();

            parse.AddErrorListener(errorListener);
            parse.AddErrorListener(errorListener);

            var production = parse.listLiteral();

            if (production.expression_list == null)
            {
                throw new LSLListParserSyntaxException("List rule missing expression list, parsing error");
            }

            var listProduction = production.expression_list.expressionList();

            if (listProduction == null)
            {
                yield break;
            }

            foreach (var child in EnumerateExpressionList(listProduction))
            {
                var atomToken        = child as LSLParser.Expr_AtomContext;
                var castExpression   = child as LSLParser.Expr_TypeCastContext;
                var negateOrPositive = child as LSLParser.Expr_PrefixOperationContext;

                if (atomToken != null)
                {
                    var maybeBasic = BasicAtomToExpr(atomToken);
                    if (maybeBasic != null)
                    {
                        yield return(maybeBasic);
                    }

                    if (atomToken.variable != null)
                    {
                        if ((parsingFlags & LSLListParsingFlags.AllowVariableReferencesInList) ==
                            LSLListParsingFlags.AllowVariableReferencesInList)
                        {
                            yield return(new LSLListStringExpr(atomToken.GetText()));
                        }
                        else
                        {
                            throw new LSLListParserOptionsConstraintException(
                                      "Variable references are not allowed in the list.");
                        }
                    }

                    if (atomToken.rotation_literal != null)
                    {
                        yield return(ListExpressionFromRotation(parsingFlags, atomToken));
                    }

                    if (atomToken.vector_literal != null)
                    {
                        yield return(ListExpressionFromVector(parsingFlags, atomToken));
                    }

                    if (atomToken.list_literal != null)
                    {
                        throw new LSLListParserSyntaxException("Lists cannot contain other lists.");
                    }
                }
                else if (castExpression != null)
                {
                    var stringLiteral = castExpression.expr_rvalue as LSLParser.Expr_AtomContext;
                    if (stringLiteral != null && stringLiteral.string_literal != null &&
                        castExpression.cast_type.Text == "key")
                    {
                        yield return(new LSLListKeyExpr(stringLiteral.GetText()));
                    }
                    else
                    {
                        throw new LSLListParserSyntaxException(
                                  "Cast expressions can only be used to specify that a list element is a 'key' and not a 'string'");
                    }
                }
                else if (negateOrPositive != null)
                {
                    var floatOrInt = negateOrPositive.expr_rvalue as LSLParser.Expr_AtomContext;
                    var operation  = negateOrPositive.operation.Text;

                    var validType = floatOrInt != null &&
                                    (floatOrInt.float_literal != null || floatOrInt.integer_literal != null);

                    if (validType && operation == "-" || operation == "+")
                    {
                        yield return(BasicAtomToExpr(floatOrInt, operation));
                    }
                    else
                    {
                        throw new LSLListParserSyntaxException(
                                  string.Format(
                                      "The Negative and Positive prefix operator can only be used on Floats and Integer list elements, operator '{0}' is not valid.",
                                      operation));
                    }
                }
                else
                {
                    throw new LSLListParserSyntaxException(
                              "Encountered an un-parseable expression in the list, only LSL literals and possibly variable names are acceptable list elements.");
                }
            }
        }
Example #5
0
        /// <summary>
        ///     Preforms an auto-complete parse on the specified stream of LSL source code, up to an arbitrary offset.
        /// </summary>
        /// <param name="code">The input source code.</param>
        /// <param name="toOffset">To offset to parse up to (the cursor offset).</param>
        /// <param name="options">Parse options.</param>
        /// <exception cref="ArgumentOutOfRangeException">if <paramref name="toOffset" /> is not greater than zero.</exception>
        /// <exception cref="ArgumentNullException"><paramref name="code" /> is <c>null</c>.</exception>
        public override void Parse(string code, int toOffset, LSLAutoCompleteParseOptions options)
        {
            if (code == null)
            {
                throw new ArgumentNullException("code");
            }

            if (toOffset < 0)
            {
                throw new ArgumentOutOfRangeException("toOffset", "toOffset cannot be less than zero.");
            }

            var detectInStringOrComment = new LSLCommentAndStringDetector(code, toOffset);

            var visitor = new LSLAutoCompleteVisitor(toOffset);

            ParserState = visitor;


            var behind = LookBehindOffset(code, toOffset, 1, 1);



            if ((options & LSLAutoCompleteParseOptions.BlockOnInvalidPrefix) == LSLAutoCompleteParseOptions.BlockOnInvalidPrefix)
            {
                if (!IsValidSuggestionPrefix(behind))
                {
                    visitor.InvalidPrefix = true;

                    return;
                }
            }


            if ((options & LSLAutoCompleteParseOptions.BlockOnInvalidKeywordPrefix) ==
                LSLAutoCompleteParseOptions.BlockOnInvalidKeywordPrefix)
            {
                if (KeywordPriorBlocksCompletion(code, toOffset))
                {
                    visitor.InvalidKeywordPrefix = true;

                    return;
                }
            }


            if (detectInStringOrComment.InComment || detectInStringOrComment.InString)
            {
                visitor.InString       = detectInStringOrComment.InString;
                visitor.InComment      = detectInStringOrComment.InComment;
                visitor.InLineComment  = detectInStringOrComment.InLineComment;
                visitor.InBlockComment = detectInStringOrComment.InBlockComment;
                return;
            }


            var inputStream = new AntlrInputStream(new StringReader(code), toOffset);

            var lexer = new LSLLexer(inputStream);

            var tokenStream = new CommonTokenStream(lexer);

            var parser = new LSLParser(tokenStream);


            parser.RemoveErrorListeners();
            lexer.RemoveErrorListeners();

            visitor.Parse(parser.compilationUnit());
        }