PageRenderTime 42ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/lib/otp.net/Otp/Erlang/Format.cs

http://github.com/gebi/jungerl
C# | 295 lines | 264 code | 11 blank | 20 comment | 31 complexity | c3bc404e16a615bcac332c7921f5e99a MD5 | raw file
Possible License(s): AGPL-1.0, JSON, LGPL-2.1, BSD-3-Clause
  1. /*``The contents of this file are subject to the Erlang Public License,
  2. * Version 1.1, (the "License"); you may not use this file except in
  3. * compliance with the License. You should have received a copy of the
  4. * Erlang Public License along with this software. If not, it can be
  5. * retrieved via the world wide web at http://www.erlang.org/.
  6. *
  7. * Software distributed under the License is distributed on an "AS IS"
  8. * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
  9. * the License for the specific language governing rights and limitations
  10. * under the License.
  11. *
  12. * The Initial Developer of the Original Code is Ericsson Utvecklings AB.
  13. * Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
  14. * AB. All Rights Reserved.''
  15. *
  16. * Copyright (c) 2011 Serge Aleynikov <saleyn@gmail.com>
  17. */
  18. namespace Otp.Erlang
  19. {
  20. using System;
  21. /*
  22. * Provides a C# representation of Erlang strings.
  23. **/
  24. internal class Formatter
  25. {
  26. private enum State {
  27. ERL_OK = 0
  28. , ERL_FMT_ERR = -1
  29. , ERL_MAX_ENTRIES = 255 /* Max entries in a tuple/list term */
  30. , ERL_MAX_NAME_LENGTH = 255 /* Max length of variable names */
  31. };
  32. private static int skip_null_chars(char[] fmt, int pos) {
  33. for (char c = fmt[pos]; pos < fmt.Length && (c == ' ' || c == '\t' || c == '\n'); c = fmt[++pos]);
  34. return pos;
  35. }
  36. private static string pvariable(char[] fmt, ref int pos)
  37. {
  38. int start = pos;
  39. for (pos = skip_null_chars(fmt, pos); pos < fmt.Length; pos++)
  40. {
  41. char c = fmt[pos];
  42. if (char.IsLetterOrDigit(c) || (c == '_'))
  43. continue;
  44. else
  45. break;
  46. }
  47. int len = pos - start;
  48. return new string(fmt, start, len);
  49. }
  50. private static string patom(char[] fmt, ref int pos)
  51. {
  52. int start = pos;
  53. for (pos = skip_null_chars(fmt, pos); pos < fmt.Length; pos++)
  54. {
  55. char c = fmt[pos];
  56. if (char.IsLetterOrDigit(c) || (c == '_') || (c == '@'))
  57. continue;
  58. else
  59. break;
  60. }
  61. int len = pos - start;
  62. return new string(fmt, start, len);
  63. }
  64. private static string pdigit(char[] fmt, ref int pos)
  65. {
  66. int start = pos;
  67. bool dotp = false;
  68. for (pos = skip_null_chars(fmt, pos); pos < fmt.Length; pos++)
  69. {
  70. char c = fmt[pos];
  71. if (char.IsDigit(c) || c == '-')
  72. continue;
  73. else if (!dotp && c == '.')
  74. {
  75. dotp = true;
  76. continue;
  77. }
  78. else
  79. break;
  80. }
  81. int len = pos - start;
  82. return new string(fmt, start, len);
  83. }
  84. private static string pstring(char[] fmt, ref int pos)
  85. {
  86. int start = ++pos; // skip the first double quote
  87. for (; pos < fmt.Length; pos++)
  88. {
  89. char c = fmt[pos];
  90. if (c == '"') {
  91. if (fmt[pos-1] == '\\')
  92. continue;
  93. else
  94. break;
  95. }
  96. }
  97. int len = pos++ - start;
  98. return new string(fmt, start, len);
  99. }
  100. private static string pquotedAtom(char[] fmt, ref int pos)
  101. {
  102. int start = ++pos; // skip first quote
  103. for (pos = skip_null_chars(fmt, pos); pos < fmt.Length; pos++)
  104. {
  105. char c = fmt[pos];
  106. if (c == '\'')
  107. {
  108. if (fmt[pos-1] == '\\')
  109. continue;
  110. else
  111. break;
  112. }
  113. }
  114. int len = pos - start;
  115. return new string(fmt, start, len);
  116. }
  117. private static State ptuple(char[] fmt, ref int pos,
  118. ref System.Collections.Generic.List<Erlang.Object> items, ref int argc, params object[] args)
  119. {
  120. int start = pos;
  121. State rc = State.ERL_FMT_ERR;
  122. pos = skip_null_chars(fmt, pos);
  123. switch (fmt[pos++]) {
  124. case '}':
  125. rc = State.ERL_OK;
  126. break;
  127. case ',':
  128. rc = ptuple(fmt, ref pos, ref items, ref argc, args);
  129. break;
  130. default: {
  131. --pos;
  132. Erlang.Object obj = create(fmt, ref pos, ref argc, args);
  133. items.Add(obj);
  134. rc = ptuple(fmt, ref pos, ref items, ref argc, args);
  135. break;
  136. }
  137. }
  138. return rc;
  139. }
  140. private static State plist(char[] fmt, ref int pos,
  141. ref System.Collections.Generic.List<Erlang.Object> items, ref int argc, params object[] args)
  142. {
  143. State rc = State.ERL_FMT_ERR;
  144. pos = skip_null_chars(fmt, pos);
  145. switch (fmt[pos++]) {
  146. case ']':
  147. rc = State.ERL_OK;
  148. break;
  149. case ',':
  150. rc = plist(fmt, ref pos, ref items, ref argc, args);
  151. break;
  152. case '|':
  153. pos = skip_null_chars(fmt, pos);
  154. if (char.IsUpper(fmt[pos]) || fmt[pos] == '_') {
  155. string s = pvariable(fmt, ref pos);
  156. items.Add(new Erlang.Var(s));
  157. pos = skip_null_chars(fmt, pos);
  158. if (fmt[pos] == ']')
  159. rc = State.ERL_OK;
  160. break;
  161. }
  162. break;
  163. default: {
  164. --pos;
  165. Erlang.Object obj = create(fmt, ref pos, ref argc, args);
  166. items.Add(obj);
  167. rc = plist(fmt, ref pos, ref items, ref argc, args);
  168. break;
  169. }
  170. }
  171. return rc;
  172. }
  173. private static State pformat(char[] fmt, ref int pos,
  174. ref System.Collections.Generic.List<Erlang.Object> items, ref int argc, params object[] args)
  175. {
  176. pos = skip_null_chars(fmt, pos);
  177. if (fmt[pos++] != 'w')
  178. return State.ERL_FMT_ERR;
  179. object o = args[argc++];
  180. Type to = o.GetType();
  181. if (to == typeof(int))
  182. items.Add(new Erlang.Long((int)o));
  183. else if (to == typeof(long))
  184. items.Add(new Erlang.Long((long)o));
  185. else if (to == typeof(double))
  186. items.Add(new Erlang.Double((double)o));
  187. else if (to == typeof(string))
  188. items.Add(new Erlang.String((string)o));
  189. else if (to == typeof(bool))
  190. items.Add(new Erlang.Boolean((bool)o));
  191. else if (to == typeof(Erlang.Object))
  192. items.Add(o as Erlang.Object);
  193. else if (to == typeof(char))
  194. items.Add(new Erlang.Char((char)o));
  195. else
  196. throw new FormatException(
  197. string.Format("Unknown type of argument #{0}: {1}", argc-1, to.ToString()));
  198. return State.ERL_OK;
  199. }
  200. internal static Erlang.Object create(
  201. char[] fmt, ref int pos, ref int argc, params object[] args)
  202. {
  203. var items = new System.Collections.Generic.List<Erlang.Object>();
  204. Erlang.Object result = null;
  205. pos = skip_null_chars(fmt, pos);
  206. switch (fmt[pos++]) {
  207. case '{':
  208. if (State.ERL_OK != ptuple(fmt, ref pos, ref items, ref argc, args))
  209. throw new FormatException(
  210. string.Format("Error parsing tuple at pos {0}", pos));
  211. result = new Erlang.Tuple(items.ToArray());
  212. break;
  213. case '[':
  214. if (fmt[pos] == ']') {
  215. result = new Erlang.List();
  216. break;
  217. }
  218. else if (State.ERL_OK == plist(fmt, ref pos, ref items, ref argc, args))
  219. {
  220. result = new Erlang.List(items.ToArray());
  221. break;
  222. }
  223. throw new FormatException(
  224. string.Format("Error parsing list at pos {0}", pos));
  225. case '$': /* char-value? */
  226. result = new Erlang.Char(fmt[pos++]);
  227. break;
  228. case '~':
  229. if (State.ERL_OK != pformat(fmt, ref pos, ref items, ref argc, args))
  230. throw new FormatException(
  231. string.Format("Error parsing term at pos {0}", pos));
  232. result = items[0];
  233. break;
  234. default:
  235. --pos;
  236. char c = fmt[pos];
  237. if (char.IsLower(c)) { /* atom ? */
  238. string s = patom(fmt, ref pos);
  239. result = new Erlang.Atom(s);
  240. } else if (char.IsUpper(c) || c == '_') {
  241. string s = pvariable(fmt, ref pos);
  242. result = new Erlang.Var(s);
  243. } else if (char.IsDigit(c) || c == '-') { /* integer/float ? */
  244. string s = pdigit(fmt, ref pos);
  245. if (s.IndexOf('.') < 0)
  246. result = new Erlang.Long(long.Parse(s));
  247. else
  248. result = new Erlang.Double(double.Parse(s));
  249. } else if (c == '"') { /* string ? */
  250. string s = pstring(fmt, ref pos);
  251. result = new Erlang.String(s);
  252. } else if (c == '\'') { /* quoted atom ? */
  253. string s = pquotedAtom(fmt, ref pos);
  254. result = new Erlang.Atom(s);
  255. }
  256. break;
  257. }
  258. return result;
  259. }
  260. }
  261. }