欧美vvv,亚洲第一成人在线,亚洲成人欧美日韩在线观看,日本猛少妇猛色XXXXX猛叫

新聞資訊

    【導讀】本文介紹了語法解析基本概念,結合 實戰做了詳細介紹。

    一、Lex & Yacc簡介

    Lex & Yacc 是用來生成詞法分析器和語法分析器的工具,與GNU用戶所熟知Flex&Bison所對應(Flex是由Vern Paxon實現的一個Lex詞法分析器的輸出結果,Bison則是GNU版本的YACC)。除了編譯器領域,Lex & Yacc對于DSL或者SQL解析領域也大有用處。

    Lex (A )用于生成詞法分析器,用于把輸入分割成一個個有意義的詞塊(稱為token)。

    Yacc(Yet -)用于生成語法解析器,用于確定上述分隔好的token之間的關聯。

    下圖描述了整個處理的流程:

    二、詞法分析器

    詞法分析器用于獲取一個token流。通過調用yylex()讀取輸入,然后返回相應的token,之后循環調用,持續返回解析好的token。每個token有兩部分組成:

    聚類分析最短距離法結果分析_oracle游標將查詢結果輸出_詞法分析器的輸出結果

    如下是計算器詞法分析器的規則定義。該定義由三部分組成,由%%分隔。

    //?計算器詞法分析器
    %{
    ????enum?yytokentype?{
    ????????NUMBER?=?258,
    ????????ADD?=?259,
    ????????SUB?=?260,
    ????????MUL?=?261,
    ????????DIV?=?262,
    ????????ABS?=?263,
    ????????EOL?=?264
    ????};
    ????int?yylval;
    %}

    %%?
    "+"????????{return?ADD;}
    "-"????????{return?SUB;}
    "*"????????{return?MUL;}
    "/"????????{return?DIV;}
    "|"????????{return?ABS;}
    [0-9]+?????{yylval?=?atoi(yytext);?return?NUMBER;}
    \n?????????{return?EOL;}
    [?\t]??????{/*忽略空白字符*/}
    %%

    main(int?argc,?char?**argv)?{
    ????int?tok;

    ??while(tok?=?yylex())?{
    ????printf("%d",?tok);
    ????if?(tok?==?NUMBER)?{
    ??????printf("?=?%d\n",?yylval);
    ????}?else?{
    ??????print("\n");
    ????}
    ??}
    }

    //?運行
    ///?輸入:
    34?+?45

    ///?輸出:
    258?=?34
    259
    258?=?45

    三、語法分析器

    語法分析器用于找出輸入token之間的關系,使用巴科斯范式(BNF, Naur Form)來書寫。同詞法分析器規則一樣,也是三部分組成。

    樣例:

    %{
    #include
    %}

    /*declare tokens*/
    %token NUMBER
    %token ADD SUB MUL DIV ABS
    %token EOL

    %%
    calclist: /*空規則*/
    | calclist exp EOL { printf("= %d\n", $2); }
    ;

    exp: factor defalut $$ = $1
    | exp ADD factor { $$ = $1 + $3; }
    | exp SUB factor { $$ = $1 - $3; }
    ;

    factor: term default $$ = $1
    | factor MUL term { $$ = $1 * $3; }
    | factor DIV term { $$ = $1 / $3; }
    ;

    term: NUMBER default $$ = $1
    | ABS term { $$ = $2 >=0 ? $2 : - $2; }
    ;

    %%
    main(int argc, char **argv) {
    yyparse();
    }

    yyerror(char *s) {
    fprintf(stderr, "error: %s\n", s);
    }

    四、yacc語法規范整體結構

    oracle游標將查詢結果輸出_詞法分析器的輸出結果_聚類分析最短距離法結果分析

    由三部分組成,其中前兩部分必須。

    ...定義部分...

    %%

    ...規則部分...

    %%

    ...用戶子程序...

    符號

    由詞法分析器產生的符號稱為終結符或者token。

    在規則左側定義的的符號稱為非終結符。

    定義部分規則部分

    包括語法規則和語義動作代碼。動作即yacc匹配語法中的一條規則時之行的代碼。例如:

    聚類分析最短距離法結果分析_oracle游標將查詢結果輸出_詞法分析器的輸出結果

    date: month '/' day '/' year { $$ = ("date %d-%d-%d", $1, $3, $5); }

    用戶子程序

    原樣被拷貝到C文件的代碼片段。

    移進/歸約

    移進(shift):語法分析器讀取token時,當讀取的token無法匹配一條規則時,則將其壓入一個內部堆棧(union為壓入堆棧的結構體),然后切換到一個新的狀態,這個新的狀態能夠反映出剛剛讀取的token。

    歸約():當發現壓入的token已經能夠匹配規則時,則把匹配的符號從堆棧中取出,然后將左側符號壓入堆棧。

    例如,fred = 12 + 13的處理過程:

    聚類分析最短距離法結果分析_oracle游標將查詢結果輸出_詞法分析器的輸出結果

    // 規則
    statement: NAME '=' expression
    expression: NUMBER + NUMBER

    // 處理過程
    fred
    fred =
    fred = 12
    fred = 12 +
    fred = 12 + 13 //匹配expression: NUMBER + NUMBER,可以歸約
    fred = expression //匹配statement: NAME '=' expression
    statement

    但是如果引入乘法后,可能會產生沖突,造成如下不同的語法結構。

    對于這種情況需要顯示指定優先級和結合性來解決沖突:

    // 意義:+ - * /都是左結合,* /的優先級高于+ -。
    %left '+' '-'
    %left '*' '/'

    五、

    /cznic/是 版的 Yacc。和 Yacc 的功能一樣, 根據輸入的語法規則文件,生成該語法規則的 go 語言版解析器。 生成的解析器 要求詞法分析器符合下面的接口:

    聚類分析最短距離法結果分析_oracle游標將查詢結果輸出_詞法分析器的輸出結果

    type yyLexer interface {
    Lex(lval *yySymType) int
    Error(e string)
    }

    或者

    type yyLexerEx interface {
    yyLexer
    // Hook for recording a reduction.
    Reduced(rule, state int, lval *yySymType) (stop bool) // Client should copy *lval.
    }

    Lex應該返回token類型詞法分析器的輸出結果,并將token值放到放在lval中(與yacc的對應)。Error相當于原yacc中的。

    六、樣例電話號碼解析

    源代碼:///tree//v3

    # 定義部分
    %{
    package jsonparser

    func setResult(l yyLexer, v Result) {
    l.(*lex).result = v
    }
    %}

    %union{
    result Result
    part string
    ch byte
    }

    %token D

    %type phone
    %type area part1 part2

    %start main

    %%
    # 規則部分
    main: phone
    {
    setResult(yylex, $1)
    }

    phone:
    area part1 part2
    {
    $$ = Result{area: $1, part1: $2, part2: $3}
    }
    | area '-' part1 '-' part2
    {
    $$ = Result{area: $1, part1: $3, part2: $5}
    }

    area: D D D
    {
    $$ = cat($1, $2, $3)
    }

    part1: D D D
    {
    $$ = cat($1, $2, $3)
    }

    part2: D D D D
    {
    $$ = cat($1, $2, $3, $4)
    }

    //?對應.y中union的結構體
    type?yySymType?struct?{
    ????yys????int
    ????result?Result
    ????part???string
    ????ch?????byte
    }
    //token類型
    const?(
    ????yyDefault?=?57347
    ????yyEofCode?=?57344
    ????D?????????=?57346
    ????yyErrCode?=?57345

    ????yyMaxDepth?=?200
    ????yyTabOfs???=?-7
    )

    //詞法分析器接口
    type?yyLexer?interface?{
    ????Lex(lval?*yySymType)?int
    ????Error(s?string)
    }

    type?yyLexerEx?interface?{
    ????yyLexer
    ????Reduced(rule,?state?int,?lval?*yySymType)?bool
    }

    //語法解析入口
    func?yyParse(yylex?yyLexer)?int?{

    }

    //?Result?is?the?type?of?the?parser?result
    type?Result?struct?{
    ????area??string
    ????part1?string
    ????part2?string
    }

    //?解析的總入口。輸入電話號碼,輸出為Result的解析結果。
    func?Parse(input?[]byte)?(Result,?error)?{
    ????l?:=?newLex(input)
    ????_?=?yyParse(l)
    ????return?l.result,?l.err
    }

    //?手動定義詞法解析器
    type?lex?struct?{
    ????input??*bytes.Buffer
    ????result?Result
    ????err????error
    }

    func?newLex(input?[]byte)?*lex?{
    ????return?&lex{
    ????????input:?bytes.NewBuffer(input),
    ????}
    }

    //?詞法分析器滿足Lex接口。能夠逐個讀取token。
    //?如果是有效的電話號碼數字,返回D類型,并賦值lval.ch。
    func?(l?*lex)?Lex(lval?*yySymType)?int?{
    ????b?:=?l.nextb()
    ????if?unicode.IsDigit(rune(b))?{
    ????????lval.ch?=?b
    ????????return?D
    ????}
    ????return?int(b)
    }

    func?(l?*lex)?nextb()?byte?{
    ????b,?err?:=?l.input.ReadByte()
    ????if?err?!=?nil?{
    ????????return?0
    ????}
    ????return?b
    }

    //?Error?satisfies?yyLexer.
    func?(l?*lex)?Error(s?string)?{
    ????l.err?=?errors.New(s)
    }

    func?cat(bytes?...byte)?string?{
    ????var?out?string
    ????for?_,?b?:=?range?bytes?{
    ????????out?+=?string(b)
    ????}
    ????return?out
    }

網站首頁   |    關于我們   |    公司新聞   |    產品方案   |    用戶案例   |    售后服務   |    合作伙伴   |    人才招聘   |   

友情鏈接: 餐飲加盟

地址:北京市海淀區    電話:010-     郵箱:@126.com

備案號:冀ICP備2024067069號-3 北京科技有限公司版權所有