aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/LSL/CSCodeGenerator.cs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/LSL/CSCodeGenerator.cs775
1 files changed, 775 insertions, 0 deletions
diff --git a/OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/LSL/CSCodeGenerator.cs b/OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/LSL/CSCodeGenerator.cs
new file mode 100644
index 0000000..142e791
--- /dev/null
+++ b/OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/LSL/CSCodeGenerator.cs
@@ -0,0 +1,775 @@
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.DotNetEngine.Compiler.LSL
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 StateChange)
120 retstr += GenerateStateChange((StateChange) s);
121 else if (s is IfStatement)
122 retstr += GenerateIfStatement((IfStatement) s);
123 else if (s is WhileStatement)
124 retstr += GenerateWhileStatement((WhileStatement) s);
125 else if (s is DoWhileStatement)
126 retstr += GenerateDoWhileStatement((DoWhileStatement) s);
127 else if (s is ForLoop)
128 retstr += GenerateForLoop((ForLoop) s);
129 else if (s is ArgumentList)
130 retstr += GenerateArgumentList((ArgumentList) s);
131 else if (s is Assignment)
132 retstr += GenerateAssignment((Assignment) s);
133 else if (s is BinaryExpression)
134 retstr += GenerateBinaryExpression((BinaryExpression) s);
135 else if (s is ParenthesisExpression)
136 retstr += GenerateParenthesisExpression((ParenthesisExpression) s);
137 else if (s is UnaryExpression)
138 retstr += GenerateUnaryExpression((UnaryExpression) s);
139 else if (s is IncrementDecrementExpression)
140 retstr += GenerateIncrementDecrementExpression((IncrementDecrementExpression) s);
141 else if (s is TypecastExpression)
142 retstr += GenerateTypecastExpression((TypecastExpression) s);
143 else if (s is FunctionCall)
144 retstr += GenerateFunctionCall((FunctionCall) s);
145 else if (s is VectorConstant)
146 retstr += GenerateVectorConstant((VectorConstant) s);
147 else if (s is RotationConstant)
148 retstr += GenerateRotationConstant((RotationConstant) s);
149 else if (s is ListConstant)
150 retstr += GenerateListConstant((ListConstant) s);
151 else if (s is Constant)
152 retstr += GenerateConstant((Constant) s);
153 else if (s is IdentDotExpression)
154 retstr += ((IdentDotExpression) s).Name + "." + ((IdentDotExpression) s).Member;
155 else if (s is IdentExpression)
156 retstr += ((IdentExpression) s).Name;
157 else if (s is IDENT)
158 retstr += ((TOKEN) s).yytext;
159 else
160 {
161 foreach (SYMBOL kid in s.kids)
162 retstr += GenerateNode(kid);
163 }
164
165 return retstr;
166 }
167
168 /// <summary>
169 /// Generates the code for a GlobalFunctionDefinition node.
170 /// </summary>
171 /// <param name="gf">The GlobalFunctionDefinition node.</param>
172 /// <returns>String containing C# code for GlobalFunctionDefinition gf.</returns>
173 private string GenerateGlobalFunctionDefinition(GlobalFunctionDefinition gf)
174 {
175 string retstr = String.Empty;
176
177 // we need to separate the argument declaration list from other kids
178 List<SYMBOL> argumentDeclarationListKids = new List<SYMBOL>();
179 List<SYMBOL> remainingKids = new List<SYMBOL>();
180
181 foreach (SYMBOL kid in gf.kids)
182 if (kid is ArgumentDeclarationList)
183 argumentDeclarationListKids.Add(kid);
184 else
185 remainingKids.Add(kid);
186
187 retstr += WriteIndented(String.Format("{0} {1}(", gf.ReturnType, gf.Name));
188
189 // print the state arguments, if any
190 foreach (SYMBOL kid in argumentDeclarationListKids)
191 retstr += GenerateArgumentDeclarationList((ArgumentDeclarationList) kid);
192
193 retstr += ")\n";
194
195 foreach (SYMBOL kid in remainingKids)
196 retstr += GenerateNode(kid);
197
198 return retstr;
199 }
200
201 /// <summary>
202 /// Generates the code for a GlobalVariableDeclaration node.
203 /// </summary>
204 /// <param name="gv">The GlobalVariableDeclaration node.</param>
205 /// <returns>String containing C# code for GlobalVariableDeclaration gv.</returns>
206 private string GenerateGlobalVariableDeclaration(GlobalVariableDeclaration gv)
207 {
208 string retstr = String.Empty;
209
210 foreach (SYMBOL s in gv.kids)
211 {
212 retstr += Indent();
213 retstr += GenerateNode(s);
214 retstr += ";\n";
215 }
216
217 return retstr;
218 }
219
220 /// <summary>
221 /// Generates the code for a State node.
222 /// </summary>
223 /// <param name="s">The State node.</param>
224 /// <returns>String containing C# code for State s.</returns>
225 private string GenerateState(State s)
226 {
227 string retstr = String.Empty;
228
229 foreach (SYMBOL kid in s.kids)
230 if (kid is StateEvent)
231 retstr += GenerateStateEvent((StateEvent) kid, s.Name);
232 else
233 retstr += String.Format("ERROR: State '{0}' contains a '{1}\n", s.Name, kid.GetType());
234
235 return retstr;
236 }
237
238 /// <summary>
239 /// Generates the code for a StateEvent node.
240 /// </summary>
241 /// <param name="se">The StateEvent node.</param>
242 /// <param name="parentStateName">The name of the parent state.</param>
243 /// <returns>String containing C# code for StateEvent se.</returns>
244 private string GenerateStateEvent(StateEvent se, string parentStateName)
245 {
246 string retstr = String.Empty;
247
248 // we need to separate the argument declaration list from other kids
249 List<SYMBOL> argumentDeclarationListKids = new List<SYMBOL>();
250 List<SYMBOL> remainingKids = new List<SYMBOL>();
251
252 foreach (SYMBOL kid in se.kids)
253 if (kid is ArgumentDeclarationList)
254 argumentDeclarationListKids.Add(kid);
255 else
256 remainingKids.Add(kid);
257
258 // "state" (function) declaration
259 retstr += WriteIndented(String.Format("public void {0}_event_{1}(", parentStateName, se.Name));
260
261 // print the state arguments, if any
262 foreach (SYMBOL kid in argumentDeclarationListKids)
263 retstr += GenerateArgumentDeclarationList((ArgumentDeclarationList) kid);
264
265 retstr += ")\n";
266
267 foreach (SYMBOL kid in remainingKids)
268 retstr += GenerateNode(kid);
269
270 return retstr;
271 }
272
273 /// <summary>
274 /// Generates the code for an ArgumentDeclarationList node.
275 /// </summary>
276 /// <param name="adl">The ArgumentDeclarationList node.</param>
277 /// <returns>String containing C# code for SYMBOL s.</returns>
278 private string GenerateArgumentDeclarationList(ArgumentDeclarationList adl)
279 {
280 string retstr = String.Empty;
281
282 int comma = adl.kids.Count - 1; // tells us whether to print a comma
283
284 foreach (Declaration d in adl.kids)
285 {
286 retstr += String.Format("{0} {1}", d.Datatype, d.Id);
287 if (0 < comma--)
288 retstr += ", ";
289 }
290
291 return retstr;
292 }
293
294 /// <summary>
295 /// Generates the code for an ArgumentList node.
296 /// </summary>
297 /// <param name="al">The ArgumentList node.</param>
298 /// <returns>String containing C# code for SYMBOL s.</returns>
299 private string GenerateArgumentList(ArgumentList al)
300 {
301 string retstr = String.Empty;
302
303 int comma = al.kids.Count - 1; // tells us whether to print a comma
304
305 foreach (SYMBOL s in al.kids)
306 {
307 retstr += GenerateNode(s);
308 if (0 < comma--)
309 retstr += ", ";
310 }
311
312 return retstr;
313 }
314
315 /// <summary>
316 /// Generates the code for a CompoundStatement node.
317 /// </summary>
318 /// <param name="cs">The CompoundStatement node.</param>
319 /// <returns>String containing C# code for SYMBOL s.</returns>
320 private string GenerateCompoundStatement(CompoundStatement cs)
321 {
322 string retstr = String.Empty;
323
324 // opening brace
325 retstr += WriteIndentedLine("{");
326 m_braceCount++;
327
328 foreach (SYMBOL kid in cs.kids)
329 retstr += GenerateNode(kid);
330
331 // closing brace
332 m_braceCount--;
333 retstr += WriteIndentedLine("}");
334
335 return retstr;
336 }
337
338 /// <summary>
339 /// Generates the code for a Declaration node.
340 /// </summary>
341 /// <param name="d">The Declaration node.</param>
342 /// <returns>String containing C# code for SYMBOL s.</returns>
343 private string GenerateDeclaration(Declaration d)
344 {
345 return String.Format("{0} {1}", d.Datatype, d.Id);
346 }
347
348 /// <summary>
349 /// Generates the code for a Statement node.
350 /// </summary>
351 /// <param name="s">The Statement node.</param>
352 /// <returns>String containing C# code for SYMBOL s.</returns>
353 private string GenerateStatement(Statement s)
354 {
355 string retstr = String.Empty;
356
357 retstr += Indent();
358
359 foreach (SYMBOL kid in s.kids)
360 retstr += GenerateNode(kid);
361
362 retstr += ";\n";
363
364 return retstr;
365 }
366
367 /// <summary>
368 /// Generates the code for an Assignment node.
369 /// </summary>
370 /// <param name="a">The Assignment node.</param>
371 /// <returns>String containing C# code for SYMBOL s.</returns>
372 private string GenerateAssignment(Assignment a)
373 {
374 string retstr = String.Empty;
375
376 retstr += GenerateNode((SYMBOL) a.kids.Pop());
377 retstr +=String.Format(" {0} ", a.AssignmentType);
378 foreach (SYMBOL kid in a.kids)
379 retstr += GenerateNode(kid);
380
381 return retstr;
382 }
383
384 /// <summary>
385 /// Generates the code for a ReturnStatement node.
386 /// </summary>
387 /// <param name="rs">The ReturnStatement node.</param>
388 /// <returns>String containing C# code for SYMBOL s.</returns>
389 private string GenerateReturnStatement(ReturnStatement rs)
390 {
391 string retstr = String.Empty;
392
393 retstr += "return ";
394
395 foreach (SYMBOL kid in rs.kids)
396 retstr += GenerateNode(kid);
397
398 return retstr;
399 }
400
401 /// <summary>
402 /// Generates the code for a IfStatement node.
403 /// </summary>
404 /// <param name="ifs">The IfStatement node.</param>
405 /// <returns>String containing C# code for SYMBOL s.</returns>
406 private string GenerateIfStatement(IfStatement ifs)
407 {
408 string retstr = String.Empty;
409
410 retstr += WriteIndented("if (");
411 retstr += GenerateNode((SYMBOL) ifs.kids.Pop());
412 retstr += ")\n";
413
414 // CompoundStatement handles indentation itself but we need to do it
415 // otherwise.
416 bool indentHere = ifs.kids.Top is Statement;
417 if (indentHere) m_braceCount++;
418 retstr += GenerateNode((SYMBOL) ifs.kids.Pop());
419 if (indentHere) m_braceCount--;
420
421 if (0 < ifs.kids.Count) // do it again for an else
422 {
423 retstr += WriteIndentedLine("else");
424
425 indentHere = ifs.kids.Top is Statement;
426 if (indentHere) m_braceCount++;
427 retstr += GenerateNode((SYMBOL) ifs.kids.Pop());
428 if (indentHere) m_braceCount--;
429 }
430
431 return retstr;
432 }
433
434 /// <summary>
435 /// Generates the code for a StateChange node.
436 /// </summary>
437 /// <param name="sc">The StateChange node.</param>
438 /// <returns>String containing C# code for SYMBOL s.</returns>
439 private string GenerateStateChange(StateChange sc)
440 {
441 return String.Format("state(\"{0}\")", sc.NewState);
442 }
443
444 /// <summary>
445 /// Generates the code for a WhileStatement node.
446 /// </summary>
447 /// <param name="ws">The WhileStatement node.</param>
448 /// <returns>String containing C# code for SYMBOL s.</returns>
449 private string GenerateWhileStatement(WhileStatement ws)
450 {
451 string retstr = String.Empty;
452
453 retstr += WriteIndented("while (");
454 retstr += GenerateNode((SYMBOL) ws.kids.Pop());
455 retstr += ")\n";
456
457 // CompoundStatement handles indentation itself but we need to do it
458 // otherwise.
459 bool indentHere = ws.kids.Top is Statement;
460 if (indentHere) m_braceCount++;
461 retstr += GenerateNode((SYMBOL) ws.kids.Pop());
462 if (indentHere) m_braceCount--;
463
464 return retstr;
465 }
466
467 /// <summary>
468 /// Generates the code for a DoWhileStatement node.
469 /// </summary>
470 /// <param name="dws">The DoWhileStatement node.</param>
471 /// <returns>String containing C# code for SYMBOL s.</returns>
472 private string GenerateDoWhileStatement(DoWhileStatement dws)
473 {
474 string retstr = String.Empty;
475
476 retstr += WriteIndentedLine("do");
477
478 // CompoundStatement handles indentation itself but we need to do it
479 // otherwise.
480 bool indentHere = dws.kids.Top is Statement;
481 if (indentHere) m_braceCount++;
482 retstr += GenerateNode((SYMBOL) dws.kids.Pop());
483 if (indentHere) m_braceCount--;
484
485 retstr += WriteIndented("while (");
486 retstr += GenerateNode((SYMBOL) dws.kids.Pop());
487 retstr += ");\n";
488
489 return retstr;
490 }
491
492 /// <summary>
493 /// Generates the code for a ForLoop node.
494 /// </summary>
495 /// <param name="fl">The ForLoop node.</param>
496 /// <returns>String containing C# code for SYMBOL s.</returns>
497 private string GenerateForLoop(ForLoop fl)
498 {
499 string retstr = String.Empty;
500
501 retstr += WriteIndented("for (");
502
503 // for ( x = 0 ; x < 10 ; x++ )
504 // ^^^^^^^
505 retstr += GenerateForLoopStatement((ForLoopStatement) fl.kids.Pop());
506 retstr += "; ";
507 // for ( x = 0 ; x < 10 ; x++ )
508 // ^^^^^^^^
509 retstr += GenerateNode((SYMBOL) fl.kids.Pop());
510 retstr += "; ";
511 // for ( x = 0 ; x < 10 ; x++ )
512 // ^^^^^
513 retstr += GenerateForLoopStatement((ForLoopStatement) fl.kids.Pop());
514 retstr += ")\n";
515
516 // CompoundStatement handles indentation itself but we need to do it
517 // otherwise.
518 bool indentHere = fl.kids.Top is Statement;
519 if (indentHere) m_braceCount++;
520 retstr += GenerateNode((SYMBOL) fl.kids.Pop());
521 if (indentHere) m_braceCount--;
522
523 return retstr;
524 }
525
526 /// <summary>
527 /// Generates the code for a ForLoopStatement node.
528 /// </summary>
529 /// <param name="fls">The ForLoopStatement node.</param>
530 /// <returns>String containing C# code for SYMBOL s.</returns>
531 private string GenerateForLoopStatement(ForLoopStatement fls)
532 {
533 string retstr = String.Empty;
534
535 int comma = fls.kids.Count - 1; // tells us whether to print a comma
536
537 foreach (SYMBOL s in fls.kids)
538 {
539 retstr += GenerateNode(s);
540 if (0 < comma--)
541 retstr += ", ";
542 }
543
544 return retstr;
545 }
546
547 /// <summary>
548 /// Generates the code for a BinaryExpression node.
549 /// </summary>
550 /// <param name="be">The BinaryExpression node.</param>
551 /// <returns>String containing C# code for SYMBOL s.</returns>
552 private string GenerateBinaryExpression(BinaryExpression be)
553 {
554 string retstr = String.Empty;
555
556 retstr += GenerateNode((SYMBOL) be.kids.Pop());
557 retstr += String.Format(" {0} ", be.ExpressionSymbol);
558 foreach (SYMBOL kid in be.kids)
559 retstr += GenerateNode(kid);
560
561 return retstr;
562 }
563
564 /// <summary>
565 /// Generates the code for a UnaryExpression node.
566 /// </summary>
567 /// <param name="ue">The UnaryExpression node.</param>
568 /// <returns>String containing C# code for SYMBOL s.</returns>
569 private string GenerateUnaryExpression(UnaryExpression ue)
570 {
571 string retstr = String.Empty;
572
573 retstr += ue.UnarySymbol;
574 retstr += GenerateNode((SYMBOL) ue.kids.Pop());
575
576 return retstr;
577 }
578
579 /// <summary>
580 /// Generates the code for a ParenthesisExpression node.
581 /// </summary>
582 /// <param name="pe">The ParenthesisExpression node.</param>
583 /// <returns>String containing C# code for SYMBOL s.</returns>
584 private string GenerateParenthesisExpression(ParenthesisExpression pe)
585 {
586 string retstr = String.Empty;
587
588 retstr += "(";
589 foreach (SYMBOL kid in pe.kids)
590 retstr += GenerateNode(kid);
591 retstr += ")";
592
593 return retstr;
594 }
595
596 /// <summary>
597 /// Generates the code for a IncrementDecrementExpression node.
598 /// </summary>
599 /// <param name="ide">The IncrementDecrementExpression node.</param>
600 /// <returns>String containing C# code for SYMBOL s.</returns>
601 private string GenerateIncrementDecrementExpression(IncrementDecrementExpression ide)
602 {
603 string retstr = String.Empty;
604
605 if (0 < ide.kids.Count)
606 {
607 IdentDotExpression dot = (IdentDotExpression) ide.kids.Top;
608 retstr += String.Format("{0}", ide.PostOperation ? dot.Name + "." + dot.Member + ide.Operation : ide.Operation + dot.Name + "." + dot.Member);
609 }
610 else
611 retstr += String.Format("{0}", ide.PostOperation ? ide.Name + ide.Operation : ide.Operation + ide.Name);
612
613 return retstr;
614 }
615
616 /// <summary>
617 /// Generates the code for a TypecastExpression node.
618 /// </summary>
619 /// <param name="te">The TypecastExpression node.</param>
620 /// <returns>String containing C# code for SYMBOL s.</returns>
621 private string GenerateTypecastExpression(TypecastExpression te)
622 {
623 string retstr = String.Empty;
624
625 // we wrap all typecasted statements in parentheses
626 retstr += String.Format("({0}) (", te.TypecastType);
627 retstr += GenerateNode((SYMBOL) te.kids.Pop());
628 retstr += ")";
629
630 return retstr;
631 }
632
633 /// <summary>
634 /// Generates the code for a FunctionCall node.
635 /// </summary>
636 /// <param name="fc">The FunctionCall node.</param>
637 /// <returns>String containing C# code for SYMBOL s.</returns>
638 private string GenerateFunctionCall(FunctionCall fc)
639 {
640 string retstr = String.Empty;
641
642 retstr += String.Format("{0}(", fc.Id);
643
644 foreach (SYMBOL kid in fc.kids)
645 retstr += GenerateNode(kid);
646
647 retstr += ")";
648
649 return retstr;
650 }
651
652 /// <summary>
653 /// Generates the code for a Constant node.
654 /// </summary>
655 /// <param name="c">The Constant node.</param>
656 /// <returns>String containing C# code for SYMBOL s.</returns>
657 private string GenerateConstant(Constant c)
658 {
659 string retstr = String.Empty;
660
661 // Supprt LSL's weird acceptance of floats with no trailing digits
662 // after the period. Turn float x = 10.; into float x = 10.0;
663 if ("LSL_Types.LSLFloat" == c.Type)
664 {
665 int dotIndex = c.Value.IndexOf('.') + 1;
666 if (0 < dotIndex && (dotIndex == c.Value.Length || !Char.IsDigit(c.Value[dotIndex])))
667 c.Value = c.Value.Insert(dotIndex, "0");
668 }
669
670 // need to quote strings
671 if ("LSL_Types.LSLString" == c.Type)
672 retstr += "\"";
673 retstr += c.Value;
674 if ("LSL_Types.LSLString" == c.Type)
675 retstr += "\"";
676
677 return retstr;
678 }
679
680 /// <summary>
681 /// Generates the code for a VectorConstant node.
682 /// </summary>
683 /// <param name="vc">The VectorConstant node.</param>
684 /// <returns>String containing C# code for SYMBOL s.</returns>
685 private string GenerateVectorConstant(VectorConstant vc)
686 {
687 string retstr = String.Empty;
688
689 retstr += String.Format("new {0}(", vc.Type);
690 retstr += GenerateNode((SYMBOL) vc.kids.Pop());
691 retstr += ", ";
692 retstr += GenerateNode((SYMBOL) vc.kids.Pop());
693 retstr += ", ";
694 retstr += GenerateNode((SYMBOL) vc.kids.Pop());
695 retstr += ")";
696
697 return retstr;
698 }
699
700 /// <summary>
701 /// Generates the code for a RotationConstant node.
702 /// </summary>
703 /// <param name="rc">The RotationConstant node.</param>
704 /// <returns>String containing C# code for SYMBOL s.</returns>
705 private string GenerateRotationConstant(RotationConstant rc)
706 {
707 string retstr = String.Empty;
708
709 retstr += String.Format("new {0}(", rc.Type);
710 retstr += GenerateNode((SYMBOL) rc.kids.Pop());
711 retstr += ", ";
712 retstr += GenerateNode((SYMBOL) rc.kids.Pop());
713 retstr += ", ";
714 retstr += GenerateNode((SYMBOL) rc.kids.Pop());
715 retstr += ", ";
716 retstr += GenerateNode((SYMBOL) rc.kids.Pop());
717 retstr += ")";
718
719 return retstr;
720 }
721
722 /// <summary>
723 /// Generates the code for a ListConstant node.
724 /// </summary>
725 /// <param name="lc">The ListConstant node.</param>
726 /// <returns>String containing C# code for SYMBOL s.</returns>
727 private string GenerateListConstant(ListConstant lc)
728 {
729 string retstr = String.Empty;
730
731 retstr += String.Format("new {0}(", lc.Type);
732
733 foreach (SYMBOL kid in lc.kids)
734 retstr += GenerateNode(kid);
735
736 retstr += ")";
737
738 return retstr;
739 }
740
741 /// <summary>
742 /// Prints text correctly indented, followed by a newline.
743 /// </summary>
744 /// <param name="s">String of text to print.</param>
745 /// <returns>String containing C# code for SYMBOL s.</returns>
746 private string WriteIndentedLine(string s)
747 {
748 return WriteIndented(s) + "\n";
749 }
750
751 /// <summary>
752 /// Prints text correctly indented.
753 /// </summary>
754 /// <param name="s">String of text to print.</param>
755 /// <returns>String containing C# code for SYMBOL s.</returns>
756 private string WriteIndented(string s)
757 {
758 return Indent() + s;
759 }
760
761 /// <summary>
762 /// Prints correct indentation.
763 /// </summary>
764 /// <returns>String containing C# code for SYMBOL s.</returns>
765 private string Indent()
766 {
767 string retstr = String.Empty;
768
769 for (int i = 0; i < m_braceCount; i++)
770 retstr += " ";
771
772 return retstr;
773 }
774 }
775}