⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 yecc.erl

📁 OTP是开放电信平台的简称
💻 ERL
📖 第 1 页 / 共 5 页
字号:
atom_option(verbose) -> {verbose, true};atom_option(Key) -> Key.is_filename(T) ->    try filename:flatten(T) of        Filename -> Filename    catch error: _ -> no    end.    shorten_filename(Name0) ->    {ok,Cwd} = file:get_cwd(),    case lists:prefix(Cwd, Name0) of        false -> Name0;        true ->            case lists:nthtail(length(Cwd), Name0) of                "/"++N -> N;                N -> N            end    end.start(Infilex, Options) ->    Infile = assure_extension(Infilex, ".yrl"),    {value, {_, Outfilex0}} = keysearch(parserfile, 1, Options),    {value, {_, Includefilex}} = keysearch(includefile, 1, Options),    Outfilex = case Outfilex0 of                   [] -> filename:rootname(Infilex, ".yrl");                   _ -> Outfilex0               end,    Includefile = case Includefilex of                      [] -> [];                      _ -> assure_extension(Includefilex,".hrl")                  end,    Outfile = assure_extension(Outfilex, ".erl"),    Module = list_to_atom(filename:basename(Outfile, ".erl")),    #yecc{infile = Infile,           outfile = Outfile,          includefile = Includefile,          module = Module,          options = Options,          verbose = member(verbose, Options),          file_attrs = member(file_attributes, Options)}.assure_extension(File, Ext) ->    concat([strip_extension(File, Ext), Ext]).%% Assumes File is a filename.strip_extension(File, Ext) ->    case filename:extension(File) of        Ext -> filename:rootname(File);        _Other -> File    end.infile(Parent, Infilex, Options) ->    St0 = start(Infilex, Options),    St = case file:open(St0#yecc.infile, [read, read_ahead]) of             {ok, Inport} ->                 try                      outfile(St0#yecc{inport = Inport})                 after                     ok = file:close(Inport)                 end;             {error, Reason} ->                 add_error(St0#yecc.infile, none, {file_error, Reason}, St0)         end,    case St#yecc.errors of        [] -> ok;        _ -> _ = file:delete(St#yecc.outfile)    end,    Parent ! {self(), yecc_ret(St)}.outfile(St0) ->    case file:open(St0#yecc.outfile, [write, delayed_write]) of        {ok, Outport} ->            try                 generate(St0#yecc{outport = Outport})            catch                 throw: St1  ->                    St1;                exit: Reason ->                    add_error({internal_error, Reason}, St0)            after               ok = file:close(Outport)            end;        {error, Reason} ->            add_error(St0#yecc.outfile, none, {file_error, Reason}, St0)    end.os_process_size() ->    case os:type() of        {unix, sunos} ->            Size = os:cmd("ps -o vsz -p " ++ os:getpid() ++ " | tail -1"),            list_to_integer(lib:nonl(Size));        _ ->            0    end.            timeit(Name, Fun, St0) ->    Time = runtime,    %% Time = wall_clock,    {Before, _} = statistics(Time),    St = Fun(St0),     {After, _} = statistics(Time),    Mem0 = erts_debug:flat_size(St)*erlang:system_info(wordsize),    Mem = lists:flatten(io_lib:format("~.1f kB", [Mem0/1024])),    Sz = lists:flatten(io_lib:format("~.1f MB", [os_process_size()/1024])),    io:fwrite(" ~-30w: ~10.2f s ~12s ~10s\n",               [Name, (After-Before)/1000, Mem, Sz]),    St.-define(PASS(P), {P, fun P/1}).generate(St0) ->    Passes = [?PASS(parse_grammar), ?PASS(check_grammar),              ?PASS(states_and_goto_table), ?PASS(parse_actions),              ?PASS(action_conflicts), ?PASS(write_file)],    F = case member(time, St0#yecc.options) of            true ->                 io:fwrite("Generating parser from grammar in ~s\n",                           [format_filename(St0#yecc.infile)]),                fun timeit/3;            false ->                fun(_Name, Fn, St) -> Fn(St) end        end,    Fun = fun({Name, Fun}, St) ->                  St2 = F(Name, Fun, St),                  if                       St2#yecc.errors =:= [] -> St2;                      true -> throw(St2)                  end          end,    foldl(Fun, St0, Passes).parse_grammar(St) ->    parse_grammar(St#yecc.inport, 1, St).parse_grammar(Inport, Line, St) ->    {NextLine, Grammar} = read_grammar(Inport, Line),    parse_grammar(Grammar, Inport, NextLine, St).parse_grammar(eof, _Inport, _NextLine, St) ->    St;parse_grammar({#symbol{name = 'Erlang'}, [#symbol{name = code}]}, _Inport,               NextLine, St) ->    St#yecc{erlang_code = NextLine};parse_grammar(Grammar, Inport, NextLine, St0) ->    St = parse_grammar(Grammar, St0),    parse_grammar(Inport, NextLine, St).parse_grammar({error,ErrorLine,Error}, St) ->    add_error(ErrorLine, Error, St);parse_grammar({rule, Rule, Tokens}, St0) ->    NmbrOfDaughters = case Rule of                          [_, #symbol{name = '$empty'}]  -> 0;                          _ -> length(Rule) - 1                      end,    St1 = check_action(Tokens, St0),    {Tokens1, St2} = subst_pseudo_vars(Tokens,                                       NmbrOfDaughters,                                       St1),    RuleDef = #rule{symbols = Rule, tokens = Tokens1},    St2#yecc{rules_list = [RuleDef | St2#yecc.rules_list]};parse_grammar({prec, Prec}, St) ->    St#yecc{prec = Prec ++ St#yecc.prec};parse_grammar({#symbol{line = Line, name = Name}, Symbols}, St) ->    CF = fun(I) ->                 case element(I, St) of                     [] ->                          setelement(I, St, Symbols);                     _ ->                          add_error(Line, {duplicate_declaration, Name}, St)                 end         end,    OneSymbol = length(Symbols) =:= 1,    case Name of        'Nonterminals' -> CF(#yecc.nonterminals);        'Terminals' -> CF(#yecc.terminals);        'Rootsymbol' when OneSymbol -> CF(#yecc.rootsymbol);        'Endsymbol' when OneSymbol ->  CF(#yecc.endsymbol);        'Expect' when OneSymbol -> CF(#yecc.expect_shift_reduce);        'States' when OneSymbol -> CF(#yecc.expect_n_states); % undocumented        _ -> add_warning(Line, bad_declaration, St)    end.read_grammar(Inport, Line) ->    case yeccscan:scan(Inport, '', Line) of        {eof, NextLine} ->            {NextLine, eof};        {error, {ErrorLine, Mod, What}, NextLine} ->            {NextLine, {error, ErrorLine, {error, Mod, What}}};        {ok, Input, NextLine} ->            {NextLine, case yeccparser:parse(Input) of                           {error, {ErrorLine, Mod, Message}} ->                               {error, ErrorLine, {error, Mod, Message}};                           {ok, {rule, Rule, {erlang_code, Tokens}}} ->                               {rule, Rule, Tokens};                           {ok, {#symbol{name=P},                                  [#symbol{name=I} | OpL]}=Ss} ->                               A = precedence(P),                               if                                   A =/= unknown,                                    is_integer(I),                                   OpL =/= [] ->                                       Ps = [{Op, I , A} || Op <- OpL],                                       {prec, Ps};                                   true ->                                        Ss                               end                       end}    end.precedence('Left') -> left;precedence('Right') -> right;precedence('Unary') -> unary;precedence('Nonassoc') -> nonassoc;precedence(_) -> unknown.%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%check_grammar(St0) ->    Empty = #symbol{line = none, name = '$empty'},    AllSymbols = St0#yecc.nonterminals ++ St0#yecc.terminals ++ [Empty],    St1 = St0#yecc{all_symbols = AllSymbols},    Cs = [fun check_nonterminals/1, fun check_terminals/1,           fun check_rootsymbol/1, fun check_endsymbol/1,           fun check_expect/1, fun check_states/1,          fun check_precedences/1, fun check_rules/1],    foldl(fun(F, St) -> F(St) end, St1, Cs).check_nonterminals(St) ->    case St#yecc.nonterminals of         [] ->            add_error(nonterminals_missing, St);        Nonterminals ->            {Unique, Dups} = duplicates(names(Nonterminals)),            St1 = add_warnings(Dups, duplicate_nonterminal, St),            St2 = check_reserved(Unique, St1),            St2#yecc{nonterminals = [?ACCEPT | Unique]}    end.check_terminals(St0) ->    case St0#yecc.terminals of        [] ->            add_error(terminals_missing, St0);        Terminals ->            {Unique, Dups} = duplicates(names(Terminals)),            St1 = add_warnings(Dups, duplicate_terminal, St0),            Common = intersect(St1#yecc.nonterminals, Unique),            St2 = add_errors(Common, symbol_terminal_and_nonterminal, St1),            St3 = check_reserved(Unique, St2),            St3#yecc{terminals = ['$empty' | Unique]}    end.check_reserved(Names, St) ->    add_errors(intersect(Names, ['$empty', '$end', '$undefined']),               reserved, St).check_rootsymbol(St) ->    case St#yecc.rootsymbol of        [] ->            add_error(rootsymbol_missing, St);        [#symbol{line = Line, name = SymName}] ->            case kind_of_symbol(St, SymName) of                nonterminal ->                    St#yecc{rootsymbol = SymName};                _ ->                    add_error(Line, {bad_rootsymbol, SymName}, St)            end    end.check_endsymbol(St) ->    case St#yecc.endsymbol of        [] ->            St#yecc{endsymbol = '$end'};        [#symbol{line = Line, name = SymName}] ->            case kind_of_symbol(St, SymName) of                nonterminal ->                    add_error(Line, {endsymbol_is_nonterminal, SymName}, St);                terminal ->                    add_error(Line, {endsymbol_is_terminal, SymName}, St);                _ ->                    St#yecc{endsymbol = SymName}            end    end.check_expect(St0) ->    case St0#yecc.expect_shift_reduce of        [] ->            St0#yecc{expect_shift_reduce = 0};        [#symbol{name = Expect}] when is_integer(Expect) ->            St0#yecc{expect_shift_reduce = Expect};        [#symbol{line = Line, name = Name}] ->            St1 = add_error(Line, {bad_expect, Name}, St0),            St1#yecc{expect_shift_reduce = 0}    end.check_states(St) ->    case St#yecc.expect_n_states of        [] ->            St;        [#symbol{name = NStates}] when is_integer(NStates) ->            St#yecc{expect_n_states = NStates};        [#symbol{line = Line, name = Name}] ->            add_error(Line, {bad_states, Name}, St)    end.check_precedences(St0) ->    {St1, _} =         foldr(fun({#symbol{line = Line, name = Op},_I,_A}, {St,Ps}) ->                      case member(Op, Ps) of                          true ->                              {add_error(Line, {duplicate_precedence,Op}, St),                               Ps};                          false ->                              {St, [Op | Ps]}                      end              end, {St0,[]}, St0#yecc.prec),    foldl(fun({#symbol{line = Line, name = Op},I,A}, St) ->                  case kind_of_symbol(St, Op) of                      endsymbol ->                          add_error(Line,{precedence_op_is_endsymbol,Op}, St);                      unknown ->                          add_error(Line, {precedence_op_is_unknown, Op}, St);                      _ ->                           St#yecc{prec = [{Op,I,A} | St#yecc.prec]}                  end          end, St1#yecc{prec = []}, St1#yecc.prec).check_rule(Rule0, {St0,Rules}) ->    Symbols = Rule0#rule.symbols,    #symbol{line = HeadLine, name = Head} = hd(Symbols),    case member(Head, St0#yecc.nonterminals) of        false ->             {add_error(HeadLine, {undefined_nonterminal, Head}, St0), Rules};        true ->            St = check_rhs(tl(Symbols), St0),            Rule = Rule0#rule{line = HeadLine, symbols = names(Symbols)},            {St, [Rule | Rules]}    end.check_rules(St0) ->    {St,Rules0} = foldl(fun check_rule/2, {St0,[]}, St0#yecc.rules_list),    case St#yecc.rules_list of        [] ->            add_error(no_grammar_rules, St);        _ ->            Rule = #rule{line = none,                          symbols = [?ACCEPT, St#yecc.rootsymbol],                         tokens = []},            Rules1 = [Rule | Rules0],            Rules = map(fun({R,I}) -> R#rule{n = I} end,  count(0, Rules1)),

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -