2019-07-28 23:53:15 +03:00
|
|
|
|
// Copyright (c) Ivan Bondarev, Stanislav Mikhalkovich (for details please see \doc\copyright.txt)
|
2015-06-02 22:52:35 +03:00
|
|
|
|
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
|
|
|
|
|
using System;
|
2015-05-14 22:35:07 +03:00
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
|
using System.Globalization;
|
|
|
|
|
|
using System.Text;
|
|
|
|
|
|
using QUT.Gppg;
|
|
|
|
|
|
using PascalABCCompiler.SyntaxTree;
|
|
|
|
|
|
using PascalABCSavParser;
|
|
|
|
|
|
using PascalABCCompiler.ParserTools;
|
|
|
|
|
|
using PascalABCCompiler.Errors;
|
2018-03-21 23:01:54 +03:00
|
|
|
|
using System.Text.RegularExpressions;
|
2015-05-14 22:35:07 +03:00
|
|
|
|
|
|
|
|
|
|
namespace GPPGParserScanner
|
|
|
|
|
|
{
|
|
|
|
|
|
public class NameExprPair
|
|
|
|
|
|
{
|
|
|
|
|
|
public ident id;
|
|
|
|
|
|
public expression ex;
|
|
|
|
|
|
public NameExprPair(ident id, expression ex)
|
|
|
|
|
|
{
|
|
|
|
|
|
this.id = id;
|
|
|
|
|
|
this.ex = ex;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public partial class GPPGParser
|
|
|
|
|
|
{
|
|
|
|
|
|
public declarations GlobalDecls = null;
|
|
|
|
|
|
|
|
|
|
|
|
private int num = 0;
|
|
|
|
|
|
|
|
|
|
|
|
public string Guid()
|
|
|
|
|
|
{
|
|
|
|
|
|
num++;
|
|
|
|
|
|
return num.ToString();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public LexLocation SCToLexLoc(SourceContext sc) // переопределить неявное преобразование типов?
|
|
|
|
|
|
{
|
|
|
|
|
|
return new LexLocation(sc.begin_position.line_num, sc.begin_position.column_num - 1, sc.end_position.line_num, sc.end_position.column_num, sc.FileName);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public program_module NewProgramModule(program_name progName, Object optHeadCompDirs, uses_list mainUsesClose, syntax_tree_node progBlock, Object optPoint, LexLocation loc)
|
|
|
|
|
|
{
|
|
|
|
|
|
var progModule = new program_module(progName, mainUsesClose, progBlock as block, null, loc);
|
|
|
|
|
|
progModule.Language = LanguageId.PascalABCNET;
|
|
|
|
|
|
if (optPoint == null && progBlock != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
var fp = progBlock.source_context.end_position;
|
|
|
|
|
|
var err_stn = progBlock;
|
|
|
|
|
|
if ((progBlock is block) && (progBlock as block).program_code != null && (progBlock as block).program_code.subnodes != null && (progBlock as block).program_code.subnodes.Count > 0)
|
|
|
|
|
|
err_stn = (progBlock as block).program_code.subnodes[(progBlock as block).program_code.subnodes.Count - 1];
|
|
|
|
|
|
parsertools.errors.Add(new PABCNETUnexpectedToken(parsertools.CurrentFileName, StringResources.Get("TKPOINT"), new SourceContext(fp.line_num, fp.column_num + 1, fp.line_num, fp.column_num + 1, 0, 0), err_stn));
|
|
|
|
|
|
}
|
|
|
|
|
|
return progModule;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public unit_name NewUnitHeading(ident unitkeyword, ident uname, LexLocation loc)
|
|
|
|
|
|
{
|
|
|
|
|
|
var un = new unit_name(uname, UnitHeaderKeyword.Unit, loc);
|
|
|
|
|
|
if (unitkeyword.name.ToLower().Equals("library"))
|
|
|
|
|
|
un.HeaderKeyword = UnitHeaderKeyword.Library;
|
|
|
|
|
|
return un;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2017-09-24 13:12:27 +03:00
|
|
|
|
public unit_name NewNamespaceHeading(ident unitkeyword, ident_list nname, LexLocation loc)
|
|
|
|
|
|
{
|
|
|
|
|
|
StringBuilder sb = new StringBuilder();
|
|
|
|
|
|
for (int i = 0; i < nname.idents.Count; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
sb.Append(nname.idents[i]);
|
|
|
|
|
|
if (i < nname.idents.Count - 1)
|
|
|
|
|
|
sb.Append(".");
|
|
|
|
|
|
}
|
2019-06-30 12:25:44 +03:00
|
|
|
|
ident uname = new ident(sb.ToString(), nname.source_context);
|
2017-09-24 13:12:27 +03:00
|
|
|
|
var un = new unit_name(uname, UnitHeaderKeyword.Unit, loc);
|
|
|
|
|
|
un.HeaderKeyword = UnitHeaderKeyword.Namespace;
|
|
|
|
|
|
return un;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2015-05-14 22:35:07 +03:00
|
|
|
|
public procedure_header NewProcedureHeader(attribute_list attrlist, procedure_header nprh, procedure_attribute forw, LexLocation loc)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (nprh.proc_attributes == null)
|
|
|
|
|
|
nprh.proc_attributes = new procedure_attributes_list();
|
|
|
|
|
|
nprh.proc_attributes.Add(forw, forw.source_context);
|
|
|
|
|
|
nprh.attributes = attrlist;
|
|
|
|
|
|
nprh.source_context = loc;
|
|
|
|
|
|
return nprh;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public typecast_node NewAsIsConstexpr(expression constterm, op_typecast typecastop, type_definition tdef, LexLocation loc)
|
|
|
|
|
|
{
|
|
|
|
|
|
var naic = new typecast_node(constterm as addressed_value, tdef, typecastop, loc);
|
|
|
|
|
|
if (!(constterm is addressed_value))
|
|
|
|
|
|
parsertools.errors.Add(new bad_operand_type(parsertools.CurrentFileName, constterm.source_context, naic));
|
|
|
|
|
|
return naic;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public expression NewConstVariable(expression constvariable, expression constvariable2, LexLocation loc)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (constvariable2 is dereference)
|
|
|
|
|
|
((dereference)constvariable2).dereferencing_value = (addressed_value)constvariable;
|
|
|
|
|
|
if (constvariable2 is dot_node)
|
|
|
|
|
|
((dot_node)constvariable2).left = (addressed_value)constvariable;
|
|
|
|
|
|
var ncv = constvariable2;
|
|
|
|
|
|
ncv.source_context = loc;
|
|
|
|
|
|
return ncv;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2017-06-06 05:24:32 +03:00
|
|
|
|
public class_definition NewObjectType(class_attribute class_attributes, token_info class_or_interface_keyword, named_type_reference_list opt_base_classes, where_definition_list opt_where_section, class_body_list opt_not_component_list_seq_end, LexLocation loc)
|
2015-05-14 22:35:07 +03:00
|
|
|
|
{
|
|
|
|
|
|
var nnof = new class_definition(opt_base_classes, opt_not_component_list_seq_end, class_keyword.Class, null, opt_where_section, class_attribute.None, false, loc);
|
|
|
|
|
|
string kw = class_or_interface_keyword.text.ToLower();
|
|
|
|
|
|
nnof.attribute = class_attributes;
|
|
|
|
|
|
if (kw=="record")
|
|
|
|
|
|
nnof.keyword=class_keyword.Record;
|
|
|
|
|
|
else
|
|
|
|
|
|
if (kw=="interface")
|
|
|
|
|
|
nnof.keyword=class_keyword.Interface;
|
|
|
|
|
|
else
|
|
|
|
|
|
if (kw=="i")
|
|
|
|
|
|
nnof.keyword=class_keyword.TemplateInterface;
|
|
|
|
|
|
else
|
|
|
|
|
|
if (kw=="r")
|
|
|
|
|
|
nnof.keyword=class_keyword.TemplateRecord;
|
|
|
|
|
|
else
|
|
|
|
|
|
if (kw=="c")
|
|
|
|
|
|
nnof.keyword=class_keyword.TemplateClass;
|
|
|
|
|
|
if (nnof.body != null && ((class_definition)nnof).body.class_def_blocks != null &&
|
|
|
|
|
|
((class_definition)nnof).body.class_def_blocks.Count > 0 && ((class_definition)nnof).body.class_def_blocks[0].access_mod == null)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (nnof.keyword == class_keyword.Class)
|
|
|
|
|
|
nnof.body.class_def_blocks[0].access_mod = new access_modifer_node(access_modifer.internal_modifer);
|
|
|
|
|
|
else
|
|
|
|
|
|
nnof.body.class_def_blocks[0].access_mod = new access_modifer_node(access_modifer.none);
|
|
|
|
|
|
}
|
|
|
|
|
|
return nnof;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2018-12-08 11:41:26 +03:00
|
|
|
|
/*public class_definition NewRecordType(named_type_reference_list opt_base_classes, where_definition_list opt_where_section, class_body_list component_list_seq, LexLocation loc)
|
2015-05-14 22:35:07 +03:00
|
|
|
|
{
|
|
|
|
|
|
var nnrt = new class_definition(opt_base_classes, component_list_seq, class_keyword.Record, null, opt_where_section, class_attribute.None, false, loc);
|
|
|
|
|
|
if (nnrt.body!=null && nnrt.body.class_def_blocks!=null &&
|
|
|
|
|
|
nnrt.body.class_def_blocks.Count>0 && nnrt.body.class_def_blocks[0].access_mod==null)
|
|
|
|
|
|
{
|
|
|
|
|
|
nnrt.body.class_def_blocks[0].access_mod = new access_modifer_node(access_modifer.public_modifer);
|
|
|
|
|
|
}
|
|
|
|
|
|
return nnrt;
|
2018-12-08 11:41:26 +03:00
|
|
|
|
} */
|
2015-05-14 22:35:07 +03:00
|
|
|
|
|
|
|
|
|
|
public token_info NewClassOrInterfaceKeyword(token_info tktemp)
|
|
|
|
|
|
{
|
|
|
|
|
|
var ncoik = tktemp;
|
|
|
|
|
|
ncoik.text = "c";
|
|
|
|
|
|
return ncoik;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public token_info NewClassOrInterfaceKeyword(token_info tktemp, string text, LexLocation loc)
|
|
|
|
|
|
{
|
|
|
|
|
|
var ncoik = tktemp;
|
|
|
|
|
|
ncoik.text = text;
|
|
|
|
|
|
ncoik.source_context = loc;
|
|
|
|
|
|
return ncoik;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public procedure_header NewProcfuncHeading(procedure_header ph)
|
|
|
|
|
|
{
|
2016-02-12 18:49:02 +03:00
|
|
|
|
//ph.name.explicit_interface_name = ph.name.class_name;
|
|
|
|
|
|
//ph.name.class_name = null;
|
2015-05-14 22:35:07 +03:00
|
|
|
|
return ph;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public method_name NewQualifiedIdentifier(method_name qualified_identifier, ident identifier, LexLocation loc)
|
|
|
|
|
|
{
|
|
|
|
|
|
var nqi = qualified_identifier;
|
|
|
|
|
|
nqi.class_name = nqi.meth_name;
|
|
|
|
|
|
nqi.meth_name = identifier;
|
|
|
|
|
|
nqi.source_context = loc;
|
|
|
|
|
|
return nqi;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public declaration NewPropertyDefinition(attribute_list opt_attribute_declarations, declaration simple_property_definition, LexLocation loc)
|
|
|
|
|
|
{
|
|
|
|
|
|
var nnpd = simple_property_definition;
|
|
|
|
|
|
nnpd.attributes = opt_attribute_declarations;
|
|
|
|
|
|
nnpd.source_context = loc;
|
|
|
|
|
|
return nnpd;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public simple_property NewSimplePrimPropertyDefinition(simple_property simple_property_definition, LexLocation loc)
|
|
|
|
|
|
{
|
|
|
|
|
|
var nsnpd = simple_property_definition;
|
|
|
|
|
|
nsnpd.attr = definition_attribute.Static;
|
|
|
|
|
|
nsnpd.source_context = loc;
|
|
|
|
|
|
return nsnpd;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2017-08-06 22:51:12 +03:00
|
|
|
|
public simple_property NewSimplePropertyDefinition(method_name qualified_identifier, property_interface property_interface, property_accessors property_specifiers, proc_attribute virt_over_none_attr, property_array_default array_defaultproperty, LexLocation loc)
|
2015-05-14 22:35:07 +03:00
|
|
|
|
{
|
2017-08-06 22:51:12 +03:00
|
|
|
|
var nnspd = new simple_property();
|
|
|
|
|
|
nnspd.virt_over_none_attr = virt_over_none_attr;
|
|
|
|
|
|
|
|
|
|
|
|
nnspd.property_name = qualified_identifier.meth_name;
|
2015-05-14 22:35:07 +03:00
|
|
|
|
if (property_interface != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
nnspd.parameter_list = property_interface.parameter_list;
|
|
|
|
|
|
nnspd.property_type = property_interface.property_type;
|
|
|
|
|
|
nnspd.index_expression = property_interface.index_expression;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (property_specifiers != null)
|
|
|
|
|
|
nnspd.accessors = property_specifiers;
|
|
|
|
|
|
if (array_defaultproperty != null)
|
|
|
|
|
|
nnspd.array_default = array_defaultproperty;
|
|
|
|
|
|
nnspd.source_context = loc;
|
|
|
|
|
|
return nnspd;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2018-07-20 14:13:28 +03:00
|
|
|
|
public property_accessors NewPropertySpecifiersRead(ident tkRead, ident opt_identifier, procedure_definition pr, expression ex, property_accessors property_specifiers, LexLocation loc)
|
2015-05-14 22:35:07 +03:00
|
|
|
|
{
|
|
|
|
|
|
var nnps = property_specifiers;
|
|
|
|
|
|
if (nnps == null)
|
|
|
|
|
|
{
|
|
|
|
|
|
nnps = new property_accessors();
|
|
|
|
|
|
}
|
|
|
|
|
|
if (opt_identifier != null && opt_identifier.name.ToLower() == "write")
|
|
|
|
|
|
{
|
2018-07-20 14:13:28 +03:00
|
|
|
|
nnps.read_accessor = new read_accessor_name(null, null, null);
|
|
|
|
|
|
nnps.write_accessor = new write_accessor_name(null, null, null);
|
2015-05-14 22:35:07 +03:00
|
|
|
|
nnps.read_accessor.source_context = tkRead.source_context;
|
|
|
|
|
|
nnps.write_accessor.source_context = opt_identifier.source_context;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
2018-07-24 23:05:49 +03:00
|
|
|
|
if (ex != null)
|
|
|
|
|
|
nnps.read_accessor = new read_accessor_name(opt_identifier, pr, ex, tkRead.source_context.Merge(ex.source_context));
|
|
|
|
|
|
else if (opt_identifier != null)
|
2018-07-20 14:13:28 +03:00
|
|
|
|
nnps.read_accessor = new read_accessor_name(opt_identifier, pr, ex, tkRead.source_context.Merge(opt_identifier.source_context));
|
|
|
|
|
|
else nnps.read_accessor = new read_accessor_name(opt_identifier, pr, ex, tkRead.source_context);
|
2015-05-14 22:35:07 +03:00
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
nnps.source_context = loc;
|
|
|
|
|
|
return nnps;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2018-07-20 14:13:28 +03:00
|
|
|
|
public property_accessors NewPropertySpecifiersWrite(ident tkWrite, ident opt_identifier, procedure_definition pr, statement st, property_accessors property_specifiers, LexLocation loc)
|
2015-05-14 22:35:07 +03:00
|
|
|
|
{
|
|
|
|
|
|
var nnpsw = property_specifiers;
|
|
|
|
|
|
if (nnpsw == null)
|
|
|
|
|
|
{
|
|
|
|
|
|
nnpsw = new property_accessors();
|
|
|
|
|
|
}
|
2018-07-24 23:05:49 +03:00
|
|
|
|
if (st != null)
|
|
|
|
|
|
nnpsw.write_accessor = new write_accessor_name(opt_identifier, pr, st, tkWrite.source_context.Merge(st.source_context));
|
|
|
|
|
|
else if (opt_identifier != null)
|
2018-07-20 14:13:28 +03:00
|
|
|
|
nnpsw.write_accessor = new write_accessor_name(opt_identifier,pr,st,tkWrite.source_context.Merge(opt_identifier.source_context));
|
2018-07-24 23:05:49 +03:00
|
|
|
|
else
|
|
|
|
|
|
nnpsw.write_accessor = new write_accessor_name(opt_identifier,pr,st,tkWrite.source_context);
|
2015-05-14 22:35:07 +03:00
|
|
|
|
nnpsw.source_context = loc;
|
|
|
|
|
|
return nnpsw;
|
|
|
|
|
|
}
|
|
|
|
|
|
/*public procedure_definition NewProcDecl(procedure_definition proc_decl_noclass, LexLocation loc)
|
|
|
|
|
|
{
|
|
|
|
|
|
(proc_decl_noclass.proc_header as procedure_header).class_keyword = true;
|
|
|
|
|
|
proc_decl_noclass.source_context = loc;
|
|
|
|
|
|
return proc_decl_noclass;
|
|
|
|
|
|
}*/
|
|
|
|
|
|
public case_variants NewCaseItem(syntax_tree_node case_item, LexLocation loc)
|
|
|
|
|
|
{
|
|
|
|
|
|
var nci = new case_variants();
|
|
|
|
|
|
if (case_item is case_variant)
|
|
|
|
|
|
nci.Add((case_variant)case_item);
|
|
|
|
|
|
nci.source_context = loc;
|
|
|
|
|
|
return nci;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public case_variants AddCaseItem(case_variants case_list, syntax_tree_node case_item, LexLocation loc)
|
|
|
|
|
|
{
|
|
|
|
|
|
var nci = case_list;
|
|
|
|
|
|
if (case_item is case_variant)
|
|
|
|
|
|
nci.Add((case_variant)case_item);
|
|
|
|
|
|
nci.source_context = loc;
|
|
|
|
|
|
return nci;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public while_node NewWhileStmt(token_info tkWhile, expression expr, token_info opt_tk_do, statement stmt, LexLocation loc)
|
|
|
|
|
|
{
|
|
|
|
|
|
var nws = new while_node(expr, stmt, WhileCycleType.While, loc);
|
|
|
|
|
|
if (opt_tk_do == null)
|
|
|
|
|
|
{
|
|
|
|
|
|
file_position fp = expr.source_context.end_position;
|
|
|
|
|
|
syntax_tree_node err_stn = stmt;
|
|
|
|
|
|
if (err_stn == null)
|
|
|
|
|
|
err_stn = expr;
|
|
|
|
|
|
parsertools.errors.Add(new PABCNETUnexpectedToken(parsertools.CurrentFileName, StringResources.Get("TKDO"), new SourceContext(fp.line_num, fp.column_num + 1, fp.line_num, fp.column_num + 1, 0, 0), err_stn));
|
|
|
|
|
|
}
|
|
|
|
|
|
return nws;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2017-06-21 21:19:38 +03:00
|
|
|
|
public for_node NewForStmt(bool opt_var, ident identifier, type_definition for_stmt_decl_or_assign, expression expr1, for_cycle_type fc_type, expression expr2, token_info opt_tk_do, statement stmt, LexLocation loc)
|
2015-05-14 22:35:07 +03:00
|
|
|
|
{
|
2017-06-21 21:19:38 +03:00
|
|
|
|
var nfs = new for_node(identifier, expr1, expr2, stmt, fc_type, null, for_stmt_decl_or_assign, opt_var != false, loc);
|
2015-05-14 22:35:07 +03:00
|
|
|
|
if (opt_tk_do == null)
|
|
|
|
|
|
{
|
|
|
|
|
|
file_position fp = expr2.source_context.end_position;
|
|
|
|
|
|
syntax_tree_node err_stn = stmt;
|
|
|
|
|
|
if (err_stn == null)
|
|
|
|
|
|
err_stn = expr2;
|
|
|
|
|
|
parsertools.errors.Add(new PABCNETUnexpectedToken(parsertools.CurrentFileName, StringResources.Get("TKDO"), new SourceContext(fp.line_num, fp.column_num + 1, fp.line_num, fp.column_num + 1, 0, 0), err_stn));
|
|
|
|
|
|
}
|
2016-09-15 21:13:02 +03:00
|
|
|
|
if (!opt_var && for_stmt_decl_or_assign == null)
|
|
|
|
|
|
parsertools.AddWarningFromResource("USING_UNLOCAL_FOR_VARIABLE", identifier.source_context);
|
2015-05-14 22:35:07 +03:00
|
|
|
|
return nfs;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public typecast_node NewAsIsExpr(syntax_tree_node term, op_typecast typecast_op, type_definition simple_or_template_type_reference, LexLocation loc)
|
|
|
|
|
|
{
|
|
|
|
|
|
var naie = new typecast_node((addressed_value)term, simple_or_template_type_reference, typecast_op, loc);
|
|
|
|
|
|
if (!(term is addressed_value))
|
|
|
|
|
|
parsertools.errors.Add(new bad_operand_type(parsertools.CurrentFileName, term.source_context, naie));
|
|
|
|
|
|
return naie;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public function_lambda_call NewFactor(ident func_decl_lambda, expression_list expr_list, LexLocation loc)
|
|
|
|
|
|
{
|
|
|
|
|
|
var fld = parsertools.find_pascalABC_lambda_name(func_decl_lambda.name);
|
|
|
|
|
|
var _expression_list = expr_list;
|
|
|
|
|
|
var _lambda_definition = fld;
|
|
|
|
|
|
var _lambda_call = new function_lambda_call(_lambda_definition, _expression_list, loc);
|
|
|
|
|
|
_lambda_call.source_context = func_decl_lambda.source_context;
|
|
|
|
|
|
return _lambda_call;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public addressed_value NewVarReference(get_address var_address, addressed_value variable, LexLocation loc)
|
|
|
|
|
|
{
|
|
|
|
|
|
var_address.address_of = variable;
|
|
|
|
|
|
parsertools.create_source_context(parsertools.NodesStack.Peek(),parsertools.NodesStack.Peek(), variable);
|
|
|
|
|
|
return (addressed_value)parsertools.NodesStack.Pop();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public get_address NewVarAddress(LexLocation loc)
|
|
|
|
|
|
{
|
|
|
|
|
|
var nva = new get_address();
|
|
|
|
|
|
nva.source_context = loc;
|
|
|
|
|
|
parsertools.NodesStack.Push(nva);
|
|
|
|
|
|
return nva;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public get_address NewVarAddress(get_address var_address, LexLocation loc)
|
|
|
|
|
|
{
|
|
|
|
|
|
var nva = new get_address();
|
|
|
|
|
|
nva.source_context = loc;
|
|
|
|
|
|
var_address.address_of = (addressed_value)nva;
|
|
|
|
|
|
return nva;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public expression NewVariable(addressed_value variable, expression var_specifiers, LexLocation loc)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (var_specifiers is dot_node)
|
|
|
|
|
|
{
|
|
|
|
|
|
var dn = (dot_node)var_specifiers;
|
|
|
|
|
|
dn.left = variable;
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (var_specifiers is template_param_list)
|
|
|
|
|
|
{
|
|
|
|
|
|
var tpl = (template_param_list)var_specifiers;
|
|
|
|
|
|
((dot_node)tpl.dereferencing_value).left = variable;
|
|
|
|
|
|
parsertools.create_source_context(tpl.dereferencing_value, variable, tpl.dereferencing_value);
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (var_specifiers is dereference)
|
|
|
|
|
|
{
|
|
|
|
|
|
((dereference)var_specifiers).dereferencing_value = variable;
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (var_specifiers is ident_with_templateparams)
|
|
|
|
|
|
{
|
|
|
|
|
|
((ident_with_templateparams)var_specifiers).name = (addressed_value_funcname)variable;
|
|
|
|
|
|
}
|
|
|
|
|
|
var_specifiers.source_context = loc;
|
|
|
|
|
|
return var_specifiers;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public literal NewLiteral(literal_const_line literal_list)
|
|
|
|
|
|
{
|
|
|
|
|
|
var lcl = literal_list;
|
|
|
|
|
|
if (lcl.literals.Count == 1)
|
|
|
|
|
|
return lcl.literals[0];
|
|
|
|
|
|
return lcl;
|
|
|
|
|
|
}
|
2018-03-21 23:01:54 +03:00
|
|
|
|
|
2018-03-22 23:34:42 +03:00
|
|
|
|
public expression ParseExpression(string Text, int line, int col)
|
|
|
|
|
|
{
|
|
|
|
|
|
PT parsertools = new PT(); // контекст сканера и парсера
|
|
|
|
|
|
parsertools.errors = new List<Error>();
|
|
|
|
|
|
parsertools.warnings = new List<CompilerWarning>();
|
|
|
|
|
|
parsertools.CurrentFileName = System.IO.Path.GetFullPath(this.parsertools.CurrentFileName);
|
|
|
|
|
|
parsertools.build_tree_for_format_strings = true;
|
|
|
|
|
|
Scanner scanner = new Scanner();
|
|
|
|
|
|
scanner.SetSource("<<expression>>"+Text, 0);
|
|
|
|
|
|
scanner.parsertools = parsertools;// передали parsertools в объект сканера
|
|
|
|
|
|
GPPGParser parser = new GPPGParser(scanner);
|
|
|
|
|
|
parsertools.build_tree_for_formatter = false;
|
2018-05-27 16:11:14 +03:00
|
|
|
|
parser.lambdaHelper = this.lambdaHelper;
|
2018-03-22 23:34:42 +03:00
|
|
|
|
parser.parsertools = parsertools;
|
|
|
|
|
|
if (!parser.Parse())
|
|
|
|
|
|
if (parsertools.errors.Count == 0)
|
|
|
|
|
|
parsertools.AddError("Неопознанная синтаксическая ошибка!", null);
|
|
|
|
|
|
foreach (Error err in parsertools.errors)
|
|
|
|
|
|
{
|
|
|
|
|
|
this.parsertools.errors.Add(err);
|
|
|
|
|
|
}
|
|
|
|
|
|
return parser.root as expression;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2018-03-21 23:01:54 +03:00
|
|
|
|
public expression NewFormatString(string_const str)
|
|
|
|
|
|
{
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
method_call mc = new method_call();
|
|
|
|
|
|
mc.dereferencing_value = new dot_node(new ident("string", str.source_context), new ident("Format", str.source_context), str.source_context);
|
|
|
|
|
|
mc.parameters = new expression_list();
|
2018-07-18 22:06:52 +03:00
|
|
|
|
if (!str.Value.Contains("{"))
|
|
|
|
|
|
return str;
|
2018-04-29 15:34:03 +03:00
|
|
|
|
string val = str.Value.Replace("{{","![&").Replace("}}}","}&]!").Replace("}}", "&]!");
|
2019-08-18 14:40:45 +03:00
|
|
|
|
|
2018-04-29 15:34:03 +03:00
|
|
|
|
string[] arr = Regex.Split(val, @"\{[^\}]+\}");
|
|
|
|
|
|
Match match = Regex.Match(val, @"\{[^\}]+\}");
|
2018-03-21 23:01:54 +03:00
|
|
|
|
List<string> vars = new List<string>();
|
2018-03-23 20:29:25 +03:00
|
|
|
|
//Dictionary<string, int> var_offsets = new Dictionary<string, int>();
|
|
|
|
|
|
List<int> var_offsets = new List<int>();
|
2018-06-07 21:30:28 +03:00
|
|
|
|
Dictionary<int, string> var_formats = new Dictionary<int, string>();
|
|
|
|
|
|
int ind = 0;
|
2018-03-21 23:01:54 +03:00
|
|
|
|
while (match.Success)
|
|
|
|
|
|
{
|
|
|
|
|
|
string s = match.Value.Replace("{", "").Replace("}", "");
|
2018-09-02 13:25:14 +03:00
|
|
|
|
int colon_pos = s.LastIndexOf(':');
|
|
|
|
|
|
int comma_pos = s.LastIndexOf(',');
|
|
|
|
|
|
int bracket_pos = s.LastIndexOf(')');
|
|
|
|
|
|
int sqbracked_pos = s.LastIndexOf(']');
|
|
|
|
|
|
if (comma_pos != -1 && comma_pos > bracket_pos && comma_pos > sqbracked_pos)
|
|
|
|
|
|
colon_pos = comma_pos;
|
2019-11-23 19:23:04 +03:00
|
|
|
|
if (colon_pos != -1 && s.IndexOf('?') == -1 && s.Substring(colon_pos).IndexOf(']') == -1)
|
2018-06-07 21:30:28 +03:00
|
|
|
|
{
|
|
|
|
|
|
var_formats.Add(ind, s.Substring(colon_pos));
|
|
|
|
|
|
s = s.Substring(0, colon_pos);
|
|
|
|
|
|
|
2019-08-18 14:40:45 +03:00
|
|
|
|
}
|
|
|
|
|
|
if (s.IndexOf("&]!") != -1 || s.IndexOf("![&") != -1)
|
|
|
|
|
|
{
|
|
|
|
|
|
parsertools.errors.Add(new bad_format_string(parsertools.CurrentFileName, str.source_context, str));
|
|
|
|
|
|
return str;
|
|
|
|
|
|
}
|
2018-03-21 23:01:54 +03:00
|
|
|
|
vars.Add(s);
|
2018-03-23 20:29:25 +03:00
|
|
|
|
var_offsets.Add(match.Index);
|
2018-03-21 23:01:54 +03:00
|
|
|
|
match = match.NextMatch();
|
2018-06-07 21:30:28 +03:00
|
|
|
|
ind++;
|
2018-03-21 23:01:54 +03:00
|
|
|
|
}
|
2019-08-18 14:40:45 +03:00
|
|
|
|
if (vars.Count == 0 && val.IndexOf("![&") == -1 && val.IndexOf("{") != -1)
|
2018-03-21 23:01:54 +03:00
|
|
|
|
{
|
|
|
|
|
|
parsertools.errors.Add(new bad_format_string(parsertools.CurrentFileName, str.source_context, str));
|
|
|
|
|
|
return str;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
StringBuilder sb = new StringBuilder();
|
|
|
|
|
|
for (int i = 0; i < arr.Length; i++)
|
|
|
|
|
|
{
|
2019-08-18 14:40:45 +03:00
|
|
|
|
if (arr[i].IndexOf("{") != -1 || arr[i].IndexOf("}") != -1)
|
|
|
|
|
|
{
|
|
|
|
|
|
parsertools.errors.Add(new bad_format_string(parsertools.CurrentFileName, str.source_context, str));
|
|
|
|
|
|
return str;
|
|
|
|
|
|
}
|
2018-04-29 15:34:03 +03:00
|
|
|
|
sb.Append(arr[i].Replace("![&", "{{").Replace("&]!", "}}"));
|
2018-03-21 23:01:54 +03:00
|
|
|
|
if (i < arr.Length - 1)
|
2018-06-07 21:30:28 +03:00
|
|
|
|
{
|
|
|
|
|
|
sb.Append("{" + i);
|
|
|
|
|
|
string fmt;
|
|
|
|
|
|
if (var_formats.TryGetValue(i, out fmt))
|
|
|
|
|
|
{
|
|
|
|
|
|
sb.Append(fmt);
|
|
|
|
|
|
}
|
|
|
|
|
|
sb.Append("}");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2018-03-21 23:01:54 +03:00
|
|
|
|
}
|
2018-09-02 12:50:39 +03:00
|
|
|
|
string str2 = sb.ToString();
|
|
|
|
|
|
if (str2.Trim().EndsWith("{"))
|
|
|
|
|
|
{
|
|
|
|
|
|
parsertools.errors.Add(new bad_format_string(parsertools.CurrentFileName, str.source_context, str));
|
|
|
|
|
|
return str;
|
|
|
|
|
|
}
|
|
|
|
|
|
mc.parameters.Add(new string_const(str2, str.source_context), str.source_context);
|
2018-03-23 20:29:25 +03:00
|
|
|
|
for (int i = 0; i < vars.Count; i++)
|
2018-03-21 23:01:54 +03:00
|
|
|
|
{
|
2018-03-23 20:29:25 +03:00
|
|
|
|
string s = vars[i];
|
|
|
|
|
|
var expr = ParseExpression(new string('\n', str.source_context.begin_position.line_num - 1) + new string(' ', str.source_context.begin_position.column_num + var_offsets[i] + 2) + s, str.source_context.begin_position.line_num, str.source_context.begin_position.column_num + var_offsets[i] + 2);
|
2018-12-30 14:29:13 +03:00
|
|
|
|
if (expr == null)
|
|
|
|
|
|
{
|
|
|
|
|
|
var err = parsertools.errors[0] as LocatedError;
|
|
|
|
|
|
err.SourceContext.begin_position.line_num = str.source_context.begin_position.line_num;
|
|
|
|
|
|
err.SourceContext.begin_position.column_num = str.source_context.begin_position.column_num + var_offsets[i] + vars[i].Length + 3;
|
|
|
|
|
|
return str;
|
|
|
|
|
|
}
|
2018-03-22 23:34:42 +03:00
|
|
|
|
expr.source_context.begin_position.line_num = str.source_context.begin_position.line_num;
|
|
|
|
|
|
expr.source_context.end_position.line_num = str.source_context.end_position.line_num;
|
|
|
|
|
|
mc.parameters.Add(expr);
|
2018-03-21 23:01:54 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
mc.source_context = str.source_context;
|
|
|
|
|
|
return mc;
|
|
|
|
|
|
}
|
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
|
{
|
|
|
|
|
|
parsertools.errors.Add(new bad_format_string(parsertools.CurrentFileName, str.source_context, str));
|
|
|
|
|
|
}
|
|
|
|
|
|
return str;
|
|
|
|
|
|
}
|
2015-05-14 22:35:07 +03:00
|
|
|
|
|
2018-11-10 21:17:58 +03:00
|
|
|
|
/*public var_def_statement NewVarOrIdentifier(ident identifier, named_type_reference fptype, LexLocation loc)
|
2015-05-14 22:35:07 +03:00
|
|
|
|
{
|
|
|
|
|
|
var n_t_r = fptype;
|
|
|
|
|
|
var vds = new var_def_statement();
|
|
|
|
|
|
vds.vars = new ident_list();
|
|
|
|
|
|
vds.vars.idents.Add(identifier);
|
|
|
|
|
|
vds.vars_type = n_t_r;
|
|
|
|
|
|
vds.source_context = loc;
|
|
|
|
|
|
return vds;
|
2018-11-10 21:17:58 +03:00
|
|
|
|
}*/
|
2015-05-14 22:35:07 +03:00
|
|
|
|
|
2018-11-10 21:17:58 +03:00
|
|
|
|
/* Функция стала короткой и утратила необходимость
|
|
|
|
|
|
*public statement_list NewLambdaBody(expression expr_l1, LexLocation loc)
|
2015-05-14 22:35:07 +03:00
|
|
|
|
{
|
2016-04-23 10:28:39 +03:00
|
|
|
|
var sl = new statement_list();
|
|
|
|
|
|
sl.expr_lambda_body = true;
|
|
|
|
|
|
var id = new ident("result");
|
|
|
|
|
|
var op = new op_type_node(Operators.Assignment);
|
|
|
|
|
|
var ass = new assign(id, expr_l1, op.type);
|
2017-12-30 11:39:02 +03:00
|
|
|
|
parsertools.create_source_context(ass, id, expr_l1); // дурацкая функция - если хотя бы у одного sc=null, то возвращает null
|
|
|
|
|
|
if (ass.source_context == null)
|
|
|
|
|
|
if (expr_l1.source_context != null)
|
|
|
|
|
|
ass.source_context = expr_l1.source_context;
|
|
|
|
|
|
else if (id.source_context != null)
|
|
|
|
|
|
ass.source_context = id.source_context;
|
2016-04-23 10:28:39 +03:00
|
|
|
|
sl.subnodes.Add(ass);
|
|
|
|
|
|
sl.source_context = loc;
|
2018-11-10 21:17:58 +03:00
|
|
|
|
var sl = new statement_list(new assign("result",expr_l1,loc),loc);
|
|
|
|
|
|
|
|
|
|
|
|
return sl;
|
|
|
|
|
|
}/**/
|
2018-07-01 11:53:34 +03:00
|
|
|
|
|
|
|
|
|
|
public procedure_definition CreateAndAddToClassReadFunc(expression ex, ident id, SourceContext sc)
|
|
|
|
|
|
{
|
|
|
|
|
|
var fd = SyntaxTreeBuilder.BuildShortFuncDefinition(new formal_parameters(), null, new method_name(id.name, sc), new no_type(), ex, sc);
|
|
|
|
|
|
return fd;
|
|
|
|
|
|
}
|
|
|
|
|
|
public procedure_definition CreateAndAddToClassWriteProc(statement st, ident id, SourceContext sc)
|
|
|
|
|
|
{
|
|
|
|
|
|
var fp = SyntaxTreeBuilder.BuildFormalParameters(new List<ident>() { new ident("value") }, new List<type_definition>() { new no_type() });
|
|
|
|
|
|
var pd = SyntaxTreeBuilder.BuildShortProcDefinition(fp, null, new method_name(id.name, sc), st, sc);
|
|
|
|
|
|
return pd;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private int num1 = 0;
|
|
|
|
|
|
|
2018-09-23 22:38:39 +03:00
|
|
|
|
public ident NewId(string prefix, SourceContext sc = null)
|
2018-07-01 11:53:34 +03:00
|
|
|
|
{
|
|
|
|
|
|
num1++;
|
2018-09-23 22:38:39 +03:00
|
|
|
|
return new ident(prefix + num1.ToString(),sc);
|
2018-07-01 11:53:34 +03:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2015-05-14 22:35:07 +03:00
|
|
|
|
}
|