成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

c語言是如何解析表達(dá)式語句"2+3*4;"的?

2501207950 / 1179人閱讀

摘要:語法分析解析字符如果類型為數(shù)字,則解析數(shù)字,不為浮點(diǎn)數(shù),所以執(zhí)行分支。解析函數(shù)會調(diào)用函數(shù)返回代表數(shù)字的類型同樣為的節(jié)點(diǎn),這點(diǎn)同解析數(shù)字的過程,不再贅述。參數(shù)為類型為的代表數(shù)字的節(jié)點(diǎn),會生成將載入寄存器,返回。函數(shù)將彈入寄存器。

1.? 要編譯的測試代碼:

int main(void){    2+3*4;}

?

2. 詞法分析

  詞法分析將字符變成token,其中很重要的是token的類型,如字符2的token類型為TK_NUM,這在后面的語法分析階段有用。

?

3. 語法分析

?

3.1 解析字符"2"

if (tok->kind == TK_NUM) {    Node *node;    if (is_flonum(tok->ty)) {      node = new_node(ND_NUM, tok);      node->fval = tok->fval;    } else {      node = new_num(tok->val, tok);    }    node->ty = tok->ty;    *rest = tok->next;    return node;  }

  如果token類型為數(shù)字,則解析數(shù)字,2不為浮點(diǎn)數(shù),所以執(zhí)行else分支。

static Node *new_num(int64_t val, Token *tok) {  Node *node = new_node(ND_NUM, tok);  node->val = val;  return node;}

  創(chuàng)建一個(gè)類型為ND_NUM的node節(jié)點(diǎn),這個(gè)節(jié)點(diǎn)就代表了數(shù)字2,數(shù)字2存儲在node節(jié)點(diǎn)的val變量中。

?

3.2 解析"+"

static Node *add(Token **rest, Token *tok) {  Node *node = mul(&tok, tok);  for (;;) {    Token *start = tok;    if (equal(tok, "+")) {      node = new_add(node, mul(&tok, tok->next), start);      continue;    }    if (equal(tok, "-")) {      node = new_sub(node, mul(&tok, tok->next), start);      continue;    }    *rest = tok;    return node;  }}

  數(shù)字2的node節(jié)點(diǎn)由mul函數(shù)返回,此時(shí)tok為"+",所以會調(diào)用new_add函數(shù),在這個(gè)函數(shù)中會創(chuàng)建類型為ND_ADD的node節(jié)點(diǎn),

這個(gè)節(jié)點(diǎn)的左表達(dá)式為代表數(shù)字2的node節(jié)點(diǎn),右表達(dá)式為代表乘法運(yùn)算的node節(jié)點(diǎn)。

static Node *new_add(Node *lhs, Node *rhs, Token *tok) {
if
(is_numeric(lhs->ty) && is_numeric(rhs->ty)) return new_binary(ND_ADD, lhs, rhs, tok);
...
}
static Node *new_binary(NodeKind kind, Node *lhs, Node *rhs, Token *tok) {  Node *node = new_node(kind, tok);  node->lhs = lhs;  node->rhs = rhs;  return node;}

?

3.3 解析"*"

static Node *mul(Token **rest, Token *tok) {  Node *node = cast(&tok, tok);  for (;;) {    Token *start = tok;    if (equal(tok, "*")) {      node = new_binary(ND_MUL, node, cast(&tok, tok->next), start);      continue;    }    if (equal(tok, "/")) {      node = new_binary(ND_DIV, node, cast(&tok, tok->next), start);      continue;    }    if (equal(tok, "%")) {      node = new_binary(ND_MOD, node, cast(&tok, tok->next), start);      continue;    }    *rest = tok;    return node;:  }}

  mul函數(shù)會調(diào)用cast函數(shù)返回代表數(shù)字3的類型同樣為ND_NUM的node節(jié)點(diǎn),這點(diǎn)同解析數(shù)字2的過程,不再贅述。

  由于tok此時(shí)為"*",所以會創(chuàng)建類型為ND_MUL的乘法node節(jié)點(diǎn),這個(gè)節(jié)點(diǎn)的左表達(dá)式為代表數(shù)字3的類型為

ND_NUM的node節(jié)點(diǎn),右表達(dá)式為cast函數(shù)返回的代表數(shù)字4的類型為ND_NUM的node節(jié)點(diǎn)。

?

4. 解析上一步生成的語法樹生成匯編代碼

static void gen_expr(Node *node) {    switch (node->kind) {    case ND_NUM: {        println("  mov $%ld, %%rax", node->val);        return;    ...    }    gen_expr(node->rhs);    push();    gen_expr(node->lhs);    pop("%rdi");    switch (node->kind) {    case ND_ADD:        println("  add %s, %s", di, ax);        return;    case ND_MUL:        println("  imul %s, %s", di, ax);        return;    ...    }...}
  4.1 gen_expr的參數(shù)為類型為ND_ADD的node節(jié)點(diǎn),首先遞歸調(diào)用gen_expr,傳入的參數(shù)為類型為ND_MUL的node節(jié)點(diǎn),又會遞歸調(diào)用
gen_expr,傳入的參數(shù)為類型為ND_NUM的代表數(shù)字4的node節(jié)點(diǎn),此時(shí)會生成匯編語句"mov  rax, 4",將4載入rax寄存器,gen_expr返回。

  4.2 push函數(shù)生成"push? ? rax",將4壓入棧。

  4.3 gen_expr的參數(shù)為類型為ND_NUM的代表數(shù)字3的node節(jié)點(diǎn),會生成"mov? ? ?rax, 3",將3載入rax寄存器,gen_expr返回。

  4.4 pop("%rdi")函數(shù)將4彈入rdi寄存器。

  4.5 由于node節(jié)點(diǎn)類型為ND_MUL,所以生成"imul? ? eax, edi",計(jì)算3*4,結(jié)果保存在eax寄存器中,并從gen_expr返回。

  4.6 回到參數(shù)為ND_ADD的gen_expr函數(shù)中。

  4.7 push函數(shù)生成"push? ? rax",將3*4壓入棧。

  4.8 gen_expr參數(shù)為類型為ND_NUM的代表數(shù)字2的node節(jié)點(diǎn),會生成"mov? ? ?rax, 2",將2載入rax寄存器,gen_expr返回。

  4.9 pop("%rdi");函數(shù)將3*4彈入rdi寄存器。

  4.10 由于node節(jié)點(diǎn)類型為ND_ADD,所以生成"add? ? ?eax, edi",計(jì)算2+3*4,結(jié)果保存在eax寄存器中,并從gen_expr返回。
  
?
?
?
?
?
?

?

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/124823.html

相關(guān)文章

  • Vue編譯器AST抽象語法樹源碼分析

     直接進(jìn)入核心現(xiàn)在說說baseCompile核心代碼:  //`createCompilerCreator`allowscreatingcompilersthatusealternative   //parser/optimizer/codegen,e.gtheSSRoptimizingcompiler.   //Herewejustexportadefaultcompilerusingthede...

    3403771864 評論0 收藏0
  • 解析ES6變量賦值和基本數(shù)據(jù)類型

      let和const  let和const兩者并不存在變量提升  這里要說明的是變量一定要在聲明后使用,否則報(bào)錯(cuò)?! ara=[];   for(vari=0;i<10;i++){   a[i]=function(){   console.log(i);   };   }   a[6]();//10  變量i是var聲明的,我們要知道這里在全局范圍內(nèi)都有效。我們要知道在每一次循環(huán)中,新的...

    3403771864 評論0 收藏0
  • vue parseHTML函數(shù)源碼解析start鉤子函數(shù)

      關(guān)于parseHTML 函數(shù)源碼解析 AST 相關(guān)知識已做過介紹,下面可以看看Vue start鉤子函數(shù)源碼。  start:functionstart(tag,attrs,unary){   //checknamespace.   //inheritparentnsifthereisone   varns=(currentParent&&currentParent.ns)||...

    3403771864 評論0 收藏0
  • python自動化具體代碼解析

      小編寫這篇文章的主要目的,主要是給大家解讀關(guān)于python接口自動化的一些詳細(xì)代碼實(shí)例,具體是什么呢?下面就給各位讀者詳細(xì)的解答下。  前言  我們做接口自動化的過程中,解決端口依賴的相關(guān)數(shù)據(jù)時(shí),一般會采用正則匹配去進(jìn)行獲取有關(guān)的信息。  正則匹配,又被稱為正規(guī)表示式、正規(guī)表示法、正規(guī)表達(dá)式、規(guī)則表達(dá)式、常規(guī)表示法(RegularExpression,在編碼中常縮寫為regex、regexp或...

    89542767 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<