码白白 2022-12-12 18:43 采纳率: 100%
浏览 24
已结题

关于#matlab#的问题:用matlab写代码时不小心把系统自带的.m文件代码改了

用matlab写代码时不小心把系统自带的.m文件代码改了,不知道原来的代码了

求热心人复制个str2symInternal.m文件的代码,万分感谢!

  • 写回答

1条回答 默认 最新

  • 感谢地心引力 嵌入式领域优质创作者 2022-12-12 18:51
    关注
    
    function [mupstr, variables] = str2symInternal(S, options)
    %str2symInternal Evaluate string representing symbolic expression.
    %   str2symInternal(S) evaluates S as a symbolic expression, where S can be
    %   a string, character vector, or cell array of character vectors.
    %
    %   str2symInternal(S) behavior:
    %     Only executes functions on path when converting the string.
    %     Does not consider variables and values from workspace.
    %     Does not add variables in the input to the workspace.
    %     Does not support programming statements like IF.
    %     Treats assignments ('=') as equations ('==').
    %
    %   For numeric strings, use SYM for exact symbolic numbers and
    %   VPA for floating-point numbers.
    %
    %   See also SUBS, SYM, SYMFUN, SYMS, SYMVAR, VPA.
    %
    %   Examples:
    %
    %      >> str2symInternal("b^2 + pi/2 + sin(x) = x^3 - 2")
    %      ans =
    %      b^2 + pi/2 + sin(x) == x^3 - 2
    %
    %      >> str2symInternal('int(x^3,x)')
    %      ans =
    %      x^4/4
    %
    %      >> str2symInternal('y(0) = 42')
    %      ans =
    %      y(0) == 42
    %
    %      >> str2symInternal({'42', 'a', 'y(0)'})
    %      ans =
    %      [ 42, a, y(0)]
    %
    %      >> str2symInternal('[42, a, y(0)]')
    %      ans =
    %      [ 42, a, y(0)]
    
    %   Copyright 2017-2019 The MathWorks, Inc.
    
    arguments
        S string
        options.Inert logical = false
    end
    inertMode = options.Inert;
    
    
    % Convert newlines and tabs to spaces (newline are not supported by evalin)
    if any(contains(S(:),newline))
        warning(message("symbolic:str2sym:NewlinesIgnored"));
    end
    S = regexprep(S, "\s", " ");
    
    % Treat assigmnments as equations by replacing "=" by "==".
    % --- But do not replace "=" in "<=", ">=", "~=", and "==".
    S = regexprep(S, "(?<![<>~=])=(?![<>~=])", "=="); 
    
    % Keep size of input for output
    mupstr = string(zeros(size(S)));
    
    variables = string([]);
    
    % Iterate linearly over string array and convert to SYM.
    for idx = 1:numel(S)
        % Behave like sym function on missing.
        if ismissing(S(idx))
            mupstr(idx) = "sym(NaN)";
            continue;
        end
    
        % Empty string results in empty sym.
        if replace(S(idx)," ","") == ""
            mupstr(idx) = "sym([])";
            continue;
        end
    
        if ~isempty(regexp(S(idx), "^\s*%{\s*$", "once")) || ~isempty(regexp(S(idx), "^\s*%}\s*$", "once"))
            % Note that newlines were replaced by blanks before. The 
            % only valid occurance of "%{" and "%}" to start and end 
            % a block comment is in a new line with nothing else but
            % spaces. Otherwise it is handled as single-line comment.
            error(message("symbolic:str2sym:CommentsNotSupported"));
        end
        
        % Parse string and identify objects that must be treated as SYMs.
        mt = mtree(S(idx), "-com");
    
        % Handle syntax errors in input
        if ~isnull(mtfind(mt, "Kind", "ERR"))
            error(message("symbolic:str2sym:UnableToConvert", string(mt)));
        end
    
        % Handle left curly bracket node in input
        if ~isnull(mtfind(mt, "Kind", "LC")) 
            error(message("symbolic:str2sym:CellArrayNotSupported"));
        end
    
        % Collect objects that need special treatment
        objects = [];
    
        % Comments
        comments = mtfind(mt, "Kind", "COMMENT");
        if ~isnull(comments)
            comments = struct( ...
                'type',    "comment", ...
                'name',    "", ...
                'start',   num2cell(position(comments))', ...
                'end',     num2cell(endposition(comments))', ...
                'infixstart', 0, ...
                'infixend', 0, ...
                'fnoargs', false, ...
                'dcall',   false, ...
                'isi',     false ...
            );
            objects = [objects comments]; %#ok<AGROW>
        end
    
        % Numbers
        numbers = mtfind(mt, "Kind", {'INT', 'DOUBLE', 'HEX', 'BINARY'});
        if ~isnull(numbers)
            numbers = struct( ...
                'type',    "number", ...
                'name',    "", ...
                'start',   num2cell(position(numbers))', ...
                'end',     num2cell(endposition(numbers))', ...
                'infixstart', 0, ...
                'infixend', 0, ...
                'fnoargs', false, ...
                'dcall',   false, ...
                'isi',     false ...
            );
            objects = [objects numbers]; %#ok<AGROW>
        end
    
        % Functions calls, variables and special values
        calls = mtfind(mt, "Kind", {'CALL', 'DCALL'});
        if ~isnull(calls)
            funvars = struct( ...
                'type',    "function", ...
                'name',    strings(calls.Left), ...
                'start',   num2cell(position(calls.Left))', ...
                'end',     num2cell(endposition(calls.Left))', ...
                'infixstart', 0, ...
                'infixend', 0, ...
                'fnoargs', false, ...
                'dcall',   false, ...
                'isi',     false ...
            );
    
            % Depending on type of call, name might need special treatment.
            wrapName = true(1,count(calls));
            cidx = indices(calls);
            for i = 1:count(calls)
                % Note that DCALL nodes always have arguments.
                % The arguments for a DCALL call are always STRINGs. 
                funvars(i).dcall = iskind(select(calls,cidx(i)), "DCALL"); 
                if ~funvars(i).dcall
                    funvars(i).fnoargs = ~isempty(regexp(S(idx),"^.{" + funvars(i).end + "}\s*\(\s*\)", "once"));
                    if isnull(Right(select(calls,cidx(i)))) && ~funvars(i).fnoargs
                        % Call has no arguments (= right branch of tree)  and
                        % found no name() so it's a variable or special value
                        name = funvars(i).name;
                        if name == "i" || name == "j"
                            funvars(i).type = "special";
                            funvars(i).isi = true;
                        elseif any(name == ["pi", "catalan", "eulergamma", "inf", "Inf", "nan", "NaN", "missing", "symtrue", "symfalse"])
                            funvars(i).type = "special";
                            funvars(i).isi = false;
                        elseif any(name == ["true", "false"])
                            funvars(i).type = "logical";
                            funvars(i).isi = false;
                        else
                            funvars(i).type = "variable";
                        end
                        continue;
                    end
                end
                % We know: It's a function call with at least one argument.
                % Respect functions on search path: do not add sym wrapper.
                if inertMode
                    wh = string([]);
                else
                    wh = string(evalin("caller", "which('" + funvars(i).name + "')"));
                end
                if ~isempty(wh) && ~strcmp(wh, "variable")
                    % Note: 'which' is *not* case-sensitive so we need to double-check!
                    % e.g.: S:\Bsymbolic\matlab\toolbox\symbolic\symbolic\@sym\sym.m    % sym method
                    wh = regexprep(wh, "\s*%.*$", ""); % for robustness
                    % e.g.: built-in (S:\Bsymbolic\matlab\toolbox\matlab\datatypes\double)
                    wh = regexprep(wh, "\)$", "");
                    % e.g.: S:\Bsymbolic\matlab\toolbox\symbolic\symbolic\str2sym.m
                    wh = regexprep(wh, "\.m$", "");
                    % e.g.: plus is a built-in method           % string method
                    if startsWith(wh, funvars(i).name) || endsWith(wh, funvars(i).name)
                        wrapName(i) = false;
                    end
                end
            end
            objects = [objects funvars(wrapName)]; %#ok<AGROW>
        end
        
        if inertMode 
            infixNames = struct(...
                'PLUS', "_plus", ...
                'MINUS', "_subtract", ...
                'MUL',  "_mult", ...
                'DIV',  "_divide", ...
                'EXP',  "_power", ...
                'EQ', "_equal");
            infixOperators = mtfind(mt, "Kind", fieldnames(infixNames));
            if ~isnull(infixOperators)
                infixStruct = struct( ...
                'type',    "infix", ...
                'name',    num2cell(string(infixOperators.kinds))', ...
                'start',   num2cell(lefttreepos(infixOperators))', ...
                'end',     num2cell(righttreepos(infixOperators))', ...
                'infixstart', num2cell(position(infixOperators))', ...
                'infixend', num2cell(endposition(infixOperators))', ...
                'fnoargs', false, ...
                'dcall',   false, ...
                'isi',     false ...
                );
                objects = [objects infixStruct]; %#ok<AGROW>
            end
        end
        
        % Manipulate given string: take action on each identified object.
        T = S(idx);
        for i = 1:numel(objects)
            switch objects(i).type
                case "comment"
                    % Remove comment
                    [T, objects] = removeStringBetween(T, objects(i).start, objects(i).end, objects);
                case "number"
                    % Rewrite <o> to sym("<o>")
                    [T, objects] = addStringAtStart(T, objects, i, "sym(""");
                    [T, objects] = addStringAtEnd (T, objects, i,  """)");
                case "variable"
                    if nargout >= 2
                       variables = union(variables, getString(T, objects(i))); 
                    end
                    [T, objects] = addStringAtStart(T, objects, i, "sym(""");
                    [T, objects] = addStringAtEnd (T, objects, i,  """)");
                case "logical" 
                    if inertMode 
                      [T, objects] = addStringAtStart(T, objects, i, "sym(");
                      [T, objects] = addStringAtEnd(T, objects, i,   ")");
                    end  
                case "special"
                    % Rewrite <o> to sym(<o>)
                    if objects(i).isi
                        [T, objects] = addStringAtStart(T, objects, i, "1");
                    end
                    [T, objects] = addStringAtStart(T, objects, i, "sym(");
                    [T, objects] = addStringAtEnd(T, objects, i,   ")");
                case "function"
                    % Rewrite 'f(<any>)' to 'feval_internal(symengine, sym("f"), <any>)'
                    if objects(i).dcall
                        continue;
                    end
                    pos = objects(i).end;
                    while(extractBetween(T,pos,pos) ~= "(")
                        pos = pos + 1;
                    end
                    T = replaceBetween(T, pos, pos, ",");
                    if inertMode 
                       [T, objects] = insertStringBefore(T, pos, ")""", objects);
                    end  
                    if objects(i).fnoargs
                        % Rewrite 'f()' to 'feval_internal(symengine, sym("f"), "null()")'
                        [T, objects] = insertStringAfter(T, pos,   """null()""",                     objects);
                    end
                    if inertMode
                        [T, objects] = insertStringBefore(T, pos, """""", objects);
                        [T, objects] = addStringAtStart(T, objects, i, "feval_internal(symengine, ""symobj::inertproc(""""");
                    else
                        [T, objects] = addStringAtStart(T, objects, i, "feval_internal(symengine,sym(""");
                        [T, objects] = addStringAtEnd (T, objects, i,  """)");
                    end
                case "infix"
                    % can only happen in inert mode
                    % replace operator by comma
                    pos = objects(i).infixstart;
                    endpos = objects(i).infixend;
                    % replace the the operator by a comma, e.g., "2 * 2" -> "2 , 2" 
                    [T, objects] = replaceStringBetween(T, objects, pos, endpos, ",");
                    % declare the object non-infix
                    objects(i).infixstart = 0;
                    objects(i).infixend = 0;
                    % Convert the MATLAB name to a MuPAD name, 
                    % e.g., "MUL" -> "_mult"
                    mupname = infixNames.(objects(i).name);
                    % add MuPAD name in front
                    [T, objects] = addStringAtStart(T, objects, i, "feval_internal(symengine, ""hold(" + mupname + ")"",");
                    % close the bracket "feval_internal(..."
                    [T, objects] = addStringAtEnd(T, objects, i,   ")");
            end
        end
    
        if replace(T," ","") == ""
            mupstr(idx) = "sym([])";
        else
            mupstr(idx) = T;
        end
    end
    
    end
    
    
    % Helper: getString
    % returns the substring of text that corresponds to obj
    function T = getString(text, obj)
    range = obj.start : obj.end;
    T = text{1}(range);
    end
    
    % Helper: removeStringBetween
    function [text, objs] = removeStringBetween(text, left, right, objs)
    text = replaceBetween(text, left, right, "");
    objs = adaptStringPositions(objs, left, left-right-1);
    end
    
    % Helper: replaceStringBetween
    % Replace the string between left and right by newtext
    function [text, objs] = replaceStringBetween(text, objs, left, right, newtext)
    text = replaceBetween(text, left, right, newtext);
    len = strlength(newtext);
    objs = adaptStartPositions(objs, left+1, left-right-1+len);
    objs = adaptEndPositions(objs, left, left-right-1+len);
    objs = adaptInfixPositions(objs, left, left-right-1+len);
    end
    
    % Helper: insertStringBefore
    function [text, objs] = insertStringBefore(text, pos, textBefore, objs)
    text = insertBefore(text, pos, textBefore);
    objs = adaptStringPositions(objs, pos, strlength(textBefore));
    end
    
    % Helper addStringAtStart
    % adds a string at the start of the n-th object
    function [text, objs] = addStringAtStart(text, objs, n, textBefore)
    len = strlength(textBefore);
    startpos = objs(n).start;
    text = insertBefore(text, startpos, textBefore);
    for i = 1:numel(objs)
        if objs(i).start == startpos && objs(i).end < objs(n).end ...
                || objs(i).start > startpos
            % If objs(i) is an inner object (subtree) of objs(n),
            % or if it is a later object, modify the start.
            % Example: 2*2 + 3 -> _plus(2*2, 3). The start of 2*2 is shifted.
            objs(i).start = objs(i).start + len;
            % else objs(n) is a subtree of objs(i), or an object to the left.
            % Do not modify the start.
            % Example: 2*2 + 3 -> _mult(2, 2) + 3. The sum still begins at 1.
        end
    end
    % adapt infix and end positions of all objects, including objs(n)
    objs = adaptInfixPositions(objs, startpos, len);
    objs = adaptEndPositions(objs, startpos, len);
    end
    
    
    % Helper addStringAtEnd
    % adds a string at the end of the n-th object
    function [text, objs] = addStringAtEnd(text, objs, n, textAfter)
    len = strlength(textAfter);
    endpos = objs(n).end;
    text = insertAfter(text, endpos, textAfter);
    for i = 1:numel(objs)
        if objs(i).end == endpos && objs(i).start <= objs(n).start ...
                || objs(i).end > endpos
            % If objs(n) is a subtree of objs(i), or i=n,
            % or if objs(i) is a later object, modify the end of objs(i).
            % Example: _plus(3 + 2*2 -> _plus(3, 2*2).
            % The sum includes the closing bracket, the end of the product
            % remains the same.
            objs(i).end = objs(i).end + len;
        end
    end
    % adapt infix and start positions of all objects on the right
    % of objs(n).
    objs = adaptInfixPositions(objs, endpos, len);
    objs = adaptStartPositions(objs, endpos, len);
    end
    
    
    % Helper: insertStringAfter
    function [text, objs] = insertStringAfter(text, pos, textAfter, objs)
    text = insertAfter(text, pos, textAfter);
    objs = adaptStringPositions(objs, pos, strlength(textAfter));
    end
    
    function objs = adaptInfixPositions(objs, pos, len)
    for i=1:numel(objs)
        if pos <= objs(i).infixstart
            objs(i).infixstart = objs(i).infixstart + len;
        end
        if pos <= objs(i).infixend
            objs(i).infixend = objs(i).infixend + len;
        end
    end
    end
    
    function objs = adaptStartPositions(objs, pos, len)
    for i=1:numel(objs)
        if pos <= objs(i).start
            objs(i).start = objs(i).start + len;
        end
    end
    end
    
    
    function objs = adaptEndPositions(objs, pos, len)
    for i=1:numel(objs)
        if pos <= objs(i).end
            objs(i).end = objs(i).end + len;
        end
    end
    end
    
    % Helper: adaptStringPositions
    function objs = adaptStringPositions(objs, pos, len)
    for i=1:numel(objs)
        if pos <= objs(i).start
            objs(i).start = objs(i).start + len;
        end
        if pos <= objs(i).end
            objs(i).end = objs(i).end + len;
        end
    end
    objs = adaptInfixPositions(objs, pos, len);
    end
    
    
    
    
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

问题事件

  • 系统已结题 12月20日
  • 已采纳回答 12月12日
  • 创建了问题 12月12日

悬赏问题

  • ¥15 2020长安杯与连接网探
  • ¥15 关于#matlab#的问题:在模糊控制器中选出线路信息,在simulink中根据线路信息生成速度时间目标曲线(初速度为20m/s,15秒后减为0的速度时间图像)我想问线路信息是什么
  • ¥15 banner广告展示设置多少时间不怎么会消耗用户价值
  • ¥16 mybatis的代理对象无法通过@Autowired装填
  • ¥15 可见光定位matlab仿真
  • ¥15 arduino 四自由度机械臂
  • ¥15 wordpress 产品图片 GIF 没法显示
  • ¥15 求三国群英传pl国战时间的修改方法
  • ¥15 matlab代码代写,需写出详细代码,代价私
  • ¥15 ROS系统搭建请教(跨境电商用途)