Preprocessor.cs 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. using System.Collections.Generic;
  2. using System.Linq;
  3. namespace NTERA.Interpreter.Compiler
  4. {
  5. public static class Preprocessor
  6. {
  7. public static IDictionary<FunctionDefinition, string> PreprocessFile(string contents, string filename)
  8. {
  9. Dictionary<FunctionDefinition, string> procs = new Dictionary<FunctionDefinition, string>();
  10. Lexer lexer = new Lexer(contents);
  11. Marker startMarker = lexer.TokenMarker;
  12. string currentDefinitionName = null;
  13. List<FunctionParameter> currentDefinitionParameters = new List<FunctionParameter>();
  14. List<FunctionVariable> currentDefinitionVariables = new List<FunctionVariable>();
  15. bool isReturnFunction = false;
  16. void Commit()
  17. {
  18. if (currentDefinitionName != null)
  19. {
  20. string procBody = contents.Substring(startMarker.Pointer,
  21. lexer.TokenMarker.Pointer - startMarker.Pointer);
  22. var definition = new FunctionDefinition(currentDefinitionName,
  23. currentDefinitionParameters.ToArray(),
  24. currentDefinitionVariables.ToArray(),
  25. isReturnFunction,
  26. filename,
  27. startMarker);
  28. procs.Add(definition, procBody);
  29. isReturnFunction = false;
  30. currentDefinitionName = null;
  31. currentDefinitionParameters.Clear();
  32. }
  33. }
  34. using (var enumerator = lexer.GetEnumerator())
  35. {
  36. do
  37. {
  38. if (lexer.TokenMarker.Column != 1)
  39. continue;
  40. if (enumerator.Current == Token.Function)
  41. {
  42. Commit();
  43. startMarker = lexer.TokenMarker;
  44. enumerator.MoveNext();
  45. if (enumerator.Current != Token.Identifer)
  46. throw new ParserException("Invalid function declaration - Expected an identifier", lexer.TokenMarker);
  47. currentDefinitionName = lexer.Identifer;
  48. enumerator.MoveNext();
  49. if (enumerator.Current == Token.NewLine
  50. || enumerator.Current == Token.EOF)
  51. continue;
  52. if (enumerator.Current != Token.LParen
  53. && enumerator.Current != Token.Comma)
  54. throw new ParserException("Invalid function declaration", lexer.TokenMarker);
  55. enumerator.MoveNext();
  56. if (enumerator.Current != Token.Identifer
  57. && enumerator.Current != Token.RParen)
  58. throw new ParserException("Invalid function declaration", lexer.TokenMarker);
  59. while (enumerator.Current == Token.Identifer)
  60. {
  61. string parameterName = lexer.Identifer;
  62. List<string> indices = new List<string>();
  63. Value? defaultValue = null;
  64. enumerator.MoveNext();
  65. while (enumerator.Current == Token.Colon
  66. && enumerator.MoveNext())
  67. {
  68. if (enumerator.Current == Token.Value)
  69. {
  70. indices.Add(lexer.Value.Type == ValueType.Real
  71. ? ((int)lexer.Value).ToString()
  72. : lexer.Value.String);
  73. }
  74. else if (enumerator.Current == Token.Identifer)
  75. {
  76. indices.Add(lexer.Identifer);
  77. }
  78. enumerator.MoveNext();
  79. }
  80. if (enumerator.Current == Token.Equal)
  81. {
  82. enumerator.MoveNext();
  83. bool hasUnaryMinus = false;
  84. if (enumerator.Current == Token.Minus)
  85. {
  86. hasUnaryMinus = true;
  87. enumerator.MoveNext();
  88. }
  89. if (enumerator.Current == Token.Identifer)
  90. {
  91. defaultValue = lexer.Identifer;
  92. }
  93. else if (enumerator.Current == Token.Value)
  94. {
  95. defaultValue = lexer.Value;
  96. if (hasUnaryMinus)
  97. {
  98. if (defaultValue.Value.Type == ValueType.Real)
  99. defaultValue = defaultValue * -1;
  100. else
  101. defaultValue = "-" + defaultValue;
  102. }
  103. }
  104. else
  105. throw new ParserException("Invalid function declaration", lexer.TokenMarker);
  106. enumerator.MoveNext();
  107. }
  108. if (enumerator.Current == Token.Comma
  109. || enumerator.Current == Token.RParen)
  110. {
  111. enumerator.MoveNext();
  112. }
  113. else if (enumerator.Current != Token.NewLine
  114. && enumerator.Current != Token.EOF)
  115. throw new ParserException("Invalid function declaration", lexer.TokenMarker);
  116. currentDefinitionParameters.Add(new FunctionParameter(parameterName, indices.ToArray(), defaultValue));
  117. }
  118. if (enumerator.Current == Token.RParen)
  119. enumerator.MoveNext();
  120. if (enumerator.Current != Token.NewLine
  121. && enumerator.Current != Token.EOF)
  122. throw new ParserException("Invalid function declaration", lexer.TokenMarker);
  123. }
  124. else if (enumerator.Current == Token.Sharp)
  125. {
  126. enumerator.MoveNext();
  127. switch (enumerator.Current)
  128. {
  129. case Token.Dims:
  130. case Token.Dim:
  131. {
  132. bool isString = enumerator.Current != Token.Dim;
  133. enumerator.MoveNext();
  134. VariableType variableType = VariableType.None;
  135. while (enumerator.Current == Token.Const
  136. || enumerator.Current == Token.Ref
  137. || enumerator.Current == Token.Dynamic)
  138. {
  139. if (enumerator.Current == Token.Const)
  140. variableType |= VariableType.Constant;
  141. else if (enumerator.Current == Token.Ref)
  142. variableType |= VariableType.Reference;
  143. else if (enumerator.Current == Token.Dynamic)
  144. variableType |= VariableType.Dynamic;
  145. enumerator.MoveNext();
  146. }
  147. string variable = lexer.Identifer;
  148. enumerator.MoveNext();
  149. Value? defaultValue = null;
  150. if (enumerator.Current == Token.Comma)
  151. {
  152. while (enumerator.MoveNext()
  153. && enumerator.Current != Token.Equal
  154. && enumerator.Current != Token.NewLine
  155. && enumerator.Current != Token.EOF)
  156. {
  157. }
  158. //arraySize = (int)lexer.Expression().Real;
  159. }
  160. if (enumerator.Current == Token.Equal)
  161. {
  162. enumerator.MoveNext();
  163. if (isString)
  164. lexer.Type = LexerType.String;
  165. defaultValue = lexer.Expression();
  166. lexer.Type = LexerType.Both;
  167. }
  168. else if (enumerator.Current != Token.NewLine
  169. && enumerator.Current != Token.EOF)
  170. {
  171. throw new ParserException("Invalid function declaration", lexer.TokenMarker);
  172. }
  173. currentDefinitionVariables.Add(new FunctionVariable(variable,
  174. isString ? ValueType.String : ValueType.Real,
  175. variableType,
  176. defaultValue));
  177. break;
  178. }
  179. case Token.ReturnFunction:
  180. {
  181. isReturnFunction = true;
  182. break;
  183. }
  184. }
  185. }
  186. } while (enumerator.MoveNext());
  187. }
  188. Commit();
  189. return procs;
  190. }
  191. public static IList<IList<string>> ProcessCSV(IEnumerable<string> lines)
  192. {
  193. List<IList<string>> csv = new List<IList<string>>();
  194. foreach (var line in lines)
  195. {
  196. if (string.IsNullOrWhiteSpace(line)
  197. || line[0] == ';')
  198. continue;
  199. string newLine = line;
  200. int commentIndex = line.IndexOf(';');
  201. if (commentIndex >= 0)
  202. newLine = line.Substring(0, commentIndex);
  203. string[] split = newLine.Split(',');
  204. csv.Add(split.ToList());
  205. }
  206. return csv;
  207. }
  208. }
  209. }