/// <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(); } }
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); }
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); }
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; }
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) { _listener.Error(e.Message); } return null; }
/// <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()); }
/// <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."); } } }