• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            糯米

            TI DaVinci, gstreamer, ffmpeg
            隨筆 - 167, 文章 - 0, 評論 - 47, 引用 - 0
            數據加載中……

            [bash源碼分析] 3 語法分析 - 入口點


            語法分析 - 入口點


            --- main()
                我們打開shell.c的main函數,大概300來行,其主題都是圍繞這xxx_init,做各種初始化操作。
                我們可以略過不看,等遇到問題的時候再說。把目光放到最后一句 reader_loop()。這是一個循環讀
                入并執行命令的函數。

            --- reader_loop()
                位于eval.c的reader_loop()函數,其中仿佛只有調用read_command()是重點。

            --- read_command()
                同樣位于eval.c的read_command()函數。一開始那一段ALARM信號的處理讓人覺得很費解,難道
                在bash輸入命令還要有時間限制嗎?無論如何,這種看似偏門的、非關鍵性的東西,在代碼分析的初期
                是不能理會的,如果太深究這些東西,沒有把握代碼的主線,則會走入死胡同,而且會失去源碼分析
                的樂趣。
                代碼主線走入parse_command()函數。

            --- parse_command()
                同樣位于eval.c的parse_command()函數。它調用的yyparse()函數是語法分析的開始。
                用過yacc的人很明白這一點了。一開始我們看到文件列表中有y.tab.c這樣的文件,就能意識到bash也是
                利用yacc生成的代碼來完成語法分析的。

            --- Yacc的作用
                你只要告訴yacc三樣東西:語法、每一條語法的處理函數、負責詞法分析的函數
                yacc就會為你生成y.tab.c文件,只要調用這個文件中的yyparse()函數,就可以完成編譯器的
                詞法分析和語法分析的部分了。在分析的過程中,你剛剛指定的每一條語法對應的處理函數也會
                被調用。關于yacc的具體介紹,可以在網上搜搜,很多的。

                例子:
                告訴yacc:語法和對應的處理函數。
                expr : expr '+' expr { $$ = add($1, $3) }
                     | expr '*' expr { $$ = mul($1, $3) }
                     | expr '-' expr { $$ = sub($1, $3) }
                     | NUMBER
                      ;
                調用yyparse(),輸入 1 + 2
                add(1, 2) 就會被回調了
                在處理函數中 $$ 代表著處理函數的返回值
                $1 代表著該條語法中的第一個元素(expr)
                $2 代表著該條語法中的第二個元素('+')
                $3 代表著該條語法中的第三個元素(expr)
                至于說這些元素的類型,則會在前面定義。比如 %type<char *> expr 之類。
                具體的還是找篇文章看看吧。

            --- parse.y
                觀察Makefile可以發現:
                y.tab.c y.tab.h: parse.y
                    $(YACC) -d $(srcdir)/parse.y
                y.tab.c是由parse.y生成的。而parse.y中包含了語法和對應的處理函數,它是語法分析的核心文件。

                首先是一個%union定義
                %union {
                    WORD_DESC *word;        /* the word that we read. */
                    int number;            /* the number that we read. */
                    WORD_LIST *word_list;
                    COMMAND *command;
                    REDIRECT *redirect;
                    ELEMENT element;
                    PATTERN_LIST *pattern;
                }

                然后是一系列的token定義:

            /* Reserved words.  Members of the first group are only recognized
               in the case that they are preceded by a list_terminator.  Members
               of the second group are for [[...]] commands.  Members of the
               third group are recognized only under special circumstances. */
            %token IF THEN ELSE ELIF FI CASE ESAC FOR SELECT WHILE UNTIL DO DONE FUNCTION
            %token COND_START COND_END COND_ERROR
            %token IN BANG TIME TIMEOPT

            /* More general tokens. yylex () knows how to make these. */
            %token <word> WORD ASSIGNMENT_WORD
            %token <number> NUMBER
            %token <word_list> ARITH_CMD ARITH_FOR_EXPRS
            %token <command> COND_CMD
            %token AND_AND OR_OR GREATER_GREATER LESS_LESS LESS_AND LESS_LESS_LESS
            %token GREATER_AND SEMI_SEMI LESS_LESS_MINUS AND_GREATER LESS_GREATER
            %token GREATER_BAR

                讀入字符串流,返回token是詞法分析函數的責任。
                以%token定義,表明返回值是int類型
                以%token <word>定義,表明返回值是%union中對應的類型

                詞法分析函數是lex生成的,但這個工程好像把原始的
                .lex文件刪除了。我們只能看到生成后的yylex()函數。
                但有一個表,可以看出token對應的字串內容:

            /* Reserved words.  These are only recognized as the first word of a
               command. */
            STRING_INT_ALIST word_token_alist[] = {
              { "if", IF },
              { "then", THEN },
              { "else", ELSE },
              { "elif", ELIF },
              { "fi", FI },
              { "case", CASE },
              { "esac", ESAC },
              { "for", FOR },
            #if defined (SELECT_COMMAND)
              { "select", SELECT },
            #endif
              { "while", WHILE },
              { "until", UNTIL },
              { "do", DO },
              { "done", DONE },
              { "in", IN },
              { "function", FUNCTION },
            #if defined (COMMAND_TIMING)
              { "time", TIME },
            #endif
              { "{", '{' },
              { "}", '}' },
              { "!", BANG },
            #if defined (COND_COMMAND)
              { "[[", COND_START },
              { "]]", COND_END },
            #endif
              { (char *)NULL, 0}
            };

            /* other tokens that can be returned by read_token() */
            STRING_INT_ALIST other_token_alist[] = {
              /* Multiple-character tokens with special values */
              { "-p", TIMEOPT },
              { "&&", AND_AND },
              { "||", OR_OR },
              { ">>", GREATER_GREATER },
              { "<<", LESS_LESS },
              { "<&", LESS_AND },
              { ">&", GREATER_AND },
              { ";;", SEMI_SEMI },
              { "<<-", LESS_LESS_MINUS },
              { "<<<", LESS_LESS_LESS },
              { "&>", AND_GREATER },
              { "<>", LESS_GREATER },
              { ">|", GREATER_BAR },
              { "EOF", yacc_EOF },
              /* Tokens whose value is the character itself */
              { ">", '>' },
              { "<", '<' },
              { "-", '-' },
              { "{", '{' },
              { "}", '}' },
              { ";", ';' },
              { "(", '(' },
              { ")", ')' },
              { "|", '|' },
              { "&", '&' },
              { "newline", '\n' },
              { (char *)NULL, 0}
            };

            /* others not listed here:
                WORD            look at yylval.word
                ASSIGNMENT_WORD        look at yylval.word
                NUMBER            look at yylval.number
                ARITH_CMD        look at yylval.word_list
                ARITH_FOR_EXPRS        look at yylval.word_list
                COND_CMD        look at yylval.command
            */

                這些token在語法中會遇到的。

                接下來是對語法中每一項內容(編譯原理沒學好,不知道這個術語叫什么。。)的定義:

            /* The types that the various syntactical units return. */

            %type <command> inputunit command pipeline pipeline_command
            %type <command> list list0 list1 compound_list simple_list simple_list1
            %type <command> simple_command shell_command
            %type <command> for_command select_command case_command group_command
            %type <command> arith_command
            %type <command> cond_command
            %type <command> arith_for_command
            %type <command> function_def function_body if_command elif_clause subshell
            %type <redirect> redirection redirection_list
            %type <element> simple_command_element
            %type <word_list> word_list pattern
            %type <pattern> pattern_list case_clause_sequence case_clause
            %type <number> timespec
            %type <number> list_terminator

            %start inputunit

                從名字上來看,大概能知道是作什么的。
                %start 表示整個語法分析的入口是 inputunit 那一項。
                接著就是語法了,內容就比較多,不直接貼了。
                語法是我比較感興趣的地方,無論看哪本關于bash的書,都不如看代碼來的直接,呵呵。
                我們以后慢慢看。





            posted on 2010-07-25 10:19 糯米 閱讀(1255) 評論(0)  編輯 收藏 引用 所屬分類: Misc

            99久久精品午夜一区二区| 久久国产精品一区二区| 久久精品夜色噜噜亚洲A∨| 99久久精品日本一区二区免费| 奇米影视7777久久精品| 国产精品久久久久久福利漫画 | 久久精品成人欧美大片| 亚洲精品国产自在久久| 久久综合狠狠综合久久综合88 | 久久大香萑太香蕉av| 色欲综合久久中文字幕网| 久久综合九色综合久99 | 国内精品久久久久影院优| 97精品伊人久久久大香线蕉| 亚洲综合久久夜AV | 国产亚州精品女人久久久久久| 波多野结衣久久| 久久精品二区| www.久久热.com| 天天爽天天狠久久久综合麻豆| 久久九九久精品国产免费直播| 欧美丰满熟妇BBB久久久| 亚洲国产日韩欧美综合久久| 国产精品一区二区久久| 色欲综合久久躁天天躁蜜桃 | 久久久久久国产精品免费无码| 久久久久久久亚洲精品| 久久精品嫩草影院| 久久九九精品99国产精品| 久久人人添人人爽添人人片牛牛| 久久精品无码一区二区app| 久久久久中文字幕| 国产精品久久永久免费| 国内精品久久久久影院一蜜桃| 色婷婷综合久久久久中文一区二区| 伊人久久大香线蕉精品不卡| 久久精品中文字幕有码| 日日狠狠久久偷偷色综合96蜜桃| 国产激情久久久久影院| 久久久久国产一级毛片高清板| 国产精品久久久久乳精品爆|