// Copyright (c) Ivan Bondarev, Stanislav Mihalkovich (for details please see \doc\copyright.txt) // This code is distributed under the GNU LGPL (for details please see \doc\license.txt) using System.Collections.Generic; using PascalABCCompiler.SyntaxTree; using PascalABCCompiler.Errors; using QUT.Gppg; using GPPGParserScanner; using System; using System.Linq; namespace PascalABCSavParser { public class Union { public expression ex; public ident id; public Object ob; public op_type_node op; public syntax_tree_node stn; public token_info ti; public type_definition td; } public static class StringResources { private static string prefix = "PASCALABCPARSER_"; public static string Get(string Id) { string ret = PascalABCCompiler.StringResources.Get(prefix + Id); if (ret == prefix + Id) return Id; else return ret; } } // Класс глобальных описаний и статических методов // для использования различными подсистемами парсера и сканера public class PT // PT - parser tools { private const int max_char_const = 0xFFFF; // SSM: Errors инициализируется в другом месте - сюда только передается! public List errors; public List warnings; public System.Collections.Stack NodesStack; // SSM: для каких-то вспомогательных целей в двух правилах public bool build_tree_for_formatter = false; public bool build_tree_for_format_strings = false; public string CurrentFileName; int lambda_num = 0; public List pascalABC_lambda_definitions; public List pascalABC_var_statements; public List pascalABC_type_declarations; public static Dictionary tokenNum; // строки, соответствующие терминалам, для вывода ошибок - SSM // TODO: CompilerDirectives по идее сюда еще надо // Преобразование GPPG LexLocation в наш SourceContext static PT() { tokenNum = new Dictionary(); tokenNum["tkStatement"] = StringResources.Get("OPERATOR"); tokenNum["tkExpression"] = StringResources.Get("EXPR"); tokenNum["EOF"] = StringResources.Get("EOF1"); tokenNum["tkIdentifier"] = StringResources.Get("TKIDENTIFIER"); tokenNum["tkAmpersend"] = "'"; tokenNum["tkColon"]="':'"; tokenNum["tkDotDot"]="'..'"; tokenNum["tkPoint"]="'.'"; tokenNum["tkRoundOpen"]="'('"; tokenNum["tkRoundClose"]="')'"; tokenNum["tkSemiColon"]="';'"; tokenNum["tkSquareOpen"]="'['"; tokenNum["tkSquareClose"]="']'"; tokenNum["tkQuestion"]="'?'"; tokenNum["tkComma"]="','"; tokenNum["tkAssign"]="':='"; tokenNum["tkPlusEqual"]="'+='"; tokenNum["tkMinusEqual"]="'-='"; tokenNum["tkMultEqual"]="'*='"; tokenNum["tkDivEqual"]="'/='"; tokenNum["tkMinus"]="'-'"; tokenNum["tkPlus"]="'+'"; tokenNum["tkSlash"]="'//'"; tokenNum["tkStar"]="'*'"; tokenNum["tkEqual"]="'='"; tokenNum["tkGreater"]="'>'"; tokenNum["tkGreaterEqual"]="'>='"; tokenNum["tkLower"]="'<'"; tokenNum["tkLowerEqual"]="'<='"; tokenNum["tkNotEqual"]="'<>'"; tokenNum["tkArrow"]="'->'"; tokenNum["tkAddressOf"]="'@'"; tokenNum["tkDeref"]="'^'"; tokenNum["tkStarStar"]="'**'"; } public PT() { NodesStack = new System.Collections.Stack(); pascalABC_lambda_definitions = new List(); pascalABC_var_statements = new List(); pascalABC_type_declarations = new List(); } public void DivideDirectiveOn(string yytext, out string directivename, out string directiveparam) { var ind = yytext.IndexOfAny(new char[]{' ','}'}); directivename = yytext.Substring(2,ind-2).ToUpper().Trim(); directiveparam = yytext.Substring(ind + 1).TrimEnd('}').Trim(); } public void CheckDirectiveParams(string directivename, string directiveparam) { } public SourceContext ToSourceContext(LexLocation loc) { if (loc != null) return new SourceContext(loc.StartLine, loc.StartColumn + 1, loc.EndLine, loc.EndColumn); return null; } public string ConvertToHumanName(string s) { var v = s; if (tokenNum.ContainsKey(v)) v = tokenNum[v]; else if (v.StartsWith("tk")) v = v.Remove(0,2).ToLower(); return v; } public int TokenPriority(string tok) { switch (tok) { case "tkSemiColon": return 120; case "tkStatement": return 100; case "tkExpression": return 100; case "tkEqual": return 90; case "tkColon": return 80; case "tkAssign": return 70; case "tkIdentifier": return 60; case "tkRoundClose": return 50; case "tkBegin": return 40; case "tkEnd": return 30; case "tkDotDot": return 20; case "tkSquareClose": return 10; case "tkGreater": return 5; } return 0; } public string MaxToken(string[] args) { return args.Max(); } public string CreateErrorString(string yytext, params object[] args) { string prefix = ""; if (yytext != "") prefix = StringResources.Get("FOUND{0}"); else prefix = StringResources.Get("FOUNDEOF"); if (this.build_tree_for_format_strings && prefix == StringResources.Get("FOUNDEOF")) { yytext = "}"; prefix = StringResources.Get("FOUND{0}"); } // Преобразовали в список строк - хорошо List tokens = new List(args.Skip(1).Cast()); // Исключаем, т.к. в реальных программах никогда не встретятся tokens = tokens.Except((new string[] { "tkParseModeExpression", "tkParseModeStatement", "tkDirectiveName" })).ToList(); // Это - временное решение, пока эти слова относятся к идентификаторам (что неправильно) if (tokens.Contains("tkIdentifier")) tokens = tokens.Except((new string[] { "tkAbstract", "tkOverload", "tkReintroduce", "tkOverride", "tkVirtual", "tkAt", "tkOn", "tkName", "tkForward", "tkRead", "tkWrite" })).ToList(); // Добавляем фиктивный токен, что означает, что далее могут идти несколько токенов, начинающих выражение if (tokens.Contains("tkFor") && tokens.Contains("tkIf") && tokens.Contains("tkRepeat") && tokens.Contains("tkWhile")) { tokens.Clear(); tokens.Add("tkStatement"); } // Добавляем фиктивный токен, что означает, что далее могут идти несколько токенов, начинающих выражение if (tokens.Contains("tkIdentifier") && tokens.Contains("tkInteger") && tokens.Contains("tkFloat")) { tokens.Clear(); tokens.Add("tkExpression"); } tokens = tokens.OrderByDescending(s => TokenPriority(s)).ToList(); /*if (args.Contains("EOF") && yytext!="") return "Текст за концом программы недопустим"; if (args.Contains("tkIdentifier")) return string.Format(prefix + "ожидался идентификатор", "'" + yytext + "'");*/ if (tokens.Contains("tkProgram")) return string.Format(prefix + StringResources.Get("EXPECTEDBEGIN"), "'" + yytext + "'"); var MaxTok = tokens.First(); var ExpectedString = StringResources.Get("EXPECTED{1}"); if (MaxTok.Equals("tkStatement") || MaxTok.Equals("tkIdentifier")) ExpectedString = StringResources.Get("EXPECTEDR{1}"); if ((MaxTok == "EOF" || MaxTok == "EOF1" || MaxTok == "FOUNDEOF") && this.build_tree_for_format_strings) MaxTok = "}"; var MaxTokHuman = ConvertToHumanName(MaxTok); // string w = string.Join(" или ", tokens.Select(s => ConvertToHumanName((string)s))); return string.Format(prefix + ExpectedString, "'" + yytext + "'", MaxTokHuman); } public void AddError(string message, LexLocation loc) { errors.Add(new SyntaxError(message, CurrentFileName, loc, null)); } public void AddErrorFromResource(string res, PascalABCCompiler.SyntaxTree.SourceContext loc, params string[] pars) { res = StringResources.Get(res); if (pars != null && pars.Length > 0) res = string.Format(res, pars); errors.Add(new SyntaxError(res, CurrentFileName, loc, null)); } public void AddWarningFromResource(string res, PascalABCCompiler.SyntaxTree.SourceContext loc, params string[] pars) { res = StringResources.Get(res); if (pars != null && pars.Length > 0) res = string.Format(res, pars); warnings.Add(new CommonWarning(res, CurrentFileName, loc.begin_position.line_num, loc.begin_position.column_num)); } public string directive_parameter(string s) { var ind = s.IndexOf(" "); if (ind < 0) return ""; else { s = s.Substring(ind + 1); s = s.TrimEnd('}'); return s; } } public ident create_directive_name(string text, SourceContext sc) { ident dn = new ident(new string(text.ToCharArray(1, text.Length - 1))); dn.source_context = sc; return dn; } public string ReplaceSpecialSymbols(string text) { text = text.Replace("''", "'"); return text; } public char_const create_char_const(string text, SourceContext sc) { string char_text = new string(text.ToCharArray(1, text.Length - 2)); char_text = ReplaceSpecialSymbols(char_text); char_const ct = new char_const(); ct.source_context = sc; if (char_text.Length == 1) { ct.cconst = char_text[0]; return ct; } return null; } public sharp_char_const create_sharp_char_const(string text, SourceContext sc) { string int_text = new string(text.ToCharArray(1, text.Length - 1)); sharp_char_const scc = null; int val = 0; if (int.TryParse(int_text, out val)) { if (val > max_char_const) { scc = new sharp_char_const(0); errors.Add(new TooBigCharNumberInSharpCharConstant(CurrentFileName, sc, scc)); } else scc = new sharp_char_const(val); scc.source_context = sc; } else { errors.Add(new TooBigCharNumberInSharpCharConstant(CurrentFileName, sc, scc)); } return scc; } public const_node create_double_const(string text, SourceContext sc) { const_node cn = null; try { System.Globalization.NumberFormatInfo sgnfi = new System.Globalization.NumberFormatInfo(); sgnfi.NumberDecimalSeparator = "."; double val = double.Parse(text, sgnfi); cn = new double_const(val); cn.source_context = sc; } catch (Exception) { errors.Add(new BadFloat(CurrentFileName, sc, null)); } return cn; } public const_node create_hex_const(string text, SourceContext sc) { return create_int_const(text, sc, System.Globalization.NumberStyles.HexNumber); } public const_node create_int_const(string text, SourceContext sc) { return create_int_const(text, sc, System.Globalization.NumberStyles.Integer); } public const_node create_int_const(string text, SourceContext sc, System.Globalization.NumberStyles NumberStyles) { //таблица целых констант на уровне синтаксиса // не может быть - 0 + // 32--------16----8----|----8----16--------32----------------64(bits) // [ int64 )[ int32 ]( int64 ]( uint64 ] if (NumberStyles == System.Globalization.NumberStyles.HexNumber) text = text.Substring(1); const_node cn = new int32_const(); if (text.Length < 8) (cn as int32_const).val = Int32.Parse(text, NumberStyles); else { try { UInt64 uint64 = UInt64.Parse(text, NumberStyles); if (uint64 <= Int32.MaxValue) (cn as int32_const).val = (Int32)uint64; else if (uint64 <= Int64.MaxValue) cn = new int64_const((Int64)uint64); else cn = new uint64_const(uint64); } catch (Exception) { if (NumberStyles == System.Globalization.NumberStyles.HexNumber) errors.Add(new BadHex(CurrentFileName, sc, null)); else errors.Add(new BadInt(CurrentFileName, sc, null)); } } cn.source_context = sc; return cn; } public ident create_ident(string text, SourceContext sc) { if (text[0] == '&') text = text.Substring(1); ident id = new ident(text); id.source_context = sc; return id; } public procedure_attributes_list AddModifier(procedure_attributes_list proc_list, proc_attribute modif) { if (proc_list == null) proc_list = new procedure_attributes_list(); foreach (procedure_attribute attr in proc_list.proc_attributes) if (attr.attribute_type == modif) return proc_list; proc_list.proc_attributes.Add(new procedure_attribute(modif)); return proc_list; } public literal create_string_const(string text, SourceContext sc) { literal lt; if (text.Length == 3 && text[0] == '\'' && text[2] == '\'') { lt = new char_const(text[1]); lt.source_context = sc; return lt; } text = ReplaceSpecialSymbols(text.Substring(1, text.Length - 2)); lt = new string_const(text); lt.source_context = sc; return lt; } public literal create_format_string_const(string text, SourceContext sc) { literal lt; text = ReplaceSpecialSymbols(text.Substring(2, text.Length - 3)); lt = new string_const(text); lt.source_context = sc; return lt; } public procedure_definition lambda(function_lambda_definition _function_lambda_definition) { procedure_definition _func_def = new procedure_definition(); method_name _method_name1 = new method_name(null,null, new ident(_function_lambda_definition.lambda_name), null); //parsertools.create_source_context(_method_name1, _method_name1.meth_name, _method_name1.meth_name); function_header _function_header1 = new function_header(); object rt1 = new object(); _function_header1.name = _method_name1; if (_function_header1.name.meth_name is template_type_name) { _function_header1.template_args = (_function_header1.name.meth_name as template_type_name).template_args; ident id = new ident(_function_header1.name.meth_name.name); //parsertools.create_source_context(id, _function_header1.name.meth_name, _function_header1.name.meth_name); _function_header1.name.meth_name = id; } formal_parameters fps = new PascalABCCompiler.SyntaxTree.formal_parameters(); _function_header1.parameters = _function_lambda_definition.formal_parameters;//fps; /*SyntaxTree.named_type_reference _named_type_reference = new SyntaxTree.named_type_reference(); SyntaxTree.ident idtype = new SyntaxTree.ident("object"); _named_type_reference.source_context = idtype.source_context; _named_type_reference.names.Add(idtype); rt1 = _named_type_reference; _function_header1.return_type = (SyntaxTree.type_definition)_named_type_reference;*/ _function_header1.return_type = _function_lambda_definition.return_type; _function_header1.of_object = false; _function_header1.class_keyword = false; token_info _token_info = new token_info("function"); //_token_info.source_context = parsertools.GetTokenSourceContext(); //parsertools.create_source_context(_function_header1, _token_info, _token_info); block _block1 = new block(null, null); statement_list sl1 = new statement_list(); sl1.subnodes.Add(_function_lambda_definition.proc_body); _block1.program_code = sl1; _func_def.proc_header = _function_header1; _func_def.proc_body = (proc_block)_block1; if (_function_lambda_definition.defs != null) { if (((block)_func_def.proc_body).defs == null) ((block)_func_def.proc_body).defs = new declarations(); for (int l = 0; l < _function_lambda_definition.defs.Count; l++) ((block)_func_def.proc_body).defs.defs.Add(_function_lambda_definition.defs[l] as procedure_definition); } _function_lambda_definition.proc_definition = _func_def; //parsertools.create_source_context(_func_def, _function_header1, _function_header1); return _func_def; } public function_lambda_definition find_pascalABC_lambda_name(string name) { int i = 0; while (i < pascalABC_lambda_definitions.Count && (pascalABC_lambda_definitions[i] == null || ((function_lambda_definition)pascalABC_lambda_definitions[i]).lambda_name != name)) i++; if (i < pascalABC_lambda_definitions.Count) return (function_lambda_definition)pascalABC_lambda_definitions[i]; else return null; } public var_def_statement find_var_statements(string name) { int i = pascalABC_var_statements.Count - 1; bool b = false; while (!b && i >= 0) { var_def_statement vds = (var_def_statement)pascalABC_var_statements[i]; int j = 0; while (j < vds.vars.idents.Count && vds.vars.idents[j].name != name) j++; if (j < vds.vars.idents.Count) b = true; else i--; } if (i >= 0 && i < pascalABC_var_statements.Count && ((var_def_statement)pascalABC_var_statements[i]).vars_type != null) return (var_def_statement)pascalABC_var_statements[i]; else return null; } public ident func_decl_lambda(object lr0, object lr2) { statement_list _statement_list = (statement_list)lr2; expression_list _expression_list = new expression_list(); ident_list _i_l = new ident_list(); formal_parameters _formal_parameters = new formal_parameters(); if (lr0 != null) { List ar = (List)lr0; for (int i = 0; i < ar.Count; i++) if (ar[i] is ident) _i_l.idents.Add((ident)ar[i]); else _i_l.idents.Add(((var_def_statement)ar[i]).vars.idents[0]); for (int i = 0; i < _i_l.idents.Count; i++) _expression_list.expressions.Add(_i_l.idents[i]); for (int i = 0; i < ar.Count; i++) { ident_list _ident_list = new ident_list(); ident id = _i_l.idents[i]; _ident_list.idents.Add(id); string name_param = id.name; typed_parameters _typed_parameters = null; int k = 0; { named_type_reference _named_type_reference = new named_type_reference(); type_definition t_d = new type_definition(); if (ar[i] is ident) { ident idtype = new ident("object"); _named_type_reference.names.Add(idtype); t_d = (type_definition)_named_type_reference; } else { t_d = ((var_def_statement)ar[i]).vars_type; } _typed_parameters = new typed_parameters(_ident_list, t_d, parametr_kind.none, null); //parsertools.create_source_context(_typed_parameters, _ident_list, t_d); } _formal_parameters.params_list.Add(_typed_parameters); } } ////////////////////////// named_type_reference _named_type_reference1 = new named_type_reference(); ident idtype1 = new ident("object"); _named_type_reference1.source_context = idtype1.source_context; _named_type_reference1.names.Add(idtype1); ///////////////////////////// lambda_num++; function_lambda_definition _procedure_definition = new function_lambda_definition(); _procedure_definition.formal_parameters = _formal_parameters; _procedure_definition.return_type = (type_definition)_named_type_reference1; _procedure_definition.ident_list = _i_l; _procedure_definition.proc_body = null; _procedure_definition.parameters = _expression_list; _procedure_definition.lambda_name = "__lambda__" + lambda_num; //new function_lambda_definition(_formal_parameters, (type_definition)_named_type_reference1, _i_l, null, _expression_list, "lambda" + lambda_num); object rt = _i_l; _procedure_definition.proc_body = _statement_list; //////////////////////////////vnutrennie lambda if (_procedure_definition.defs == null) _procedure_definition.defs = new List(); while (pascalABC_lambda_definitions.Count > 0 && pascalABC_lambda_definitions[pascalABC_lambda_definitions.Count - 1] != null) { _procedure_definition.defs.Add(lambda((function_lambda_definition)pascalABC_lambda_definitions[pascalABC_lambda_definitions.Count - 1])); pascalABC_lambda_definitions.RemoveAt(pascalABC_lambda_definitions.Count - 1); } if (pascalABC_lambda_definitions.Count > 0 && pascalABC_lambda_definitions[pascalABC_lambda_definitions.Count - 1] == null) pascalABC_lambda_definitions.RemoveAt(pascalABC_lambda_definitions.Count - 1); pascalABC_lambda_definitions.Add(_procedure_definition); /////////////////////////////////////////////// //parsertools.create_source_context(_procedure_definition, _expression_list, rt); ident _name = new ident(_procedure_definition.lambda_name); if (lr0 != null) _name.source_context = _i_l.idents[0].source_context; return _name; } public List ident_list11(object lr1, object lr3) { List ar = (List)lr3; ar.Insert(0, lr1); return ar; } public List ident_list12(object lr0) { List ar = new List(); ar.Add(lr0); return ar; } public List ident_list21(object lr0, object lr2) { List ar = (List)lr0; ar.Add(lr2); return ar; } public List ident_list13(object lr1, object lr3, object lr5) { List ar = (List)lr5; //named_type_reference n_t_r = (named_type_reference)lr3; var_def_statement vds = new var_def_statement(); vds.vars = new ident_list(); vds.vars.idents.Add((ident)lr1); vds.vars_type = (type_definition)lr3;//n_t_r; ar.Insert(0, vds); return ar; } public List ident_list14(object lr1, object lr3) { List ar = new List(); //named_type_reference n_t_r = (named_type_reference)lr3; var_def_statement vds = new var_def_statement(); vds.vars = new ident_list(); vds.vars.idents.Add((ident)lr1); vds.vars_type = (type_definition)lr3; ar.Add(vds); return ar; } public void add_lambda_to_program_block(block _block) { //tasha 16.04.2010 if (pascalABC_lambda_definitions.Count > 0) { if (_block.defs == null) _block.defs = new declarations(); for (int i = 0; i < pascalABC_lambda_definitions.Count; i++) _block.defs.defs.Add(lambda((function_lambda_definition)pascalABC_lambda_definitions[i])); pascalABC_lambda_definitions.Clear(); } } public void add_lambda(object lr1, procedure_definition _procedure_definition) { if (pascalABC_lambda_definitions.Count > 0)//tasha 16.04.2010 { block _block = (block)lr1; if (_block.defs == null) _block.defs = new declarations(); for (int i = 0; i < pascalABC_lambda_definitions.Count; i++) _block.defs.defs.Add(lambda((function_lambda_definition)pascalABC_lambda_definitions[i])); pascalABC_lambda_definitions.Clear(); _procedure_definition.proc_body = (proc_block)_block; } else //////////////////////////tasha 16.04.2010 _procedure_definition.proc_body = (proc_block)lr1; } public void for_assignment(object lr0, object lr2) { if (lr0 is ident && lr2 is ident && ((ident)lr2).name.Contains("__lambda__")) { string type_name = ""; var_def_statement vds = find_var_statements(((ident)lr0).name); if (vds != null) type_name = ((named_type_reference)vds.vars_type).names[0].name; if (type_name != "") { int ii = 0; while (ii < pascalABC_type_declarations.Count && ((type_declaration)pascalABC_type_declarations[ii]).type_name.name != type_name) ii++; if (ii < pascalABC_type_declarations.Count) { type_definition td = ((type_declaration)pascalABC_type_declarations[ii]).type_def; function_lambda_definition fld = find_pascalABC_lambda_name(((ident)lr2).name); fld.return_type = ((function_header)td).return_type; for (int k = 0; k < fld.formal_parameters.params_list.Count && k < ((function_header)td).parameters.params_list.Count; k++) fld.formal_parameters.params_list[k].vars_type = ((function_header)td).parameters.params_list[k].vars_type; } pascalABC_var_statements.Remove(vds); } } } public void create_source_context(object to, object left, object right) { if (to != null) ((syntax_tree_node)to).source_context = get_source_context(left, right); } public SourceContext get_source_context(object left, object right) { //debug /*if (left == null && right!=null) { Console.WriteLine("\n\rerror: left is null(create_source_context)!\n\r"); Console.WriteLine(((syntax_tree_node)right).source_context.ToString()); } if (right == null && left!=null) { Console.WriteLine("\n\rerror: right is null(create_source_context)!\n\r"); Console.WriteLine(((syntax_tree_node)left).source_context.ToString()); } if (((syntax_tree_node)left).source_context == null) { Console.WriteLine("\n\rerror: source_context is null!(left)\n\r"); return null; } if (((syntax_tree_node)right).source_context == null) { Console.WriteLine("\n\rerror: source_context is null!(right)\n\r"); return null; } */ if ((left == null) || (right == null) || (((syntax_tree_node)left).source_context == null) || (((syntax_tree_node)right).source_context == null)) return null; return new SourceContext(((syntax_tree_node)left).source_context, ((syntax_tree_node)right).source_context); } public void create_source_context_left(object to, object left) { file_position fp = ((syntax_tree_node)left).source_context.begin_position; ((syntax_tree_node)to).source_context = new SourceContext(fp.line_num, fp.column_num, fp.line_num, fp.column_num, 0, 0); } public void create_source_context_right(object to, object right) { file_position fp = ((syntax_tree_node)right).source_context.end_position; ((syntax_tree_node)to).source_context = new SourceContext(fp.line_num, fp.column_num, fp.line_num, fp.column_num, 0, 0); } public object sc_not_null(object o1, object o2) { if (o1 != null) if (((syntax_tree_node)o1).source_context != null) return o1; return o2; } public object sc_not_null(object o1, object o2, object o3) { if (o1 != null) if (((syntax_tree_node)o1).source_context != null) return o1; if (o2 != null) if (((syntax_tree_node)o2).source_context != null) return o2; return o3; } public object sc_not_null(params object[] arr) { foreach (object o in arr) if (o != null) if (((syntax_tree_node)o).source_context != null) return o; return null; } public void assign_source_context(object to, object from) { //debug //if (((tree_node)from).source_context==null) Console.WriteLine("\n\rerror: from sc is null(assign_source_context)!\n\r"); if (to!=null && from!=null) ((syntax_tree_node)to).source_context = ((syntax_tree_node)from).source_context; } public statement MyStmt(expression ex, statement st) { // Проверить, что в ex - целый тип // Сделать специальный узел для проверки new semantic_check("Тип проверки",params syntax_node[] ob) // Включать этот узел первым для "сахарных" узлов синтаксического дерева var sc = new semantic_check("ExprIsInteger", ex); var id = new ident("#my"); var idlist = new ident_list(id); var typ = new named_type_reference("integer"); var one = new int32_const(1); var vdef = new var_def_statement(idlist, typ, one, definition_attribute.None, false, null); var vstat = new var_statement(vdef, null); var ass = new assign(new ident("#my"), one, Operators.AssignmentAddition); var stlistwhile = new statement_list(st); stlistwhile.Add(ass); var bin = new bin_expr(id, ex, Operators.LessEqual); var wh = new while_node(bin, stlistwhile, WhileCycleType.While); var stlist = new statement_list(sc); stlist.Add(vstat); stlist.Add(wh); return stlist; } public expression ConvertNamedTypeReferenceToDotNodeOrIdent(named_type_reference ntr) // либо ident либо dot_node { if (ntr.names.Count == 1) return ntr.names[0]; else { var dn = new dot_node(ntr.names[0], ntr.names[1], ntr.names[0].source_context.Merge(ntr.names[1].source_context)); for (var i = 2; i < ntr.names.Count; i++) dn = new dot_node(dn, ntr.names[i],dn.source_context.Merge(ntr.names[i].source_context)); dn.source_context = ntr.source_context; return dn; } } public named_type_reference ConvertDotNodeOrIdentToNamedTypeReference(expression en) { if (en is ident) return new named_type_reference(en as ident, en.source_context); if (en is dot_node) { var dn = en as dot_node; var sc = dn.source_context; var ids = new List(); ids.Add(dn.right as ident); while (dn.left is dot_node) { dn = dn.left as dot_node; ids.Add(dn.right as ident); } ids.Add(dn.left as ident); ids.Reverse(); return new named_type_reference(ids, sc); } this.AddErrorFromResource("TYPE_NAME_EXPECTED", en.source_context); return null; } } }