Announcement

Collapse
No announcement yet.
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Option parser

    Before I go too much into the rabbit hole
    Does anyone know of a command that parses all options in a command? (regardless of the command type?)
    For example, if I type
    cmd y x t, hc1 cluster(asd) xline(123) twoway(scatter v1 c2)

    It would create a local (r() or s()) with something like this:
    s(hc1) hc1
    s(cluster) asd
    s(xline) 123
    s(twoway) scatter v1 c2
    And, perhaps with a list of all these options
    s(optlist) hc1 cluster xline twoway

    Thank you!

  • #2
    syntax puts all options, as typed, into local macro options, when you type

    Code:
    syntax [ , * ]
    What is the context here? What are you trying to do?

    Comment


    • #3
      Well, when using that particular syntax, all options go into `options`. My case is a bit different.
      What I want to know is, before knowing apriori all those options, what options were used, with their details
      Its for passing and mixing arguments in a graph package I'm working on.
      (this is really a programming question)

      Comment


      • #4
        I'm not sure I understand what you are asking. Are you saying you are looking for a command that will return the options that were passed into an entirely different command at runtime? If so, are these options passed in by your user, or generated programmatically by your package? Are you looking to preform some kind of reflection on the options that your user passes into a command?

        Comment


        • #5
          Maybe this will help to illustrate how to parse the options:

          Code:
          local stropt = "hc1 cluster (asd) xline(123)  twoway(scatter v1 c2)"
          
          * FORMAT OPTIONS
          local cleanopt = stritrim("`stropt'")
          di "`cleanopt'"
          local cleanopt = subinstr("`cleanopt'", " (","(",.)
          di "`cleanopt'"
          local cleanopt = subinstr("`cleanopt'", "( ","(",.)
          di "`cleanopt'"
          
          
          * GET UPPER LEVEL OPTIONS
          local mainopt = "`cleanopt'"
          while strpos("`mainopt'","(")!=0 {
              local openpar = strpos("`mainopt'","(")
              local closepar = strpos("`mainopt'",")")-`openpar'+1
              if `closepar' <1 {
                  exit
              }
              local removestr = substr("`mainopt'",`openpar',`closepar')
              local mainopt = subinstr("`mainopt'","`removestr'","",.)
          }
          
          * PARSE OPTIONS
          foreach option in `mainopt' {
              di "`option': " _continue
              local openpar = strpos("`cleanopt'","`option'(")
              if `openpar'==0 {
                  di "`option'"
                  local cleanopt = subinstr("`cleanopt'", "`option'","",.)
              }
              else {
                  local openpar = strpos("`cleanopt'","(")+1
                  local closepar = strpos("`cleanopt'",")")-`openpar'
                  local suboption = substr("`cleanopt'",`openpar',`closepar')
                  di "`suboption'"
                  local cleanopt = subinstr("`cleanopt'", "`option'(`suboption')","",.)
              } 
          }

          Comment


          • #6
            Maybe some variant of
            Code:
            * .\mytest.ado 
            
            prog define mytest, rclass
            
                syntax , hc1 cluster(string) xline(int) twoway(string)
            
                _sub_parse_args `0'
            
                * cont ...
                
            end
            
            prog define _sub_parse_args,  sclass
            
                gettoken first 0 : 0 , parse(",")
            
                sreturn local opts `0' 
                  
                while "`0'" != "" {
            
                    gettoken opt 0 : 0 , bind
                    
                    if ( ustrregexm("`opt'", "^(.*)\((.*)\)") ) {
            
                        sreturn local `=ustrregexs(1)' "`=ustrregexs(2)'"    
                    }
                    
                    else {
                        
                        sreturn local `opt' `opt'
                    }  
                }
            
            end
            
            exit // test 
            
            mytest , hc1 cluster(asd) xline(123) twoway(scatter v1 c2)
            sret li
            Code:
            . mytest , hc1 cluster(asd) xline(123) twoway(scatter v1 c2)
            
            . sret li
            
            macros:
                         s(twoway) : "scatter v1 c2"
                          s(xline) : "123"
                        s(cluster) : "asd"
                            s(hc1) : "hc1"
                           s(opts) : "hc1 cluster(asd) xline(123) twoway(scatter v1 c2)"
            Last edited by Bjarte Aagnes; 03 Mar 2023, 09:31.

            Comment


            • #7
              Thank you, Daniel
              So what I have in mind was more in line the truly undocumented command "_iv_parse.ado". This command takes all arguments given by a regression command, and ids endogenous and exogenous factors,
              In my case, i want to have something only for options that is more general.
              The code Daniel provides does what i have in mind.
              Although, I ended up doing more of my own, and got to the following:

              Code:
              capture program drop myparser
              capture program drop smyparser
              program myparser, sclass
                  syntax,[*]
                  sreturn clear
                  local op `options'
                  local true 1
                  while `true' {
                      gettoken i op:op,   bind
                      gettoken ii x:i , parse("(")
                      if "`i'"=="" {
                          local true 0
                          break
                      }
                      else {
                          if strlen("`i'")==strlen("`ii'") sreturn local `ii' __self__        
                          else {
                              smyparser `ii', `i'
                              sreturn local `ii' `s(xxxopt)'    
                          }
                          local listopt `listopt' `ii'
                      }    
                  }
                  sreturn local xxxopt
                  sreturn local opt_list `listopt'
                  sreturn local org_list `options'
              end
               program smyparser, sclass
                  syntax namelist,[*]
                  local nm `namelist'
                  syntax namelist, `nm'(str asis)
                  sreturn local xxxopt ``nm''
              end
               
              myparser , robust cluster(asd) save(asd) rif(save)
              sreturn list
              Now I may have to do a bit of recursion here get more sub-levels of functions, but this is more than enough for what i need.
              Thank you

              Comment

              Working...
              X