Files
opensim/OpenSim/Region/ScriptEngine/Shared/CodeTools/CSCodeGenerator.cs
Melanie Thielker a5d2674a43 This is an attempt to fix the handling of constants in LSL.
It wraps constants in new LSLType(x), so that lists with
constant values are processed correctly. Contains changes to
the lsl.parser.cs that are not (yet) reflected in opensim-libs,
since this experimental patch affects XEngine only. Also contains
nuts.
2008-09-01 23:33:12 +00:00

946 lines
35 KiB
C#

/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSim Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.IO;
using System.Collections.Generic;
using Tools;
namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
{
public class CSCodeGenerator : ICodeConverter
{
private SYMBOL m_astRoot = null;
private Dictionary<KeyValuePair<int, int>, KeyValuePair<int, int>> m_positionMap;
private int m_indentWidth = 4; // for indentation
private int m_braceCount; // for indentation
private int m_CSharpLine; // the current line of generated C# code
private int m_CSharpCol; // the current column of generated C# code
/// <summary>
/// Creates an 'empty' CSCodeGenerator instance.
/// </summary>
public CSCodeGenerator()
{
ResetCounters();
}
/// <summary>
/// Get the mapping between LSL and C# line/column number.
/// </summary>
/// <returns>Dictionary\<KeyValuePair\<int, int\>, KeyValuePair\<int, int\>\>.</returns>
public Dictionary<KeyValuePair<int, int>, KeyValuePair<int, int>> PositionMap
{
get { return m_positionMap; }
}
/// <summary>
/// Get the mapping between LSL and C# line/column number.
/// </summary>
/// <returns>SYMBOL pointing to root of the abstract syntax tree.</returns>
public SYMBOL ASTRoot
{
get { return m_astRoot; }
}
/// <summary>
/// Resets various counters and metadata.
/// </summary>
private void ResetCounters()
{
m_braceCount = 0;
m_CSharpLine = 0;
m_CSharpCol = 1;
m_positionMap = new Dictionary<KeyValuePair<int, int>, KeyValuePair<int, int>>();
m_astRoot = null;
}
/// <summary>
/// Generate the code from the AST we have.
/// </summary>
/// <param name="script">The LSL source as a string.</param>
/// <returns>String containing the generated C# code.</returns>
public string Convert(string script)
{
ResetCounters();
Parser p = new LSLSyntax(new yyLSLSyntax(), new ErrorHandler(true));
// Obviously this needs to be in a try/except block.
LSL2CSCodeTransformer codeTransformer = new LSL2CSCodeTransformer(p.Parse(script));
m_astRoot = codeTransformer.Transform();
string retstr = String.Empty;
// standard preamble
//retstr = GenerateLine("using OpenSim.Region.ScriptEngine.Common;");
//retstr += GenerateLine("using System.Collections.Generic;");
//retstr += GenerateLine("");
//retstr += GenerateLine("namespace SecondLife");
//retstr += GenerateLine("{");
m_braceCount++;
//retstr += GenerateIndentedLine("public class Script : OpenSim.Region.ScriptEngine.Common");
//retstr += GenerateIndentedLine("{");
m_braceCount++;
// line number
m_CSharpLine += 3;
// here's the payload
retstr += GenerateLine();
foreach (SYMBOL s in m_astRoot.kids)
retstr += GenerateNode(s);
// close braces!
m_braceCount--;
//retstr += GenerateIndentedLine("}");
m_braceCount--;
//retstr += GenerateLine("}");
return retstr;
}
/// <summary>
/// Recursively called to generate each type of node. Will generate this
/// node, then all it's children.
/// </summary>
/// <param name="s">The current node to generate code for.</param>
/// <returns>String containing C# code for SYMBOL s.</returns>
private string GenerateNode(SYMBOL s)
{
string retstr = String.Empty;
// make sure to put type lower in the inheritance hierarchy first
// ie: since IdentArgument and ExpressionArgument inherit from
// Argument, put IdentArgument and ExpressionArgument before Argument
if (s is GlobalFunctionDefinition)
retstr += GenerateGlobalFunctionDefinition((GlobalFunctionDefinition) s);
else if (s is GlobalVariableDeclaration)
retstr += GenerateGlobalVariableDeclaration((GlobalVariableDeclaration) s);
else if (s is State)
retstr += GenerateState((State) s);
else if (s is CompoundStatement)
retstr += GenerateCompoundStatement((CompoundStatement) s);
else if (s is Declaration)
retstr += GenerateDeclaration((Declaration) s);
else if (s is Statement)
retstr += GenerateStatement((Statement) s);
else if (s is ReturnStatement)
retstr += GenerateReturnStatement((ReturnStatement) s);
else if (s is JumpLabel)
retstr += GenerateJumpLabel((JumpLabel) s);
else if (s is JumpStatement)
retstr += GenerateJumpStatement((JumpStatement) s);
else if (s is StateChange)
retstr += GenerateStateChange((StateChange) s);
else if (s is IfStatement)
retstr += GenerateIfStatement((IfStatement) s);
else if (s is WhileStatement)
retstr += GenerateWhileStatement((WhileStatement) s);
else if (s is DoWhileStatement)
retstr += GenerateDoWhileStatement((DoWhileStatement) s);
else if (s is ForLoop)
retstr += GenerateForLoop((ForLoop) s);
else if (s is ArgumentList)
retstr += GenerateArgumentList((ArgumentList) s);
else if (s is Assignment)
retstr += GenerateAssignment((Assignment) s);
else if (s is BinaryExpression)
retstr += GenerateBinaryExpression((BinaryExpression) s);
else if (s is ParenthesisExpression)
retstr += GenerateParenthesisExpression((ParenthesisExpression) s);
else if (s is UnaryExpression)
retstr += GenerateUnaryExpression((UnaryExpression) s);
else if (s is IncrementDecrementExpression)
retstr += GenerateIncrementDecrementExpression((IncrementDecrementExpression) s);
else if (s is TypecastExpression)
retstr += GenerateTypecastExpression((TypecastExpression) s);
else if (s is FunctionCall)
retstr += GenerateFunctionCall((FunctionCall) s);
else if (s is VectorConstant)
retstr += GenerateVectorConstant((VectorConstant) s);
else if (s is RotationConstant)
retstr += GenerateRotationConstant((RotationConstant) s);
else if (s is ListConstant)
retstr += GenerateListConstant((ListConstant) s);
else if (s is Constant)
retstr += GenerateConstant((Constant) s);
else if (s is IdentDotExpression)
retstr += Generate(((IdentDotExpression) s).Name + "." + ((IdentDotExpression) s).Member, s);
else if (s is IdentExpression)
retstr += Generate(((IdentExpression) s).Name, s);
else if (s is IDENT)
retstr += Generate(((TOKEN) s).yytext, s);
else
{
foreach (SYMBOL kid in s.kids)
retstr += GenerateNode(kid);
}
return retstr;
}
/// <summary>
/// Generates the code for a GlobalFunctionDefinition node.
/// </summary>
/// <param name="gf">The GlobalFunctionDefinition node.</param>
/// <returns>String containing C# code for GlobalFunctionDefinition gf.</returns>
private string GenerateGlobalFunctionDefinition(GlobalFunctionDefinition gf)
{
string retstr = String.Empty;
// we need to separate the argument declaration list from other kids
List<SYMBOL> argumentDeclarationListKids = new List<SYMBOL>();
List<SYMBOL> remainingKids = new List<SYMBOL>();
foreach (SYMBOL kid in gf.kids)
if (kid is ArgumentDeclarationList)
argumentDeclarationListKids.Add(kid);
else
remainingKids.Add(kid);
retstr += GenerateIndented(String.Format("{0} {1}(", gf.ReturnType, gf.Name), gf);
// print the state arguments, if any
foreach (SYMBOL kid in argumentDeclarationListKids)
retstr += GenerateArgumentDeclarationList((ArgumentDeclarationList) kid);
retstr += GenerateLine(")");
foreach (SYMBOL kid in remainingKids)
retstr += GenerateNode(kid);
return retstr;
}
/// <summary>
/// Generates the code for a GlobalVariableDeclaration node.
/// </summary>
/// <param name="gv">The GlobalVariableDeclaration node.</param>
/// <returns>String containing C# code for GlobalVariableDeclaration gv.</returns>
private string GenerateGlobalVariableDeclaration(GlobalVariableDeclaration gv)
{
string retstr = String.Empty;
foreach (SYMBOL s in gv.kids)
{
retstr += Indent();
retstr += GenerateNode(s);
retstr += GenerateLine(";");
}
return retstr;
}
/// <summary>
/// Generates the code for a State node.
/// </summary>
/// <param name="s">The State node.</param>
/// <returns>String containing C# code for State s.</returns>
private string GenerateState(State s)
{
string retstr = String.Empty;
foreach (SYMBOL kid in s.kids)
if (kid is StateEvent)
retstr += GenerateStateEvent((StateEvent) kid, s.Name);
return retstr;
}
/// <summary>
/// Generates the code for a StateEvent node.
/// </summary>
/// <param name="se">The StateEvent node.</param>
/// <param name="parentStateName">The name of the parent state.</param>
/// <returns>String containing C# code for StateEvent se.</returns>
private string GenerateStateEvent(StateEvent se, string parentStateName)
{
string retstr = String.Empty;
// we need to separate the argument declaration list from other kids
List<SYMBOL> argumentDeclarationListKids = new List<SYMBOL>();
List<SYMBOL> remainingKids = new List<SYMBOL>();
foreach (SYMBOL kid in se.kids)
if (kid is ArgumentDeclarationList)
argumentDeclarationListKids.Add(kid);
else
remainingKids.Add(kid);
// "state" (function) declaration
retstr += GenerateIndented(String.Format("public void {0}_event_{1}(", parentStateName, se.Name), se);
// print the state arguments, if any
foreach (SYMBOL kid in argumentDeclarationListKids)
retstr += GenerateArgumentDeclarationList((ArgumentDeclarationList) kid);
retstr += GenerateLine(")");
foreach (SYMBOL kid in remainingKids)
retstr += GenerateNode(kid);
return retstr;
}
/// <summary>
/// Generates the code for an ArgumentDeclarationList node.
/// </summary>
/// <param name="adl">The ArgumentDeclarationList node.</param>
/// <returns>String containing C# code for ArgumentDeclarationList adl.</returns>
private string GenerateArgumentDeclarationList(ArgumentDeclarationList adl)
{
string retstr = String.Empty;
int comma = adl.kids.Count - 1; // tells us whether to print a comma
foreach (Declaration d in adl.kids)
{
retstr += Generate(String.Format("{0} {1}", d.Datatype, d.Id), d);
if (0 < comma--)
retstr += Generate(", ");
}
return retstr;
}
/// <summary>
/// Generates the code for an ArgumentList node.
/// </summary>
/// <param name="al">The ArgumentList node.</param>
/// <returns>String containing C# code for ArgumentList al.</returns>
private string GenerateArgumentList(ArgumentList al)
{
string retstr = String.Empty;
int comma = al.kids.Count - 1; // tells us whether to print a comma
foreach (SYMBOL s in al.kids)
{
retstr += GenerateNode(s);
if (0 < comma--)
retstr += Generate(", ");
}
return retstr;
}
/// <summary>
/// Generates the code for a CompoundStatement node.
/// </summary>
/// <param name="cs">The CompoundStatement node.</param>
/// <returns>String containing C# code for CompoundStatement cs.</returns>
private string GenerateCompoundStatement(CompoundStatement cs)
{
string retstr = String.Empty;
// opening brace
retstr += GenerateIndentedLine("{");
m_braceCount++;
foreach (SYMBOL kid in cs.kids)
retstr += GenerateNode(kid);
// closing brace
m_braceCount--;
retstr += GenerateIndentedLine("}");
return retstr;
}
/// <summary>
/// Generates the code for a Declaration node.
/// </summary>
/// <param name="d">The Declaration node.</param>
/// <returns>String containing C# code for Declaration d.</returns>
private string GenerateDeclaration(Declaration d)
{
return Generate(String.Format("{0} {1}", d.Datatype, d.Id), d);
}
/// <summary>
/// Generates the code for a Statement node.
/// </summary>
/// <param name="s">The Statement node.</param>
/// <returns>String containing C# code for Statement s.</returns>
private string GenerateStatement(Statement s)
{
string retstr = String.Empty;
bool printSemicolon = true;
retstr += Indent();
if (0 < s.kids.Count)
{
// Jump label prints its own colon, we don't need a semicolon.
printSemicolon = !(s.kids.Top is JumpLabel);
foreach (SYMBOL kid in s.kids)
retstr += GenerateNode(kid);
}
if (printSemicolon)
retstr += GenerateLine(";");
return retstr;
}
/// <summary>
/// Generates the code for an Assignment node.
/// </summary>
/// <param name="a">The Assignment node.</param>
/// <returns>String containing C# code for Assignment a.</returns>
private string GenerateAssignment(Assignment a)
{
string retstr = String.Empty;
retstr += GenerateNode((SYMBOL) a.kids.Pop());
retstr += Generate(String.Format(" {0} ", a.AssignmentType), a);
foreach (SYMBOL kid in a.kids)
retstr += GenerateNode(kid);
return retstr;
}
/// <summary>
/// Generates the code for a ReturnStatement node.
/// </summary>
/// <param name="rs">The ReturnStatement node.</param>
/// <returns>String containing C# code for ReturnStatement rs.</returns>
private string GenerateReturnStatement(ReturnStatement rs)
{
string retstr = String.Empty;
retstr += Generate("return ", rs);
foreach (SYMBOL kid in rs.kids)
retstr += GenerateNode(kid);
return retstr;
}
/// <summary>
/// Generates the code for a JumpLabel node.
/// </summary>
/// <param name="jl">The JumpLabel node.</param>
/// <returns>String containing C# code for JumpLabel jl.</returns>
private string GenerateJumpLabel(JumpLabel jl)
{
return Generate(String.Format("{0}:\n", jl.LabelName), jl);
}
/// <summary>
/// Generates the code for a JumpStatement node.
/// </summary>
/// <param name="js">The JumpStatement node.</param>
/// <returns>String containing C# code for JumpStatement js.</returns>
private string GenerateJumpStatement(JumpStatement js)
{
return Generate(String.Format("goto {0}", js.TargetName), js);
}
/// <summary>
/// Generates the code for an IfStatement node.
/// </summary>
/// <param name="ifs">The IfStatement node.</param>
/// <returns>String containing C# code for IfStatement ifs.</returns>
private string GenerateIfStatement(IfStatement ifs)
{
string retstr = String.Empty;
retstr += GenerateIndented("if (", ifs);
retstr += GenerateNode((SYMBOL) ifs.kids.Pop());
retstr += GenerateLine(")");
// CompoundStatement handles indentation itself but we need to do it
// otherwise.
bool indentHere = ifs.kids.Top is Statement;
if (indentHere) m_braceCount++;
retstr += GenerateNode((SYMBOL) ifs.kids.Pop());
if (indentHere) m_braceCount--;
if (0 < ifs.kids.Count) // do it again for an else
{
retstr += GenerateIndentedLine("else", ifs);
indentHere = ifs.kids.Top is Statement;
if (indentHere) m_braceCount++;
retstr += GenerateNode((SYMBOL) ifs.kids.Pop());
if (indentHere) m_braceCount--;
}
return retstr;
}
/// <summary>
/// Generates the code for a StateChange node.
/// </summary>
/// <param name="sc">The StateChange node.</param>
/// <returns>String containing C# code for StateChange sc.</returns>
private string GenerateStateChange(StateChange sc)
{
return Generate(String.Format("state(\"{0}\")", sc.NewState), sc);
}
/// <summary>
/// Generates the code for a WhileStatement node.
/// </summary>
/// <param name="ws">The WhileStatement node.</param>
/// <returns>String containing C# code for WhileStatement ws.</returns>
private string GenerateWhileStatement(WhileStatement ws)
{
string retstr = String.Empty;
retstr += GenerateIndented("while (", ws);
retstr += GenerateNode((SYMBOL) ws.kids.Pop());
retstr += GenerateLine(")");
// CompoundStatement handles indentation itself but we need to do it
// otherwise.
bool indentHere = ws.kids.Top is Statement;
if (indentHere) m_braceCount++;
retstr += GenerateNode((SYMBOL) ws.kids.Pop());
if (indentHere) m_braceCount--;
return retstr;
}
/// <summary>
/// Generates the code for a DoWhileStatement node.
/// </summary>
/// <param name="dws">The DoWhileStatement node.</param>
/// <returns>String containing C# code for DoWhileStatement dws.</returns>
private string GenerateDoWhileStatement(DoWhileStatement dws)
{
string retstr = String.Empty;
retstr += GenerateIndentedLine("do", dws);
// CompoundStatement handles indentation itself but we need to do it
// otherwise.
bool indentHere = dws.kids.Top is Statement;
if (indentHere) m_braceCount++;
retstr += GenerateNode((SYMBOL) dws.kids.Pop());
if (indentHere) m_braceCount--;
retstr += GenerateIndented("while (", dws);
retstr += GenerateNode((SYMBOL) dws.kids.Pop());
retstr += GenerateLine(");");
return retstr;
}
/// <summary>
/// Generates the code for a ForLoop node.
/// </summary>
/// <param name="fl">The ForLoop node.</param>
/// <returns>String containing C# code for ForLoop fl.</returns>
private string GenerateForLoop(ForLoop fl)
{
string retstr = String.Empty;
retstr += GenerateIndented("for (", fl);
// for ( x = 0 ; x < 10 ; x++ )
// ^^^^^^^
retstr += GenerateForLoopStatement((ForLoopStatement) fl.kids.Pop());
retstr += Generate("; ");
// for ( x = 0 ; x < 10 ; x++ )
// ^^^^^^^^
retstr += GenerateNode((SYMBOL) fl.kids.Pop());
retstr += Generate("; ");
// for ( x = 0 ; x < 10 ; x++ )
// ^^^^^
retstr += GenerateForLoopStatement((ForLoopStatement) fl.kids.Pop());
retstr += GenerateLine(")");
// CompoundStatement handles indentation itself but we need to do it
// otherwise.
bool indentHere = fl.kids.Top is Statement;
if (indentHere) m_braceCount++;
retstr += GenerateNode((SYMBOL) fl.kids.Pop());
if (indentHere) m_braceCount--;
return retstr;
}
/// <summary>
/// Generates the code for a ForLoopStatement node.
/// </summary>
/// <param name="fls">The ForLoopStatement node.</param>
/// <returns>String containing C# code for ForLoopStatement fls.</returns>
private string GenerateForLoopStatement(ForLoopStatement fls)
{
string retstr = String.Empty;
int comma = fls.kids.Count - 1; // tells us whether to print a comma
foreach (SYMBOL s in fls.kids)
{
retstr += GenerateNode(s);
if (0 < comma--)
retstr += Generate(", ");
}
return retstr;
}
/// <summary>
/// Generates the code for a BinaryExpression node.
/// </summary>
/// <param name="be">The BinaryExpression node.</param>
/// <returns>String containing C# code for BinaryExpression be.</returns>
private string GenerateBinaryExpression(BinaryExpression be)
{
string retstr = String.Empty;
retstr += GenerateNode((SYMBOL) be.kids.Pop());
retstr += Generate(String.Format(" {0} ", be.ExpressionSymbol), be);
foreach (SYMBOL kid in be.kids)
retstr += GenerateNode(kid);
return retstr;
}
/// <summary>
/// Generates the code for a UnaryExpression node.
/// </summary>
/// <param name="ue">The UnaryExpression node.</param>
/// <returns>String containing C# code for UnaryExpression ue.</returns>
private string GenerateUnaryExpression(UnaryExpression ue)
{
string retstr = String.Empty;
retstr += Generate(ue.UnarySymbol, ue);
retstr += GenerateNode((SYMBOL) ue.kids.Pop());
return retstr;
}
/// <summary>
/// Generates the code for a ParenthesisExpression node.
/// </summary>
/// <param name="pe">The ParenthesisExpression node.</param>
/// <returns>String containing C# code for ParenthesisExpression pe.</returns>
private string GenerateParenthesisExpression(ParenthesisExpression pe)
{
string retstr = String.Empty;
retstr += Generate("(");
foreach (SYMBOL kid in pe.kids)
retstr += GenerateNode(kid);
retstr += Generate(")");
return retstr;
}
/// <summary>
/// Generates the code for a IncrementDecrementExpression node.
/// </summary>
/// <param name="ide">The IncrementDecrementExpression node.</param>
/// <returns>String containing C# code for IncrementDecrementExpression ide.</returns>
private string GenerateIncrementDecrementExpression(IncrementDecrementExpression ide)
{
string retstr = String.Empty;
if (0 < ide.kids.Count)
{
IdentDotExpression dot = (IdentDotExpression) ide.kids.Top;
retstr += Generate(String.Format("{0}", ide.PostOperation ? dot.Name + "." + dot.Member + ide.Operation : ide.Operation + dot.Name + "." + dot.Member), ide);
}
else
retstr += Generate(String.Format("{0}", ide.PostOperation ? ide.Name + ide.Operation : ide.Operation + ide.Name), ide);
return retstr;
}
/// <summary>
/// Generates the code for a TypecastExpression node.
/// </summary>
/// <param name="te">The TypecastExpression node.</param>
/// <returns>String containing C# code for TypecastExpression te.</returns>
private string GenerateTypecastExpression(TypecastExpression te)
{
string retstr = String.Empty;
// we wrap all typecasted statements in parentheses
retstr += Generate(String.Format("({0}) (", te.TypecastType), te);
retstr += GenerateNode((SYMBOL) te.kids.Pop());
retstr += Generate(")");
return retstr;
}
/// <summary>
/// Generates the code for a FunctionCall node.
/// </summary>
/// <param name="fc">The FunctionCall node.</param>
/// <returns>String containing C# code for FunctionCall fc.</returns>
private string GenerateFunctionCall(FunctionCall fc)
{
string retstr = String.Empty;
retstr += Generate(String.Format("{0}(", fc.Id), fc);
foreach (SYMBOL kid in fc.kids)
retstr += GenerateNode(kid);
retstr += Generate(")");
return retstr;
}
/// <summary>
/// Generates the code for a Constant node.
/// </summary>
/// <param name="c">The Constant node.</param>
/// <returns>String containing C# code for Constant c.</returns>
private string GenerateConstant(Constant c)
{
string retstr = String.Empty;
// Supprt LSL's weird acceptance of floats with no trailing digits
// after the period. Turn float x = 10.; into float x = 10.0;
if ("LSL_Types.LSLFloat" == c.Type)
{
int dotIndex = c.Value.IndexOf('.') + 1;
// Skip first dot (in type name)
dotIndex = c.Value.IndexOf('.', dotIndex) + 1;
if (0 < dotIndex && (dotIndex == c.Value.Length || !Char.IsDigit(c.Value[dotIndex])))
c.Value = c.Value.Insert(dotIndex, "0");
}
// commencted because the parser does it now
// need to quote strings
// if ("LSL_Types.LSLString" == c.Type)
// retstr += Generate("\"");
retstr += Generate(c.Value, c);
// if ("LSL_Types.LSLString" == c.Type)
// retstr += Generate("\"");
return retstr;
}
/// <summary>
/// Generates the code for a VectorConstant node.
/// </summary>
/// <param name="vc">The VectorConstant node.</param>
/// <returns>String containing C# code for VectorConstant vc.</returns>
private string GenerateVectorConstant(VectorConstant vc)
{
string retstr = String.Empty;
retstr += Generate(String.Format("new {0}(", vc.Type), vc);
retstr += GenerateNode((SYMBOL) vc.kids.Pop());
retstr += Generate(", ");
retstr += GenerateNode((SYMBOL) vc.kids.Pop());
retstr += Generate(", ");
retstr += GenerateNode((SYMBOL) vc.kids.Pop());
retstr += Generate(")");
return retstr;
}
/// <summary>
/// Generates the code for a RotationConstant node.
/// </summary>
/// <param name="rc">The RotationConstant node.</param>
/// <returns>String containing C# code for RotationConstant rc.</returns>
private string GenerateRotationConstant(RotationConstant rc)
{
string retstr = String.Empty;
retstr += Generate(String.Format("new {0}(", rc.Type), rc);
retstr += GenerateNode((SYMBOL) rc.kids.Pop());
retstr += Generate(", ");
retstr += GenerateNode((SYMBOL) rc.kids.Pop());
retstr += Generate(", ");
retstr += GenerateNode((SYMBOL) rc.kids.Pop());
retstr += Generate(", ");
retstr += GenerateNode((SYMBOL) rc.kids.Pop());
retstr += Generate(")");
return retstr;
}
/// <summary>
/// Generates the code for a ListConstant node.
/// </summary>
/// <param name="lc">The ListConstant node.</param>
/// <returns>String containing C# code for ListConstant lc.</returns>
private string GenerateListConstant(ListConstant lc)
{
string retstr = String.Empty;
retstr += Generate(String.Format("new {0}(", lc.Type), lc);
foreach (SYMBOL kid in lc.kids)
retstr += GenerateNode(kid);
retstr += Generate(")");
return retstr;
}
/// <summary>
/// Prints a newline.
/// </summary>
/// <returns>A newline.</returns>
private string GenerateLine()
{
return GenerateLine("");
}
/// <summary>
/// Prints text, followed by a newline.
/// </summary>
/// <param name="s">String of text to print.</param>
/// <returns>String s followed by newline.</returns>
private string GenerateLine(string s)
{
return GenerateLine(s, null);
}
/// <summary>
/// Prints text, followed by a newline.
/// </summary>
/// <param name="s">String of text to print.</param>
/// <param name="sym">Symbol being generated to extract original line
/// number and column from.</param>
/// <returns>String s followed by newline.</returns>
private string GenerateLine(string s, SYMBOL sym)
{
string retstr = Generate(s, sym) + "\n";
m_CSharpLine++;
m_CSharpCol = 1;
return retstr;
}
/// <summary>
/// Prints text.
/// </summary>
/// <param name="s">String of text to print.</param>
/// <returns>String s.</returns>
private string Generate(string s)
{
return Generate(s, null);
}
/// <summary>
/// Prints text.
/// </summary>
/// <param name="s">String of text to print.</param>
/// <param name="sym">Symbol being generated to extract original line
/// number and column from.</param>
/// <returns>String s.</returns>
private string Generate(string s, SYMBOL sym)
{
if (null != sym)
m_positionMap.Add(new KeyValuePair<int, int>(m_CSharpLine, m_CSharpCol), new KeyValuePair<int, int>(sym.Line, sym.Position));
m_CSharpCol += s.Length;
return s;
}
/// <summary>
/// Prints text correctly indented, followed by a newline.
/// </summary>
/// <param name="s">String of text to print.</param>
/// <returns>Properly indented string s followed by newline.</returns>
private string GenerateIndentedLine(string s)
{
return GenerateIndentedLine(s, null);
}
/// <summary>
/// Prints text correctly indented, followed by a newline.
/// </summary>
/// <param name="s">String of text to print.</param>
/// <param name="sym">Symbol being generated to extract original line
/// number and column from.</param>
/// <returns>Properly indented string s followed by newline.</returns>
private string GenerateIndentedLine(string s, SYMBOL sym)
{
string retstr = GenerateIndented(s, sym) + "\n";
m_CSharpLine++;
m_CSharpCol = 1;
return retstr;
}
/// <summary>
/// Prints text correctly indented.
/// </summary>
/// <param name="s">String of text to print.</param>
/// <returns>Properly indented string s.</returns>
//private string GenerateIndented(string s)
//{
// return GenerateIndented(s, null);
//}
// THIS FUNCTION IS COMMENTED OUT TO SUPPRESS WARNINGS
/// <summary>
/// Prints text correctly indented.
/// </summary>
/// <param name="s">String of text to print.</param>
/// <param name="sym">Symbol being generated to extract original line
/// number and column from.</param>
/// <returns>Properly indented string s.</returns>
private string GenerateIndented(string s, SYMBOL sym)
{
string retstr = Indent() + s;
if (null != sym)
m_positionMap.Add(new KeyValuePair<int, int>(m_CSharpLine, m_CSharpCol), new KeyValuePair<int, int>(sym.Line, sym.Position));
m_CSharpCol += s.Length;
return retstr;
}
/// <summary>
/// Prints correct indentation.
/// </summary>
/// <returns>Indentation based on brace count.</returns>
private string Indent()
{
string retstr = String.Empty;
for (int i = 0; i < m_braceCount; i++)
for (int j = 0; j < m_indentWidth; j++)
{
retstr += " ";
m_CSharpCol++;
}
return retstr;
}
}
}