CSCodeGenerator.cs 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803
  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. using System;
  28. using System.IO;
  29. using System.Collections.Generic;
  30. using Tools;
  31. namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
  32. {
  33. public class CSCodeGenerator
  34. {
  35. private SYMBOL m_astRoot = null;
  36. private int m_braceCount; // for indentation
  37. /// <summary>
  38. /// Pass the new CodeGenerator a string containing the LSL source.
  39. /// </summary>
  40. /// <param name="script">String containing LSL source.</param>
  41. public CSCodeGenerator(string script)
  42. {
  43. Parser p = new LSLSyntax();
  44. // Obviously this needs to be in a try/except block.
  45. LSL2CSCodeTransformer codeTransformer = new LSL2CSCodeTransformer(p.Parse(script));
  46. m_astRoot = codeTransformer.Transform();
  47. }
  48. /// <summary>
  49. /// Pass the new CodeGenerator an abstract syntax tree.
  50. /// </summary>
  51. /// <param name="astRoot">The root node of the AST.</param>
  52. public CSCodeGenerator(SYMBOL astRoot)
  53. {
  54. m_braceCount = 0;
  55. m_astRoot = astRoot;
  56. }
  57. /// <summary>
  58. /// Generate the code from the AST we have.
  59. /// </summary>
  60. /// <returns>String containing the generated C# code.</returns>
  61. public string Generate()
  62. {
  63. string retstr = String.Empty;
  64. // standard preamble
  65. //retstr = "using OpenSim.Region.ScriptEngine.Common;\n";
  66. //retstr += "using System.Collections.Generic;\n\n";
  67. //retstr += "namespace SecondLife\n";
  68. //retstr += "{\n";
  69. //retstr += " public class Script : OpenSim.Region.ScriptEngine.Common\n";
  70. //retstr += " {\n";
  71. // here's the payload
  72. m_braceCount += 2;
  73. retstr += "\n";
  74. foreach (SYMBOL s in m_astRoot.kids)
  75. retstr += GenerateNode(s);
  76. // close braces!
  77. //retstr += " }\n";
  78. //retstr += "}\n";
  79. m_braceCount -= 2;
  80. return retstr;
  81. }
  82. /// <summary>
  83. /// Recursively called to generate each type of node. Will generate this
  84. /// node, then all it's children.
  85. /// </summary>
  86. /// <param name="s">The current node to generate code for.</param>
  87. /// <returns>String containing C# code for SYMBOL s.</returns>
  88. private string GenerateNode(SYMBOL s)
  89. {
  90. string retstr = String.Empty;
  91. // make sure to put type lower in the inheritance hierarchy first
  92. // ie: since IdentArgument and ExpressionArgument inherit from
  93. // Argument, put IdentArgument and ExpressionArgument before Argument
  94. if (s is GlobalFunctionDefinition)
  95. retstr += GenerateGlobalFunctionDefinition((GlobalFunctionDefinition) s);
  96. else if (s is GlobalVariableDeclaration)
  97. retstr += GenerateGlobalVariableDeclaration((GlobalVariableDeclaration) s);
  98. else if (s is State)
  99. retstr += GenerateState((State) s);
  100. else if (s is CompoundStatement)
  101. retstr += GenerateCompoundStatement((CompoundStatement) s);
  102. else if (s is Declaration)
  103. retstr += GenerateDeclaration((Declaration) s);
  104. else if (s is Statement)
  105. retstr += GenerateStatement((Statement) s);
  106. else if (s is ReturnStatement)
  107. retstr += GenerateReturnStatement((ReturnStatement) s);
  108. else if (s is JumpLabel)
  109. retstr += GenerateJumpLabel((JumpLabel) s);
  110. else if (s is JumpStatement)
  111. retstr += GenerateJumpStatement((JumpStatement) s);
  112. else if (s is StateChange)
  113. retstr += GenerateStateChange((StateChange) s);
  114. else if (s is IfStatement)
  115. retstr += GenerateIfStatement((IfStatement) s);
  116. else if (s is WhileStatement)
  117. retstr += GenerateWhileStatement((WhileStatement) s);
  118. else if (s is DoWhileStatement)
  119. retstr += GenerateDoWhileStatement((DoWhileStatement) s);
  120. else if (s is ForLoop)
  121. retstr += GenerateForLoop((ForLoop) s);
  122. else if (s is ArgumentList)
  123. retstr += GenerateArgumentList((ArgumentList) s);
  124. else if (s is Assignment)
  125. retstr += GenerateAssignment((Assignment) s);
  126. else if (s is BinaryExpression)
  127. retstr += GenerateBinaryExpression((BinaryExpression) s);
  128. else if (s is ParenthesisExpression)
  129. retstr += GenerateParenthesisExpression((ParenthesisExpression) s);
  130. else if (s is UnaryExpression)
  131. retstr += GenerateUnaryExpression((UnaryExpression) s);
  132. else if (s is IncrementDecrementExpression)
  133. retstr += GenerateIncrementDecrementExpression((IncrementDecrementExpression) s);
  134. else if (s is TypecastExpression)
  135. retstr += GenerateTypecastExpression((TypecastExpression) s);
  136. else if (s is FunctionCall)
  137. retstr += GenerateFunctionCall((FunctionCall) s);
  138. else if (s is VectorConstant)
  139. retstr += GenerateVectorConstant((VectorConstant) s);
  140. else if (s is RotationConstant)
  141. retstr += GenerateRotationConstant((RotationConstant) s);
  142. else if (s is ListConstant)
  143. retstr += GenerateListConstant((ListConstant) s);
  144. else if (s is Constant)
  145. retstr += GenerateConstant((Constant) s);
  146. else if (s is IdentDotExpression)
  147. retstr += ((IdentDotExpression) s).Name + "." + ((IdentDotExpression) s).Member;
  148. else if (s is IdentExpression)
  149. retstr += ((IdentExpression) s).Name;
  150. else if (s is IDENT)
  151. retstr += ((TOKEN) s).yytext;
  152. else
  153. {
  154. foreach (SYMBOL kid in s.kids)
  155. retstr += GenerateNode(kid);
  156. }
  157. return retstr;
  158. }
  159. /// <summary>
  160. /// Generates the code for a GlobalFunctionDefinition node.
  161. /// </summary>
  162. /// <param name="gf">The GlobalFunctionDefinition node.</param>
  163. /// <returns>String containing C# code for GlobalFunctionDefinition gf.</returns>
  164. private string GenerateGlobalFunctionDefinition(GlobalFunctionDefinition gf)
  165. {
  166. string retstr = String.Empty;
  167. // we need to separate the argument declaration list from other kids
  168. List<SYMBOL> argumentDeclarationListKids = new List<SYMBOL>();
  169. List<SYMBOL> remainingKids = new List<SYMBOL>();
  170. foreach (SYMBOL kid in gf.kids)
  171. if (kid is ArgumentDeclarationList)
  172. argumentDeclarationListKids.Add(kid);
  173. else
  174. remainingKids.Add(kid);
  175. retstr += WriteIndented(String.Format("{0} {1}(", gf.ReturnType, gf.Name));
  176. // print the state arguments, if any
  177. foreach (SYMBOL kid in argumentDeclarationListKids)
  178. retstr += GenerateArgumentDeclarationList((ArgumentDeclarationList) kid);
  179. retstr += ")\n";
  180. foreach (SYMBOL kid in remainingKids)
  181. retstr += GenerateNode(kid);
  182. return retstr;
  183. }
  184. /// <summary>
  185. /// Generates the code for a GlobalVariableDeclaration node.
  186. /// </summary>
  187. /// <param name="gv">The GlobalVariableDeclaration node.</param>
  188. /// <returns>String containing C# code for GlobalVariableDeclaration gv.</returns>
  189. private string GenerateGlobalVariableDeclaration(GlobalVariableDeclaration gv)
  190. {
  191. string retstr = String.Empty;
  192. foreach (SYMBOL s in gv.kids)
  193. {
  194. retstr += Indent();
  195. retstr += GenerateNode(s);
  196. retstr += ";\n";
  197. }
  198. return retstr;
  199. }
  200. /// <summary>
  201. /// Generates the code for a State node.
  202. /// </summary>
  203. /// <param name="s">The State node.</param>
  204. /// <returns>String containing C# code for State s.</returns>
  205. private string GenerateState(State s)
  206. {
  207. string retstr = String.Empty;
  208. foreach (SYMBOL kid in s.kids)
  209. if (kid is StateEvent)
  210. retstr += GenerateStateEvent((StateEvent) kid, s.Name);
  211. else
  212. retstr += String.Format("ERROR: State '{0}' contains a '{1}\n", s.Name, kid.GetType());
  213. return retstr;
  214. }
  215. /// <summary>
  216. /// Generates the code for a StateEvent node.
  217. /// </summary>
  218. /// <param name="se">The StateEvent node.</param>
  219. /// <param name="parentStateName">The name of the parent state.</param>
  220. /// <returns>String containing C# code for StateEvent se.</returns>
  221. private string GenerateStateEvent(StateEvent se, string parentStateName)
  222. {
  223. string retstr = String.Empty;
  224. // we need to separate the argument declaration list from other kids
  225. List<SYMBOL> argumentDeclarationListKids = new List<SYMBOL>();
  226. List<SYMBOL> remainingKids = new List<SYMBOL>();
  227. foreach (SYMBOL kid in se.kids)
  228. if (kid is ArgumentDeclarationList)
  229. argumentDeclarationListKids.Add(kid);
  230. else
  231. remainingKids.Add(kid);
  232. // "state" (function) declaration
  233. retstr += WriteIndented(String.Format("public void {0}_event_{1}(", parentStateName, se.Name));
  234. // print the state arguments, if any
  235. foreach (SYMBOL kid in argumentDeclarationListKids)
  236. retstr += GenerateArgumentDeclarationList((ArgumentDeclarationList) kid);
  237. retstr += ")\n";
  238. foreach (SYMBOL kid in remainingKids)
  239. retstr += GenerateNode(kid);
  240. return retstr;
  241. }
  242. /// <summary>
  243. /// Generates the code for an ArgumentDeclarationList node.
  244. /// </summary>
  245. /// <param name="adl">The ArgumentDeclarationList node.</param>
  246. /// <returns>String containing C# code for SYMBOL s.</returns>
  247. private string GenerateArgumentDeclarationList(ArgumentDeclarationList adl)
  248. {
  249. string retstr = String.Empty;
  250. int comma = adl.kids.Count - 1; // tells us whether to print a comma
  251. foreach (Declaration d in adl.kids)
  252. {
  253. retstr += String.Format("{0} {1}", d.Datatype, d.Id);
  254. if (0 < comma--)
  255. retstr += ", ";
  256. }
  257. return retstr;
  258. }
  259. /// <summary>
  260. /// Generates the code for an ArgumentList node.
  261. /// </summary>
  262. /// <param name="al">The ArgumentList node.</param>
  263. /// <returns>String containing C# code for SYMBOL s.</returns>
  264. private string GenerateArgumentList(ArgumentList al)
  265. {
  266. string retstr = String.Empty;
  267. int comma = al.kids.Count - 1; // tells us whether to print a comma
  268. foreach (SYMBOL s in al.kids)
  269. {
  270. retstr += GenerateNode(s);
  271. if (0 < comma--)
  272. retstr += ", ";
  273. }
  274. return retstr;
  275. }
  276. /// <summary>
  277. /// Generates the code for a CompoundStatement node.
  278. /// </summary>
  279. /// <param name="cs">The CompoundStatement node.</param>
  280. /// <returns>String containing C# code for SYMBOL s.</returns>
  281. private string GenerateCompoundStatement(CompoundStatement cs)
  282. {
  283. string retstr = String.Empty;
  284. // opening brace
  285. retstr += WriteIndentedLine("{");
  286. m_braceCount++;
  287. foreach (SYMBOL kid in cs.kids)
  288. retstr += GenerateNode(kid);
  289. // closing brace
  290. m_braceCount--;
  291. retstr += WriteIndentedLine("}");
  292. return retstr;
  293. }
  294. /// <summary>
  295. /// Generates the code for a Declaration node.
  296. /// </summary>
  297. /// <param name="d">The Declaration node.</param>
  298. /// <returns>String containing C# code for SYMBOL s.</returns>
  299. private string GenerateDeclaration(Declaration d)
  300. {
  301. return String.Format("{0} {1}", d.Datatype, d.Id);
  302. }
  303. /// <summary>
  304. /// Generates the code for a Statement node.
  305. /// </summary>
  306. /// <param name="s">The Statement node.</param>
  307. /// <returns>String containing C# code for SYMBOL s.</returns>
  308. private string GenerateStatement(Statement s)
  309. {
  310. string retstr = String.Empty;
  311. // Jump label prints its own colon, we don't need a semicolon.
  312. bool printSemicolon = !(s.kids.Top is JumpLabel);
  313. retstr += Indent();
  314. foreach (SYMBOL kid in s.kids)
  315. retstr += GenerateNode(kid);
  316. if (printSemicolon)
  317. retstr += ";\n";
  318. return retstr;
  319. }
  320. /// <summary>
  321. /// Generates the code for an Assignment node.
  322. /// </summary>
  323. /// <param name="a">The Assignment node.</param>
  324. /// <returns>String containing C# code for SYMBOL s.</returns>
  325. private string GenerateAssignment(Assignment a)
  326. {
  327. string retstr = String.Empty;
  328. retstr += GenerateNode((SYMBOL) a.kids.Pop());
  329. retstr +=String.Format(" {0} ", a.AssignmentType);
  330. foreach (SYMBOL kid in a.kids)
  331. retstr += GenerateNode(kid);
  332. return retstr;
  333. }
  334. /// <summary>
  335. /// Generates the code for a ReturnStatement node.
  336. /// </summary>
  337. /// <param name="rs">The ReturnStatement node.</param>
  338. /// <returns>String containing C# code for SYMBOL s.</returns>
  339. private string GenerateReturnStatement(ReturnStatement rs)
  340. {
  341. string retstr = String.Empty;
  342. retstr += "return ";
  343. foreach (SYMBOL kid in rs.kids)
  344. retstr += GenerateNode(kid);
  345. return retstr;
  346. }
  347. /// <summary>
  348. /// Generates the code for a JumpLabel node.
  349. /// </summary>
  350. /// <param name="jl">The JumpLabel node.</param>
  351. /// <returns>String containing C# code for SYMBOL s.</returns>
  352. private string GenerateJumpLabel(JumpLabel jl)
  353. {
  354. return String.Format("{0}:\n", jl.LabelName);
  355. }
  356. /// <summary>
  357. /// Generates the code for a JumpStatement node.
  358. /// </summary>
  359. /// <param name="js">The JumpStatement node.</param>
  360. /// <returns>String containing C# code for SYMBOL s.</returns>
  361. private string GenerateJumpStatement(JumpStatement js)
  362. {
  363. return String.Format("goto {0}", js.TargetName);
  364. }
  365. /// <summary>
  366. /// Generates the code for a IfStatement node.
  367. /// </summary>
  368. /// <param name="ifs">The IfStatement node.</param>
  369. /// <returns>String containing C# code for SYMBOL s.</returns>
  370. private string GenerateIfStatement(IfStatement ifs)
  371. {
  372. string retstr = String.Empty;
  373. retstr += WriteIndented("if (");
  374. retstr += GenerateNode((SYMBOL) ifs.kids.Pop());
  375. retstr += ")\n";
  376. // CompoundStatement handles indentation itself but we need to do it
  377. // otherwise.
  378. bool indentHere = ifs.kids.Top is Statement;
  379. if (indentHere) m_braceCount++;
  380. retstr += GenerateNode((SYMBOL) ifs.kids.Pop());
  381. if (indentHere) m_braceCount--;
  382. if (0 < ifs.kids.Count) // do it again for an else
  383. {
  384. retstr += WriteIndentedLine("else");
  385. indentHere = ifs.kids.Top is Statement;
  386. if (indentHere) m_braceCount++;
  387. retstr += GenerateNode((SYMBOL) ifs.kids.Pop());
  388. if (indentHere) m_braceCount--;
  389. }
  390. return retstr;
  391. }
  392. /// <summary>
  393. /// Generates the code for a StateChange node.
  394. /// </summary>
  395. /// <param name="sc">The StateChange node.</param>
  396. /// <returns>String containing C# code for SYMBOL s.</returns>
  397. private string GenerateStateChange(StateChange sc)
  398. {
  399. return String.Format("state(\"{0}\")", sc.NewState);
  400. }
  401. /// <summary>
  402. /// Generates the code for a WhileStatement node.
  403. /// </summary>
  404. /// <param name="ws">The WhileStatement node.</param>
  405. /// <returns>String containing C# code for SYMBOL s.</returns>
  406. private string GenerateWhileStatement(WhileStatement ws)
  407. {
  408. string retstr = String.Empty;
  409. retstr += WriteIndented("while (");
  410. retstr += GenerateNode((SYMBOL) ws.kids.Pop());
  411. retstr += ")\n";
  412. // CompoundStatement handles indentation itself but we need to do it
  413. // otherwise.
  414. bool indentHere = ws.kids.Top is Statement;
  415. if (indentHere) m_braceCount++;
  416. retstr += GenerateNode((SYMBOL) ws.kids.Pop());
  417. if (indentHere) m_braceCount--;
  418. return retstr;
  419. }
  420. /// <summary>
  421. /// Generates the code for a DoWhileStatement node.
  422. /// </summary>
  423. /// <param name="dws">The DoWhileStatement node.</param>
  424. /// <returns>String containing C# code for SYMBOL s.</returns>
  425. private string GenerateDoWhileStatement(DoWhileStatement dws)
  426. {
  427. string retstr = String.Empty;
  428. retstr += WriteIndentedLine("do");
  429. // CompoundStatement handles indentation itself but we need to do it
  430. // otherwise.
  431. bool indentHere = dws.kids.Top is Statement;
  432. if (indentHere) m_braceCount++;
  433. retstr += GenerateNode((SYMBOL) dws.kids.Pop());
  434. if (indentHere) m_braceCount--;
  435. retstr += WriteIndented("while (");
  436. retstr += GenerateNode((SYMBOL) dws.kids.Pop());
  437. retstr += ");\n";
  438. return retstr;
  439. }
  440. /// <summary>
  441. /// Generates the code for a ForLoop node.
  442. /// </summary>
  443. /// <param name="fl">The ForLoop node.</param>
  444. /// <returns>String containing C# code for SYMBOL s.</returns>
  445. private string GenerateForLoop(ForLoop fl)
  446. {
  447. string retstr = String.Empty;
  448. retstr += WriteIndented("for (");
  449. // for ( x = 0 ; x < 10 ; x++ )
  450. // ^^^^^^^
  451. retstr += GenerateForLoopStatement((ForLoopStatement) fl.kids.Pop());
  452. retstr += "; ";
  453. // for ( x = 0 ; x < 10 ; x++ )
  454. // ^^^^^^^^
  455. retstr += GenerateNode((SYMBOL) fl.kids.Pop());
  456. retstr += "; ";
  457. // for ( x = 0 ; x < 10 ; x++ )
  458. // ^^^^^
  459. retstr += GenerateForLoopStatement((ForLoopStatement) fl.kids.Pop());
  460. retstr += ")\n";
  461. // CompoundStatement handles indentation itself but we need to do it
  462. // otherwise.
  463. bool indentHere = fl.kids.Top is Statement;
  464. if (indentHere) m_braceCount++;
  465. retstr += GenerateNode((SYMBOL) fl.kids.Pop());
  466. if (indentHere) m_braceCount--;
  467. return retstr;
  468. }
  469. /// <summary>
  470. /// Generates the code for a ForLoopStatement node.
  471. /// </summary>
  472. /// <param name="fls">The ForLoopStatement node.</param>
  473. /// <returns>String containing C# code for SYMBOL s.</returns>
  474. private string GenerateForLoopStatement(ForLoopStatement fls)
  475. {
  476. string retstr = String.Empty;
  477. int comma = fls.kids.Count - 1; // tells us whether to print a comma
  478. foreach (SYMBOL s in fls.kids)
  479. {
  480. retstr += GenerateNode(s);
  481. if (0 < comma--)
  482. retstr += ", ";
  483. }
  484. return retstr;
  485. }
  486. /// <summary>
  487. /// Generates the code for a BinaryExpression node.
  488. /// </summary>
  489. /// <param name="be">The BinaryExpression node.</param>
  490. /// <returns>String containing C# code for SYMBOL s.</returns>
  491. private string GenerateBinaryExpression(BinaryExpression be)
  492. {
  493. string retstr = String.Empty;
  494. retstr += GenerateNode((SYMBOL) be.kids.Pop());
  495. retstr += String.Format(" {0} ", be.ExpressionSymbol);
  496. foreach (SYMBOL kid in be.kids)
  497. retstr += GenerateNode(kid);
  498. return retstr;
  499. }
  500. /// <summary>
  501. /// Generates the code for a UnaryExpression node.
  502. /// </summary>
  503. /// <param name="ue">The UnaryExpression node.</param>
  504. /// <returns>String containing C# code for SYMBOL s.</returns>
  505. private string GenerateUnaryExpression(UnaryExpression ue)
  506. {
  507. string retstr = String.Empty;
  508. retstr += ue.UnarySymbol;
  509. retstr += GenerateNode((SYMBOL) ue.kids.Pop());
  510. return retstr;
  511. }
  512. /// <summary>
  513. /// Generates the code for a ParenthesisExpression node.
  514. /// </summary>
  515. /// <param name="pe">The ParenthesisExpression node.</param>
  516. /// <returns>String containing C# code for SYMBOL s.</returns>
  517. private string GenerateParenthesisExpression(ParenthesisExpression pe)
  518. {
  519. string retstr = String.Empty;
  520. retstr += "(";
  521. foreach (SYMBOL kid in pe.kids)
  522. retstr += GenerateNode(kid);
  523. retstr += ")";
  524. return retstr;
  525. }
  526. /// <summary>
  527. /// Generates the code for a IncrementDecrementExpression node.
  528. /// </summary>
  529. /// <param name="ide">The IncrementDecrementExpression node.</param>
  530. /// <returns>String containing C# code for SYMBOL s.</returns>
  531. private string GenerateIncrementDecrementExpression(IncrementDecrementExpression ide)
  532. {
  533. string retstr = String.Empty;
  534. if (0 < ide.kids.Count)
  535. {
  536. IdentDotExpression dot = (IdentDotExpression) ide.kids.Top;
  537. retstr += String.Format("{0}", ide.PostOperation ? dot.Name + "." + dot.Member + ide.Operation : ide.Operation + dot.Name + "." + dot.Member);
  538. }
  539. else
  540. retstr += String.Format("{0}", ide.PostOperation ? ide.Name + ide.Operation : ide.Operation + ide.Name);
  541. return retstr;
  542. }
  543. /// <summary>
  544. /// Generates the code for a TypecastExpression node.
  545. /// </summary>
  546. /// <param name="te">The TypecastExpression node.</param>
  547. /// <returns>String containing C# code for SYMBOL s.</returns>
  548. private string GenerateTypecastExpression(TypecastExpression te)
  549. {
  550. string retstr = String.Empty;
  551. // we wrap all typecasted statements in parentheses
  552. retstr += String.Format("({0}) (", te.TypecastType);
  553. retstr += GenerateNode((SYMBOL) te.kids.Pop());
  554. retstr += ")";
  555. return retstr;
  556. }
  557. /// <summary>
  558. /// Generates the code for a FunctionCall node.
  559. /// </summary>
  560. /// <param name="fc">The FunctionCall node.</param>
  561. /// <returns>String containing C# code for SYMBOL s.</returns>
  562. private string GenerateFunctionCall(FunctionCall fc)
  563. {
  564. string retstr = String.Empty;
  565. retstr += String.Format("{0}(", fc.Id);
  566. foreach (SYMBOL kid in fc.kids)
  567. retstr += GenerateNode(kid);
  568. retstr += ")";
  569. return retstr;
  570. }
  571. /// <summary>
  572. /// Generates the code for a Constant node.
  573. /// </summary>
  574. /// <param name="c">The Constant node.</param>
  575. /// <returns>String containing C# code for SYMBOL s.</returns>
  576. private string GenerateConstant(Constant c)
  577. {
  578. string retstr = String.Empty;
  579. // Supprt LSL's weird acceptance of floats with no trailing digits
  580. // after the period. Turn float x = 10.; into float x = 10.0;
  581. if ("LSL_Types.LSLFloat" == c.Type)
  582. {
  583. int dotIndex = c.Value.IndexOf('.') + 1;
  584. if (0 < dotIndex && (dotIndex == c.Value.Length || !Char.IsDigit(c.Value[dotIndex])))
  585. c.Value = c.Value.Insert(dotIndex, "0");
  586. }
  587. // need to quote strings
  588. if ("LSL_Types.LSLString" == c.Type)
  589. retstr += "\"";
  590. retstr += c.Value;
  591. if ("LSL_Types.LSLString" == c.Type)
  592. retstr += "\"";
  593. return retstr;
  594. }
  595. /// <summary>
  596. /// Generates the code for a VectorConstant node.
  597. /// </summary>
  598. /// <param name="vc">The VectorConstant node.</param>
  599. /// <returns>String containing C# code for SYMBOL s.</returns>
  600. private string GenerateVectorConstant(VectorConstant vc)
  601. {
  602. string retstr = String.Empty;
  603. retstr += String.Format("new {0}(", vc.Type);
  604. retstr += GenerateNode((SYMBOL) vc.kids.Pop());
  605. retstr += ", ";
  606. retstr += GenerateNode((SYMBOL) vc.kids.Pop());
  607. retstr += ", ";
  608. retstr += GenerateNode((SYMBOL) vc.kids.Pop());
  609. retstr += ")";
  610. return retstr;
  611. }
  612. /// <summary>
  613. /// Generates the code for a RotationConstant node.
  614. /// </summary>
  615. /// <param name="rc">The RotationConstant node.</param>
  616. /// <returns>String containing C# code for SYMBOL s.</returns>
  617. private string GenerateRotationConstant(RotationConstant rc)
  618. {
  619. string retstr = String.Empty;
  620. retstr += String.Format("new {0}(", rc.Type);
  621. retstr += GenerateNode((SYMBOL) rc.kids.Pop());
  622. retstr += ", ";
  623. retstr += GenerateNode((SYMBOL) rc.kids.Pop());
  624. retstr += ", ";
  625. retstr += GenerateNode((SYMBOL) rc.kids.Pop());
  626. retstr += ", ";
  627. retstr += GenerateNode((SYMBOL) rc.kids.Pop());
  628. retstr += ")";
  629. return retstr;
  630. }
  631. /// <summary>
  632. /// Generates the code for a ListConstant node.
  633. /// </summary>
  634. /// <param name="lc">The ListConstant node.</param>
  635. /// <returns>String containing C# code for SYMBOL s.</returns>
  636. private string GenerateListConstant(ListConstant lc)
  637. {
  638. string retstr = String.Empty;
  639. retstr += String.Format("new {0}(", lc.Type);
  640. foreach (SYMBOL kid in lc.kids)
  641. retstr += GenerateNode(kid);
  642. retstr += ")";
  643. return retstr;
  644. }
  645. /// <summary>
  646. /// Prints text correctly indented, followed by a newline.
  647. /// </summary>
  648. /// <param name="s">String of text to print.</param>
  649. /// <returns>String containing C# code for SYMBOL s.</returns>
  650. private string WriteIndentedLine(string s)
  651. {
  652. return WriteIndented(s) + "\n";
  653. }
  654. /// <summary>
  655. /// Prints text correctly indented.
  656. /// </summary>
  657. /// <param name="s">String of text to print.</param>
  658. /// <returns>String containing C# code for SYMBOL s.</returns>
  659. private string WriteIndented(string s)
  660. {
  661. return Indent() + s;
  662. }
  663. /// <summary>
  664. /// Prints correct indentation.
  665. /// </summary>
  666. /// <returns>String containing C# code for SYMBOL s.</returns>
  667. private string Indent()
  668. {
  669. string retstr = String.Empty;
  670. for (int i = 0; i < m_braceCount; i++)
  671. retstr += " ";
  672. return retstr;
  673. }
  674. }
  675. }