aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ScriptEngine/Shared/CodeTools/CSCodeGenerator.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/ScriptEngine/Shared/CodeTools/CSCodeGenerator.cs')
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/CodeTools/CSCodeGenerator.cs803
1 files changed, 803 insertions, 0 deletions
diff --git a/OpenSim/Region/ScriptEngine/Shared/CodeTools/CSCodeGenerator.cs b/OpenSim/Region/ScriptEngine/Shared/CodeTools/CSCodeGenerator.cs
new file mode 100644
index 0000000..78c636e
--- /dev/null
+++ b/OpenSim/Region/ScriptEngine/Shared/CodeTools/CSCodeGenerator.cs
@@ -0,0 +1,803 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSim Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.IO;
30using System.Collections.Generic;
31using Tools;
32
33namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
34{
35 public class CSCodeGenerator
36 {
37 private SYMBOL m_astRoot = null;
38 private int m_braceCount; // for indentation
39
40 /// <summary>
41 /// Pass the new CodeGenerator a string containing the LSL source.
42 /// </summary>
43 /// <param name="script">String containing LSL source.</param>
44 public CSCodeGenerator(string script)
45 {
46 Parser p = new LSLSyntax();
47 // Obviously this needs to be in a try/except block.
48 LSL2CSCodeTransformer codeTransformer = new LSL2CSCodeTransformer(p.Parse(script));
49 m_astRoot = codeTransformer.Transform();
50 }
51
52 /// <summary>
53 /// Pass the new CodeGenerator an abstract syntax tree.
54 /// </summary>
55 /// <param name="astRoot">The root node of the AST.</param>
56 public CSCodeGenerator(SYMBOL astRoot)
57 {
58 m_braceCount = 0;
59 m_astRoot = astRoot;
60 }
61
62 /// <summary>
63 /// Generate the code from the AST we have.
64 /// </summary>
65 /// <returns>String containing the generated C# code.</returns>
66 public string Generate()
67 {
68 string retstr = String.Empty;
69
70 // standard preamble
71 //retstr = "using OpenSim.Region.ScriptEngine.Common;\n";
72 //retstr += "using System.Collections.Generic;\n\n";
73 //retstr += "namespace SecondLife\n";
74 //retstr += "{\n";
75 //retstr += " public class Script : OpenSim.Region.ScriptEngine.Common\n";
76 //retstr += " {\n";
77
78 // here's the payload
79 m_braceCount += 2;
80 retstr += "\n";
81 foreach (SYMBOL s in m_astRoot.kids)
82 retstr += GenerateNode(s);
83
84 // close braces!
85 //retstr += " }\n";
86 //retstr += "}\n";
87 m_braceCount -= 2;
88
89 return retstr;
90 }
91
92 /// <summary>
93 /// Recursively called to generate each type of node. Will generate this
94 /// node, then all it's children.
95 /// </summary>
96 /// <param name="s">The current node to generate code for.</param>
97 /// <returns>String containing C# code for SYMBOL s.</returns>
98 private string GenerateNode(SYMBOL s)
99 {
100 string retstr = String.Empty;
101
102 // make sure to put type lower in the inheritance hierarchy first
103 // ie: since IdentArgument and ExpressionArgument inherit from
104 // Argument, put IdentArgument and ExpressionArgument before Argument
105 if (s is GlobalFunctionDefinition)
106 retstr += GenerateGlobalFunctionDefinition((GlobalFunctionDefinition) s);
107 else if (s is GlobalVariableDeclaration)
108 retstr += GenerateGlobalVariableDeclaration((GlobalVariableDeclaration) s);
109 else if (s is State)
110 retstr += GenerateState((State) s);
111 else if (s is CompoundStatement)
112 retstr += GenerateCompoundStatement((CompoundStatement) s);
113 else if (s is Declaration)
114 retstr += GenerateDeclaration((Declaration) s);
115 else if (s is Statement)
116 retstr += GenerateStatement((Statement) s);
117 else if (s is ReturnStatement)
118 retstr += GenerateReturnStatement((ReturnStatement) s);
119 else if (s is JumpLabel)
120 retstr += GenerateJumpLabel((JumpLabel) s);
121 else if (s is JumpStatement)
122 retstr += GenerateJumpStatement((JumpStatement) s);
123 else if (s is StateChange)
124 retstr += GenerateStateChange((StateChange) s);
125 else if (s is IfStatement)
126 retstr += GenerateIfStatement((IfStatement) s);
127 else if (s is WhileStatement)
128 retstr += GenerateWhileStatement((WhileStatement) s);
129 else if (s is DoWhileStatement)
130 retstr += GenerateDoWhileStatement((DoWhileStatement) s);
131 else if (s is ForLoop)
132 retstr += GenerateForLoop((ForLoop) s);
133 else if (s is ArgumentList)
134 retstr += GenerateArgumentList((ArgumentList) s);
135 else if (s is Assignment)
136 retstr += GenerateAssignment((Assignment) s);
137 else if (s is BinaryExpression)
138 retstr += GenerateBinaryExpression((BinaryExpression) s);
139 else if (s is ParenthesisExpression)
140 retstr += GenerateParenthesisExpression((ParenthesisExpression) s);
141 else if (s is UnaryExpression)
142 retstr += GenerateUnaryExpression((UnaryExpression) s);
143 else if (s is IncrementDecrementExpression)
144 retstr += GenerateIncrementDecrementExpression((IncrementDecrementExpression) s);
145 else if (s is TypecastExpression)
146 retstr += GenerateTypecastExpression((TypecastExpression) s);
147 else if (s is FunctionCall)
148 retstr += GenerateFunctionCall((FunctionCall) s);
149 else if (s is VectorConstant)
150 retstr += GenerateVectorConstant((VectorConstant) s);
151 else if (s is RotationConstant)
152 retstr += GenerateRotationConstant((RotationConstant) s);
153 else if (s is ListConstant)
154 retstr += GenerateListConstant((ListConstant) s);
155 else if (s is Constant)
156 retstr += GenerateConstant((Constant) s);
157 else if (s is IdentDotExpression)
158 retstr += ((IdentDotExpression) s).Name + "." + ((IdentDotExpression) s).Member;
159 else if (s is IdentExpression)
160 retstr += ((IdentExpression) s).Name;
161 else if (s is IDENT)
162 retstr += ((TOKEN) s).yytext;
163 else
164 {
165 foreach (SYMBOL kid in s.kids)
166 retstr += GenerateNode(kid);
167 }
168
169 return retstr;
170 }
171
172 /// <summary>
173 /// Generates the code for a GlobalFunctionDefinition node.
174 /// </summary>
175 /// <param name="gf">The GlobalFunctionDefinition node.</param>
176 /// <returns>String containing C# code for GlobalFunctionDefinition gf.</returns>
177 private string GenerateGlobalFunctionDefinition(GlobalFunctionDefinition gf)
178 {
179 string retstr = String.Empty;
180
181 // we need to separate the argument declaration list from other kids
182 List<SYMBOL> argumentDeclarationListKids = new List<SYMBOL>();
183 List<SYMBOL> remainingKids = new List<SYMBOL>();
184
185 foreach (SYMBOL kid in gf.kids)
186 if (kid is ArgumentDeclarationList)
187 argumentDeclarationListKids.Add(kid);
188 else
189 remainingKids.Add(kid);
190
191 retstr += WriteIndented(String.Format("{0} {1}(", gf.ReturnType, gf.Name));
192
193 // print the state arguments, if any
194 foreach (SYMBOL kid in argumentDeclarationListKids)
195 retstr += GenerateArgumentDeclarationList((ArgumentDeclarationList) kid);
196
197 retstr += ")\n";
198
199 foreach (SYMBOL kid in remainingKids)
200 retstr += GenerateNode(kid);
201
202 return retstr;
203 }
204
205 /// <summary>
206 /// Generates the code for a GlobalVariableDeclaration node.
207 /// </summary>
208 /// <param name="gv">The GlobalVariableDeclaration node.</param>
209 /// <returns>String containing C# code for GlobalVariableDeclaration gv.</returns>
210 private string GenerateGlobalVariableDeclaration(GlobalVariableDeclaration gv)
211 {
212 string retstr = String.Empty;
213
214 foreach (SYMBOL s in gv.kids)
215 {
216 retstr += Indent();
217 retstr += GenerateNode(s);
218 retstr += ";\n";
219 }
220
221 return retstr;
222 }
223
224 /// <summary>
225 /// Generates the code for a State node.
226 /// </summary>
227 /// <param name="s">The State node.</param>
228 /// <returns>String containing C# code for State s.</returns>
229 private string GenerateState(State s)
230 {
231 string retstr = String.Empty;
232
233 foreach (SYMBOL kid in s.kids)
234 if (kid is StateEvent)
235 retstr += GenerateStateEvent((StateEvent) kid, s.Name);
236 else
237 retstr += String.Format("ERROR: State '{0}' contains a '{1}\n", s.Name, kid.GetType());
238
239 return retstr;
240 }
241
242 /// <summary>
243 /// Generates the code for a StateEvent node.
244 /// </summary>
245 /// <param name="se">The StateEvent node.</param>
246 /// <param name="parentStateName">The name of the parent state.</param>
247 /// <returns>String containing C# code for StateEvent se.</returns>
248 private string GenerateStateEvent(StateEvent se, string parentStateName)
249 {
250 string retstr = String.Empty;
251
252 // we need to separate the argument declaration list from other kids
253 List<SYMBOL> argumentDeclarationListKids = new List<SYMBOL>();
254 List<SYMBOL> remainingKids = new List<SYMBOL>();
255
256 foreach (SYMBOL kid in se.kids)
257 if (kid is ArgumentDeclarationList)
258 argumentDeclarationListKids.Add(kid);
259 else
260 remainingKids.Add(kid);
261
262 // "state" (function) declaration
263 retstr += WriteIndented(String.Format("public void {0}_event_{1}(", parentStateName, se.Name));
264
265 // print the state arguments, if any
266 foreach (SYMBOL kid in argumentDeclarationListKids)
267 retstr += GenerateArgumentDeclarationList((ArgumentDeclarationList) kid);
268
269 retstr += ")\n";
270
271 foreach (SYMBOL kid in remainingKids)
272 retstr += GenerateNode(kid);
273
274 return retstr;
275 }
276
277 /// <summary>
278 /// Generates the code for an ArgumentDeclarationList node.
279 /// </summary>
280 /// <param name="adl">The ArgumentDeclarationList node.</param>
281 /// <returns>String containing C# code for SYMBOL s.</returns>
282 private string GenerateArgumentDeclarationList(ArgumentDeclarationList adl)
283 {
284 string retstr = String.Empty;
285
286 int comma = adl.kids.Count - 1; // tells us whether to print a comma
287
288 foreach (Declaration d in adl.kids)
289 {
290 retstr += String.Format("{0} {1}", d.Datatype, d.Id);
291 if (0 < comma--)
292 retstr += ", ";
293 }
294
295 return retstr;
296 }
297
298 /// <summary>
299 /// Generates the code for an ArgumentList node.
300 /// </summary>
301 /// <param name="al">The ArgumentList node.</param>
302 /// <returns>String containing C# code for SYMBOL s.</returns>
303 private string GenerateArgumentList(ArgumentList al)
304 {
305 string retstr = String.Empty;
306
307 int comma = al.kids.Count - 1; // tells us whether to print a comma
308
309 foreach (SYMBOL s in al.kids)
310 {
311 retstr += GenerateNode(s);
312 if (0 < comma--)
313 retstr += ", ";
314 }
315
316 return retstr;
317 }
318
319 /// <summary>
320 /// Generates the code for a CompoundStatement node.
321 /// </summary>
322 /// <param name="cs">The CompoundStatement node.</param>
323 /// <returns>String containing C# code for SYMBOL s.</returns>
324 private string GenerateCompoundStatement(CompoundStatement cs)
325 {
326 string retstr = String.Empty;
327
328 // opening brace
329 retstr += WriteIndentedLine("{");
330 m_braceCount++;
331
332 foreach (SYMBOL kid in cs.kids)
333 retstr += GenerateNode(kid);
334
335 // closing brace
336 m_braceCount--;
337 retstr += WriteIndentedLine("}");
338
339 return retstr;
340 }
341
342 /// <summary>
343 /// Generates the code for a Declaration node.
344 /// </summary>
345 /// <param name="d">The Declaration node.</param>
346 /// <returns>String containing C# code for SYMBOL s.</returns>
347 private string GenerateDeclaration(Declaration d)
348 {
349 return String.Format("{0} {1}", d.Datatype, d.Id);
350 }
351
352 /// <summary>
353 /// Generates the code for a Statement node.
354 /// </summary>
355 /// <param name="s">The Statement node.</param>
356 /// <returns>String containing C# code for SYMBOL s.</returns>
357 private string GenerateStatement(Statement s)
358 {
359 string retstr = String.Empty;
360
361 // Jump label prints its own colon, we don't need a semicolon.
362 bool printSemicolon = !(s.kids.Top is JumpLabel);
363
364 retstr += Indent();
365
366 foreach (SYMBOL kid in s.kids)
367 retstr += GenerateNode(kid);
368
369 if (printSemicolon)
370 retstr += ";\n";
371
372 return retstr;
373 }
374
375 /// <summary>
376 /// Generates the code for an Assignment node.
377 /// </summary>
378 /// <param name="a">The Assignment node.</param>
379 /// <returns>String containing C# code for SYMBOL s.</returns>
380 private string GenerateAssignment(Assignment a)
381 {
382 string retstr = String.Empty;
383
384 retstr += GenerateNode((SYMBOL) a.kids.Pop());
385 retstr +=String.Format(" {0} ", a.AssignmentType);
386 foreach (SYMBOL kid in a.kids)
387 retstr += GenerateNode(kid);
388
389 return retstr;
390 }
391
392 /// <summary>
393 /// Generates the code for a ReturnStatement node.
394 /// </summary>
395 /// <param name="rs">The ReturnStatement node.</param>
396 /// <returns>String containing C# code for SYMBOL s.</returns>
397 private string GenerateReturnStatement(ReturnStatement rs)
398 {
399 string retstr = String.Empty;
400
401 retstr += "return ";
402
403 foreach (SYMBOL kid in rs.kids)
404 retstr += GenerateNode(kid);
405
406 return retstr;
407 }
408
409 /// <summary>
410 /// Generates the code for a JumpLabel node.
411 /// </summary>
412 /// <param name="jl">The JumpLabel node.</param>
413 /// <returns>String containing C# code for SYMBOL s.</returns>
414 private string GenerateJumpLabel(JumpLabel jl)
415 {
416 return String.Format("{0}:\n", jl.LabelName);
417 }
418
419 /// <summary>
420 /// Generates the code for a JumpStatement node.
421 /// </summary>
422 /// <param name="js">The JumpStatement node.</param>
423 /// <returns>String containing C# code for SYMBOL s.</returns>
424 private string GenerateJumpStatement(JumpStatement js)
425 {
426 return String.Format("goto {0}", js.TargetName);
427 }
428
429 /// <summary>
430 /// Generates the code for a IfStatement node.
431 /// </summary>
432 /// <param name="ifs">The IfStatement node.</param>
433 /// <returns>String containing C# code for SYMBOL s.</returns>
434 private string GenerateIfStatement(IfStatement ifs)
435 {
436 string retstr = String.Empty;
437
438 retstr += WriteIndented("if (");
439 retstr += GenerateNode((SYMBOL) ifs.kids.Pop());
440 retstr += ")\n";
441
442 // CompoundStatement handles indentation itself but we need to do it
443 // otherwise.
444 bool indentHere = ifs.kids.Top is Statement;
445 if (indentHere) m_braceCount++;
446 retstr += GenerateNode((SYMBOL) ifs.kids.Pop());
447 if (indentHere) m_braceCount--;
448
449 if (0 < ifs.kids.Count) // do it again for an else
450 {
451 retstr += WriteIndentedLine("else");
452
453 indentHere = ifs.kids.Top is Statement;
454 if (indentHere) m_braceCount++;
455 retstr += GenerateNode((SYMBOL) ifs.kids.Pop());
456 if (indentHere) m_braceCount--;
457 }
458
459 return retstr;
460 }
461
462 /// <summary>
463 /// Generates the code for a StateChange node.
464 /// </summary>
465 /// <param name="sc">The StateChange node.</param>
466 /// <returns>String containing C# code for SYMBOL s.</returns>
467 private string GenerateStateChange(StateChange sc)
468 {
469 return String.Format("state(\"{0}\")", sc.NewState);
470 }
471
472 /// <summary>
473 /// Generates the code for a WhileStatement node.
474 /// </summary>
475 /// <param name="ws">The WhileStatement node.</param>
476 /// <returns>String containing C# code for SYMBOL s.</returns>
477 private string GenerateWhileStatement(WhileStatement ws)
478 {
479 string retstr = String.Empty;
480
481 retstr += WriteIndented("while (");
482 retstr += GenerateNode((SYMBOL) ws.kids.Pop());
483 retstr += ")\n";
484
485 // CompoundStatement handles indentation itself but we need to do it
486 // otherwise.
487 bool indentHere = ws.kids.Top is Statement;
488 if (indentHere) m_braceCount++;
489 retstr += GenerateNode((SYMBOL) ws.kids.Pop());
490 if (indentHere) m_braceCount--;
491
492 return retstr;
493 }
494
495 /// <summary>
496 /// Generates the code for a DoWhileStatement node.
497 /// </summary>
498 /// <param name="dws">The DoWhileStatement node.</param>
499 /// <returns>String containing C# code for SYMBOL s.</returns>
500 private string GenerateDoWhileStatement(DoWhileStatement dws)
501 {
502 string retstr = String.Empty;
503
504 retstr += WriteIndentedLine("do");
505
506 // CompoundStatement handles indentation itself but we need to do it
507 // otherwise.
508 bool indentHere = dws.kids.Top is Statement;
509 if (indentHere) m_braceCount++;
510 retstr += GenerateNode((SYMBOL) dws.kids.Pop());
511 if (indentHere) m_braceCount--;
512
513 retstr += WriteIndented("while (");
514 retstr += GenerateNode((SYMBOL) dws.kids.Pop());
515 retstr += ");\n";
516
517 return retstr;
518 }
519
520 /// <summary>
521 /// Generates the code for a ForLoop node.
522 /// </summary>
523 /// <param name="fl">The ForLoop node.</param>
524 /// <returns>String containing C# code for SYMBOL s.</returns>
525 private string GenerateForLoop(ForLoop fl)
526 {
527 string retstr = String.Empty;
528
529 retstr += WriteIndented("for (");
530
531 // for ( x = 0 ; x < 10 ; x++ )
532 // ^^^^^^^
533 retstr += GenerateForLoopStatement((ForLoopStatement) fl.kids.Pop());
534 retstr += "; ";
535 // for ( x = 0 ; x < 10 ; x++ )
536 // ^^^^^^^^
537 retstr += GenerateNode((SYMBOL) fl.kids.Pop());
538 retstr += "; ";
539 // for ( x = 0 ; x < 10 ; x++ )
540 // ^^^^^
541 retstr += GenerateForLoopStatement((ForLoopStatement) fl.kids.Pop());
542 retstr += ")\n";
543
544 // CompoundStatement handles indentation itself but we need to do it
545 // otherwise.
546 bool indentHere = fl.kids.Top is Statement;
547 if (indentHere) m_braceCount++;
548 retstr += GenerateNode((SYMBOL) fl.kids.Pop());
549 if (indentHere) m_braceCount--;
550
551 return retstr;
552 }
553
554 /// <summary>
555 /// Generates the code for a ForLoopStatement node.
556 /// </summary>
557 /// <param name="fls">The ForLoopStatement node.</param>
558 /// <returns>String containing C# code for SYMBOL s.</returns>
559 private string GenerateForLoopStatement(ForLoopStatement fls)
560 {
561 string retstr = String.Empty;
562
563 int comma = fls.kids.Count - 1; // tells us whether to print a comma
564
565 foreach (SYMBOL s in fls.kids)
566 {
567 retstr += GenerateNode(s);
568 if (0 < comma--)
569 retstr += ", ";
570 }
571
572 return retstr;
573 }
574
575 /// <summary>
576 /// Generates the code for a BinaryExpression node.
577 /// </summary>
578 /// <param name="be">The BinaryExpression node.</param>
579 /// <returns>String containing C# code for SYMBOL s.</returns>
580 private string GenerateBinaryExpression(BinaryExpression be)
581 {
582 string retstr = String.Empty;
583
584 retstr += GenerateNode((SYMBOL) be.kids.Pop());
585 retstr += String.Format(" {0} ", be.ExpressionSymbol);
586 foreach (SYMBOL kid in be.kids)
587 retstr += GenerateNode(kid);
588
589 return retstr;
590 }
591
592 /// <summary>
593 /// Generates the code for a UnaryExpression node.
594 /// </summary>
595 /// <param name="ue">The UnaryExpression node.</param>
596 /// <returns>String containing C# code for SYMBOL s.</returns>
597 private string GenerateUnaryExpression(UnaryExpression ue)
598 {
599 string retstr = String.Empty;
600
601 retstr += ue.UnarySymbol;
602 retstr += GenerateNode((SYMBOL) ue.kids.Pop());
603
604 return retstr;
605 }
606
607 /// <summary>
608 /// Generates the code for a ParenthesisExpression node.
609 /// </summary>
610 /// <param name="pe">The ParenthesisExpression node.</param>
611 /// <returns>String containing C# code for SYMBOL s.</returns>
612 private string GenerateParenthesisExpression(ParenthesisExpression pe)
613 {
614 string retstr = String.Empty;
615
616 retstr += "(";
617 foreach (SYMBOL kid in pe.kids)
618 retstr += GenerateNode(kid);
619 retstr += ")";
620
621 return retstr;
622 }
623
624 /// <summary>
625 /// Generates the code for a IncrementDecrementExpression node.
626 /// </summary>
627 /// <param name="ide">The IncrementDecrementExpression node.</param>
628 /// <returns>String containing C# code for SYMBOL s.</returns>
629 private string GenerateIncrementDecrementExpression(IncrementDecrementExpression ide)
630 {
631 string retstr = String.Empty;
632
633 if (0 < ide.kids.Count)
634 {
635 IdentDotExpression dot = (IdentDotExpression) ide.kids.Top;
636 retstr += String.Format("{0}", ide.PostOperation ? dot.Name + "." + dot.Member + ide.Operation : ide.Operation + dot.Name + "." + dot.Member);
637 }
638 else
639 retstr += String.Format("{0}", ide.PostOperation ? ide.Name + ide.Operation : ide.Operation + ide.Name);
640
641 return retstr;
642 }
643
644 /// <summary>
645 /// Generates the code for a TypecastExpression node.
646 /// </summary>
647 /// <param name="te">The TypecastExpression node.</param>
648 /// <returns>String containing C# code for SYMBOL s.</returns>
649 private string GenerateTypecastExpression(TypecastExpression te)
650 {
651 string retstr = String.Empty;
652
653 // we wrap all typecasted statements in parentheses
654 retstr += String.Format("({0}) (", te.TypecastType);
655 retstr += GenerateNode((SYMBOL) te.kids.Pop());
656 retstr += ")";
657
658 return retstr;
659 }
660
661 /// <summary>
662 /// Generates the code for a FunctionCall node.
663 /// </summary>
664 /// <param name="fc">The FunctionCall node.</param>
665 /// <returns>String containing C# code for SYMBOL s.</returns>
666 private string GenerateFunctionCall(FunctionCall fc)
667 {
668 string retstr = String.Empty;
669
670 retstr += String.Format("{0}(", fc.Id);
671
672 foreach (SYMBOL kid in fc.kids)
673 retstr += GenerateNode(kid);
674
675 retstr += ")";
676
677 return retstr;
678 }
679
680 /// <summary>
681 /// Generates the code for a Constant node.
682 /// </summary>
683 /// <param name="c">The Constant node.</param>
684 /// <returns>String containing C# code for SYMBOL s.</returns>
685 private string GenerateConstant(Constant c)
686 {
687 string retstr = String.Empty;
688
689 // Supprt LSL's weird acceptance of floats with no trailing digits
690 // after the period. Turn float x = 10.; into float x = 10.0;
691 if ("LSL_Types.LSLFloat" == c.Type)
692 {
693 int dotIndex = c.Value.IndexOf('.') + 1;
694 if (0 < dotIndex && (dotIndex == c.Value.Length || !Char.IsDigit(c.Value[dotIndex])))
695 c.Value = c.Value.Insert(dotIndex, "0");
696 }
697
698 // need to quote strings
699 if ("LSL_Types.LSLString" == c.Type)
700 retstr += "\"";
701 retstr += c.Value;
702 if ("LSL_Types.LSLString" == c.Type)
703 retstr += "\"";
704
705 return retstr;
706 }
707
708 /// <summary>
709 /// Generates the code for a VectorConstant node.
710 /// </summary>
711 /// <param name="vc">The VectorConstant node.</param>
712 /// <returns>String containing C# code for SYMBOL s.</returns>
713 private string GenerateVectorConstant(VectorConstant vc)
714 {
715 string retstr = String.Empty;
716
717 retstr += String.Format("new {0}(", vc.Type);
718 retstr += GenerateNode((SYMBOL) vc.kids.Pop());
719 retstr += ", ";
720 retstr += GenerateNode((SYMBOL) vc.kids.Pop());
721 retstr += ", ";
722 retstr += GenerateNode((SYMBOL) vc.kids.Pop());
723 retstr += ")";
724
725 return retstr;
726 }
727
728 /// <summary>
729 /// Generates the code for a RotationConstant node.
730 /// </summary>
731 /// <param name="rc">The RotationConstant node.</param>
732 /// <returns>String containing C# code for SYMBOL s.</returns>
733 private string GenerateRotationConstant(RotationConstant rc)
734 {
735 string retstr = String.Empty;
736
737 retstr += String.Format("new {0}(", rc.Type);
738 retstr += GenerateNode((SYMBOL) rc.kids.Pop());
739 retstr += ", ";
740 retstr += GenerateNode((SYMBOL) rc.kids.Pop());
741 retstr += ", ";
742 retstr += GenerateNode((SYMBOL) rc.kids.Pop());
743 retstr += ", ";
744 retstr += GenerateNode((SYMBOL) rc.kids.Pop());
745 retstr += ")";
746
747 return retstr;
748 }
749
750 /// <summary>
751 /// Generates the code for a ListConstant node.
752 /// </summary>
753 /// <param name="lc">The ListConstant node.</param>
754 /// <returns>String containing C# code for SYMBOL s.</returns>
755 private string GenerateListConstant(ListConstant lc)
756 {
757 string retstr = String.Empty;
758
759 retstr += String.Format("new {0}(", lc.Type);
760
761 foreach (SYMBOL kid in lc.kids)
762 retstr += GenerateNode(kid);
763
764 retstr += ")";
765
766 return retstr;
767 }
768
769 /// <summary>
770 /// Prints text correctly indented, followed by a newline.
771 /// </summary>
772 /// <param name="s">String of text to print.</param>
773 /// <returns>String containing C# code for SYMBOL s.</returns>
774 private string WriteIndentedLine(string s)
775 {
776 return WriteIndented(s) + "\n";
777 }
778
779 /// <summary>
780 /// Prints text correctly indented.
781 /// </summary>
782 /// <param name="s">String of text to print.</param>
783 /// <returns>String containing C# code for SYMBOL s.</returns>
784 private string WriteIndented(string s)
785 {
786 return Indent() + s;
787 }
788
789 /// <summary>
790 /// Prints correct indentation.
791 /// </summary>
792 /// <returns>String containing C# code for SYMBOL s.</returns>
793 private string Indent()
794 {
795 string retstr = String.Empty;
796
797 for (int i = 0; i < m_braceCount; i++)
798 retstr += " ";
799
800 return retstr;
801 }
802 }
803}