Beispiel #1
0
//.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- DtOptItem::ParseOpt -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-
//
void  DtOptItem::ParseOpt(DtOptItem* Options, int NumOpt, int argc, char* argv[], 
                                                                  list<wstring>& FreeArgs)
{
    // First assign default values to all options
    for (int i=0; i<NumOpt; i++)
    {
        Options[i].m_Option.m_Type = Options[i].m_Type;
        switch (Options[i].m_Type)
        {
        case OPT_TYPE_BOOL:
        case OPT_TYPE_INT:
            Options[i].m_Option.m_IntValue = Options[i].m_IntValue;
            break;
        case OPT_TYPE_INT64:
            Options[i].m_Option.m_Int64Value = Options[i].m_Int64Value;
            break;
        case OPT_TYPE_DOUBLE:
            Options[i].m_Option.m_DoubleValue = Options[i].m_DoubleValue;
            break;
        case OPT_TYPE_STRING:
            break;
        case OPT_TYPE_STRING_LIST:
            Options[i].m_Option.m_Strings.clear();
            Options[i].m_Option.m_IntValue = Options[i].m_IntValue;
            for (int j=0; j<Options[i].m_Option.m_IntValue; j++)
                Options[i].m_Option.m_Strings.push_back(wstring());
            break;
        default:
            assert(false);
        }
    }
    bool  CheckOptions = true;
    // And then parse the actual commandline arguments
    for (int i=1; i<argc; i++)
    {
#ifdef WINBUILD
        if (CheckOptions && (argv[i][0]=='-' || argv[i][0]=='/'))
#else
        if (CheckOptions && argv[i][0]=='-')
#endif
        {
            if (argv[i][1] == '-')
            {
                CheckOptions = false;
                continue;
            }
            string  OptName(argv[i] + 1);
            wstring  WOptName(OptName.begin(), OptName.end());
            int j;
            for (j=0; j<NumOpt; j++)
            {
                if (Options[j].m_Name != WOptName)
                    continue;

                Options[j].m_Option.m_IsSet = true;
                if (Options[j].m_Type == OPT_TYPE_BOOL)
                {
                    Options[j].m_Option.m_IntValue = true;
                    break;
                }

                if (Options[j].m_Type == OPT_TYPE_STRING_LIST)
                {
                    if (i == argc - Options[j].m_IntValue)
                        throw DtOptException(L"Not enough arguments for command-line "
                                                            L"option: -%ls (expected %d)",
                                                            WOptName.c_str(),
                                                            Options[j].m_IntValue);
                    list<wstring>::iterator  It=Options[j].m_Option.m_Strings.begin();
                    for (int k=0; k<Options[j].m_IntValue; k++)
                    {
                        string  OptArg(argv[++i]);
                        *It = wstring(OptArg.begin(), OptArg.end());
                        It++;
                    }
                    break;
                }

                if (i == argc - 1)
                    throw DtOptException(L"Missing argument for command-line option: -%ls", 
                                                                        WOptName.c_str());
                string  OptArg(argv[++i]);
                Options[j].m_Option.m_StrValue = wstring(OptArg.begin(), OptArg.end());

                if (Options[j].m_Type == OPT_TYPE_DOUBLE)
                    Options[j].ParseDoubleOpt();
                else if (Options[j].m_Type == OPT_TYPE_INT)
                    Options[j].ParseIntOpt();
                else if (Options[j].m_Type == OPT_TYPE_INT64)
                    Options[j].ParseInt64Opt();
                break;
            }
            if (j == NumOpt)
                throw DtOptException(L"Unknown command-line option (-%ls) encountered", 
                                                                        WOptName.c_str());
        } else {
            string  Opt(argv[i]);
            FreeArgs.push_back(wstring(Opt.begin(), Opt.end()));
        }
    }
}
Beispiel #2
0
/* The main program.  Parse the command line and do it... */
int main(int argc, char **argv)
{
    static int version = 0;
    static int rpflag = 0;
    static int basisflag = 0;
    static int compress = 0;
    static int quiet = 0;
    static int statistics = 0;
    static int mhflag = 0;
    static struct s_options options[] = {
        {OPT_FLAG, "b", (char*)&basisflag, "Print only the basis in report."},
        {OPT_FLAG, "c", (char*)&compress, "Don't compress the action table."},
        {OPT_FSTR, "D", (char*)handle_D_option, "Define an %ifdef macro."},
        {OPT_FLAG, "g", (char*)&rpflag, "Print grammar without actions."},
        {OPT_FSTR, "l", (char*)handle_l_option, "Set an output language (c, c++, d)."},
        {OPT_FLAG, "m", (char*)&mhflag, "Output a makeheaders compatible file"},
        {OPT_FLAG, "q", (char*)&quiet, "(Quiet) Don't print the report file."},
        {OPT_FLAG, "s", (char*)&statistics,
            "Print parser stats to standard output."},
        {OPT_FLAG, "x", (char*)&version, "Print the version number."},
        {OPT_FLAG,0,0,0}
    };
    int i;
    struct lemon lem;
    
    OptInit(argv,options,stderr);
    if( version ){
        printf("Lemon version 1.0\n");
        exit(0);
    }
    if( OptNArgs()!=1 ){
        ErrorMsg("lemon", LINENO_NONE, "Exactly one filename argument is required.\n");
        exit(1);
    }
    memset(&lem, 0, sizeof(lem));
    lem.errorcnt = 0;
    
    /* Initialize the machine */
    Strsafe_init();
    Symbol_init();
    State_init();
    lem.argv0 = argv[0];
    lem.filename = OptArg(0);
    lem.basisflag = basisflag;
    Symbol_new("$");
    lem.errsym = Symbol_new("error");
    lem.errsym->useCnt = 0;
    
    /* Parse the input file */
    Parse(&lem);
    if( lem.errorcnt ) exit(lem.errorcnt);
        if( lem.nrule==0 ){
            ErrorMsg(lem.filename, LINENO_NONE, "Empty grammar.\n");
            exit(1);
        }
    
    /* Count and index the symbols of the grammar */
    lem.nsymbol = Symbol_count();
    Symbol_new("{default}");
    lem.symbols = Symbol_arrayof();
    for(i=0; i<=lem.nsymbol; i++) lem.symbols[i]->index = i;
        qsort(lem.symbols,lem.nsymbol+1,sizeof(struct symbol*),
              (int(*)())Symbolcmpp);
        for(i=0; i<=lem.nsymbol; i++) lem.symbols[i]->index = i;
            for(i=1; isupper(lem.symbols[i]->name[0]); i++);
    lem.nterminal = i;
    
    /* Generate a reprint of the grammar, if requested on the command line */
    if( rpflag ){
        Reprint(&lem);
    }else{
        /* Initialize the size for all follow and first sets */
        SetSize(lem.nterminal+1);
        
        /* Find the precedence for every production rule (that has one) */
        FindRulePrecedences(&lem);
        
        /* Compute the lambda-nonterminals and the first-sets for every
         ** nonterminal */
        FindFirstSets(&lem);
        
        /* Compute all LR(0) states.  Also record follow-set propagation
         ** links so that the follow-set can be computed later */
        lem.nstate = 0;
        FindStates(&lem);
        lem.sorted = State_arrayof();
        
        /* Tie up loose ends on the propagation links */
        FindLinks(&lem);
        
        /* Compute the follow set of every reducible configuration */
        FindFollowSets(&lem);
        
        /* Compute the action tables */
        FindActions(&lem);
        
        /* Compress the action tables */
        if( compress==0 ) CompressTables(&lem);
        
        /* Reorder and renumber the states so that states with fewer choices
         ** occur at the end. */
        ResortStates(&lem);
        
        /* Generate a report of the parser generated.  (the "y.output" file) */
        if( !quiet ) ReportOutput(&lem);
        
        /* Generate the source code for the parser */
        ReportTable(&lem, mhflag);
        
        /* Produce a header file for use by the scanner.  (This step is
         ** omitted if the "-m" option is used because makeheaders will
         ** generate the file for us.) */
        if (! mhflag && language != LANG_D)
            ReportHeader(&lem);
    }
    if( statistics ){
        LogMsg(LOGLEVEL_INFO, lem.filename, LINENO_NONE,
               "Parser statistics: %d terminals, %d nonterminals, %d rules\n",
               lem.nterminal, lem.nsymbol - lem.nterminal, lem.nrule);
        LogMsg(LOGLEVEL_INFO, lem.filename, LINENO_NONE,
               "                   %d states, %d parser table entries, %d conflicts\n",
               lem.nstate, lem.tablesize, lem.nconflict);
    }
    if( lem.nconflict ){
        LogMsg(LOGLEVEL_WARNING, lem.filename, LINENO_NONE, "%d parsing conflicts.\n", lem.nconflict);
    }
    exit(lem.errorcnt + lem.nconflict);
    return (lem.errorcnt + lem.nconflict);
}