Construct matching questions

Product Compare Forums Multi-Edit Support Construct matching questions

Viewing 8 posts - 1 through 8 (of 8 total)
  • Author
    Posts
  • #2568
    jayterry
    Participant

    I’m 99% done with the Powerbasic support macros, just a couple of minor things I’d like to perfect.

    When construct matching IF statements, everything works fine EXCEPT one condition. There are 2 forms of IF. The first is an IF block, as in
    [code:c3l1lyzd]
    IF integer_expression THEN
    {statements}
    [ELSEIF integer_expression THEN
    {statements}]
    [ELSE
    {statements}]
    END IF
    [/code:c3l1lyzd]
    Then there is the single-line format:
    [code:c3l1lyzd]
    IF integer_expression THEN {sub|label|statements} [ELSE {sub|label|statements}]
    [/code:c3l1lyzd]

    My construct matching handles the block format just fine, including nested blocks within blocks. The problem is if there is a single-line IF anywhere inside the IF … ENDIF block. In that case it does not work correctly. As in:
    [code:c3l1lyzd]
    IF expression THEN
    statement(s)
    IF expression THEN statement ELSE statement
    ELSE
    statement(s)
    END IF
    [/code:c3l1lyzd]
    I thought that I could use a _mtchIgnore to skip an IF line if it had anything following the THEN on the same line (except whitespace), but I cannot get that to work. Here is what I tried.
    [code:c3l1lyzd]
    _mtchSep + "IF" + // Match IF/ELSE/ELSEIF/END IF
    _mtchSep + "ELSE" +
    _mtchSep + "ELSEIF" +
    _mtchFlags + mtchFlags_If +
    _mtchBeg + "|IF|" +
    _mtchMid + "|ELSE|ELSEIF|" +
    _mtchEnd + "|END IF|" +
    _mtchExp + "((END +)@IF)|((EXIT +)@IF)|(ELSE)|(ELSEIF)" +
    //_mtchIgnore + "|EXIT IF|" +
    _mtchIgnore + "|(IF<b1>(.+)<b1>THEN<b1>(.+)$)|EXIT IF|" +
    [/code:c3l1lyzd]
    Any ideas how I could get this constuct match to work the way I want?

    Thanks

    #8562
    deleyd
    Participant

    It looks like Language.s LangDoMatch uses:[code:16y41yy6] // Do actual text search
    TTRACE( "Language", TDBG_TRACE, "Search – FStrLen=%d %d:%d ‘%s’", FStrLen, C_Line, C_Col, S_Str );
    S_Res = Find_Text( S_Str, Scope, REStyle | Direction );
    [/code:16y41yy6]
    to do the search, then does:
    [code:16y41yy6] if ( XPos( Delim + FStr + Delim, IStr1, 1 ) ) {[/code:16y41yy6]
    to check for a ignore part, so it’s looking for an exact match, not using regular expressions.

    You can specify your own search macro instead of using Language.s LangDoMatch(). In your <language>Match macro (e.g. AwkMatch) it usually just calls LangDoMatch[code:16y41yy6] Return_Int = LangDoMatch( "Awk", "", TStr );
    [/code:16y41yy6]
    but you could change that to call your own macro instead. (You could copy LangDoMatch then make any modifications you want. I think I did that once. I’ll search to see if I can find any code I wrote. Don’t quite recall.)

    #8563
    jayterry
    Participant

    Hmm, I don’t think I can do "ignore an IF…THEN if the THEN is followed by anything other than whitespace or EOL" without a regex. So if Ignore doesn’t take a regex, then I suppose the only way to handle is as you suggest – copy LangDoMatch and make my own customizations.

    But, have mercy, that’s one hellacious long complicated macro to learn. I’d say it’s not worth it, but unfortunately having embedded single line IF statements inside an IF…ENDIF block is a pretty common thing – as in
    [code:6j2njb40]
    IF this THEN
    IF a=b THEN c=d
    IF e=f THEN g=h
    ELSE
    IF i=j THEN k=l
    END IF
    [/code:6j2njb40]
    So I may have to force myself to do it.

    #8564
    deleyd
    Participant

    I found it was for a special CIRWIN language, I made CIRWIN.s, in which I copied LangDoMatch to create CirwinLangDoMatch(). And CirwinMatch() calls CirwinLangDoMatch() instead of LangDoMatch().

    Attached is CIRWIN.s

    (The LangDoMatch() used to make CirwinLangDoMatch was probably from ME2006.)

    Anyway, try copying over LangDoMatch(), then change that one line that currently uses XPOS to determine if we should ignore this line to something that uses a regular expression.

    Let’s see if I can figure this out:[code:3p78areh] if ( XPos( Delim + FStr + Delim, IStr1, 1 ) ) {

    // found ignore string so continue to next match
    [/code:3p78areh]
    and IStr1 is,… the ignore match expression, OK that’s not what I want,…

    Let’s see, we did a[code:3p78areh] S_Res = Find_Text( S_Str, Scope, REStyle | Direction );
    [/code:3p78areh]and I don’t see us moving off the found line, so all we need to do is check the current line, perhaps with something like:
    [code:3p78areh]mark_pos;
    goto_col(1);
    int stat;
    stat = find_text(<some perl regular expression>,1,_PerlExp);
    goto_mark;
    if (stat)
    {
    // Found ignore string so abort search
    .
    .
    .
    [/code:3p78areh]

    (I’m not sure if it’s necessary to do all that push mark / pop mark (mark_pos/goto_mark) to put us back exactly where we were.) (The 1 in the Find_Text(,1,) means search just this one line only.)
    CIRWIN.s

    #8565
    jayterry
    Participant

    Ok, I’ve been playing with it a bit, but haven’t gotten it working yet. I copied over LangDoMatch into my PowerBasic.s, renamed it LangDoMatch_PB, and changed my calls to that.

    There are 3 places where LangDoMatch says it’s looking at the ignore string. I replaced it in each case with this:
    [code:1szviia0]
    // ———————————————– //
    // MOD to use regex for ignore string
    mark_pos; goto_col(1);
    FoundIgnore = Find_Text(IStr1,1,REStyle);
    goto_mark;
    if (FoundIgnore) {
    // ———————————————– //
    //Original IF statement
    //if ( XPos( Delim + FStr + Delim, IStr1, 1 ) ) {
    // ———————————————– //
    [/code:1szviia0]
    FoundIgnore is previously defined as an int. I’m using REStyle, so it will use the same regex flavor as the rest of the construct matching expressions. Probably need to do a ReTranslate on IStr1, but for now I’m not using in aliases in the ignore string, so that shouldn’t be a problem.

    What would be really handy is a command (macro) to search for a regex in a string – as opposed to only being able to search for a regex in file lines. Then that command "should" just be a drop in replacement of the Xpos test. Something like Find_Text_In_String(regex,string,regextype). But, of course, that’s something else to write. Probably could just copy the string to a temp buffer, then use Find_Text against it.

    But if I do write that, then I could just do this:
    [code:1szviia0]
    Replace
    if ( XPos( Delim + FStr + Delim, IStr1, 1 ) ) {
    with
    if ( Find_Text_In_String( IStr1, Delim + FStr + Delim, REStyle ) ) {
    [/code:1szviia0]

    #8566
    jayterry
    Participant

    I took a shot at writing a macro to do a regex search of a string. I thought I would be able to use a buffer, copy the string to it, then do a Find_Text against what I just wrote to the buffer. What I’m getting is that my debug message shows the current line is always blank, i.e. not the string that I just wrote to it.

    Any suggestions as to what I’m doing wrong?
    [code:wuejp3je]

    /*——————————————————————————
    Function: Search a string using a regex
    Entry : /RE=str – A regex to find
    /SS=str – A string to be searched
    /RETYPE=int – Regex flavor (rasUnix, rasPerl)
    Exit : int Found – 0=not found, 1=found
    —————————————————————————–*/
    int Find_InString(
    str IRex[MAX_LINE_LENGTH] = parse_str("/RE=",mparm_str),
    str SStr[MAX_LINE_LENGTH] = parse_str("/SS=",mparm_str),
    int REStyle = parse_int("/RETYPE=",mparm_str))
    {
    int Source_Win = Cur_Window;
    int SavRefresh = Refresh;
    int SavInsertMode = Insert_Mode;
    int Found = false;

    DebugLog(0,"FIS","IRex[%s] SStr[%s] REStyle[%d]",IRex,SStr,REStyle);
    Refresh = false;
    Insert_Mode = true;

    SwitchToBuffer(0);
    Eof;
    if (C_Col != 1) {Down; Goto_Col(1);}
    Mark_Pos;
    TEXT(SStr);
    GoTo_Mark;
    IRex = ReTranslate(IRex,REStyle);
    DebugLog(0,"FIS","XlatedIRex[%s] CurLine[%s]",IRex,Get_Line);
    Found = Find_Text(IRex,0,REStyle);

    Switch_Window(Source_Win);
    Insert_Mode = SavInsertMode;
    Refresh = SavRefresh;
    DebugLog(0,"FIS","Found[%d]",Found);
    Return(Found);
    } // Find_InString

    void Test_Find_InString()
    {
    RM(’Find_InString /RE=sub/SS= sub /RETYPE=1’);
    //Find_InString("((static<b1>)?sub)","xx static sub xx",rasPerl);
    //Find_InString("((static<b1>)+sub)","xx static sub xx",rasUnix);
    //Find_InString("sub","xx static sub xx",rasUnix);
    //Find_InString("sub"," sub ",_RegExp);
    }
    [/code:wuejp3je]

    #8567
    deleyd
    Participant

    I think it has to do with a bug setting a marker beyond the end of file. Try replacing[code:2h6drl9r] Mark_Pos;
    TEXT(SStr);
    GoTo_Mark;
    [/code:2h6drl9r]
    with
    [code:2h6drl9r] TEXT(SStr);
    goto_col(1);
    [/code:2h6drl9r]
    or you could also try
    [code:2h6drl9r] Put_Line(SStr);
    goto_col(1);
    [/code:2h6drl9r]

    #8568
    jayterry
    Participant

    When I was first whipping up this macro, that’s exactly how I coded it. But then I thought – why make the assumption, and limit the macro, to only working with a 1 line string to search. You might could want to search against a marked block of lines or something like that. That’s why I put in the mark_pos to begin with, and also why I set Find_Text to search to eof (0) instead of just 1 line.

    Anyway, you’re apparently correct about mark_pos not working past eof. So instead of assuming 1 line, I just did my own kind of mark_pos, like so:
    [code:1ypntcoi]
    SwitchToBuffer(0);
    Eof;
    if (C_Col != 1) {Down; Goto_Col(1);}
    BufStartLine = C_Line;
    TEXT(SStr);
    Goto_Line(BufStartLine); Goto_Col(1);
    IRex = ReTranslate(IRex,REStyle);
    Found = Find_Text(IRex,0,REStyle);
    [/code:1ypntcoi]
    This now works fine.

    Now to go back to my custom LangDoMatch and try to use it there.

Viewing 8 posts - 1 through 8 (of 8 total)
  • You must be logged in to reply to this topic.