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