Construct a script engine using C language (4) syntax analysis

Source: Internet
Author: User
Construct a script engine using C language (4)

Author: kevin_qing

Please note

As in the previous chapter, the syntax analysis section does not prepare to directly generate code using YACC, but only uses the analysis table generated by YACC.

BNF:

% Token ID if else switch goto return number string main
% Token add_op mul_op assign_op cmp_op logic_op1 logic_op2
% Token lparen rparen lbrace rbrace colon comma semi

%
Prog
: Main lparen rparen cpd_smt
;

Cpd_smt
: Lbrace smt_seq rbrace
;

Smt_seq
: Lb_smt
| Smt_seq lb_smt
;

Lable: Id colon
;

Lb_smt
: SMT
| Lable SMT
;
SMT
: Expr semi
| Semi
| Goto ID semi
| Return semi
| If lparen expr rparen SMT
| If lparen expr rparen SMT else SMT
| Switch lparen expr rparen lbrace cases rbrace
| Cpd_smt
;

Case: Numbers colon SMT
;

Cases: Case
| Cases case
;

Numbers: add_op number
| Number
;

Strings: String
| Strings string
;

Pam_list
: Expr
| Pam_list comma expr
;

Pri_expr
: ID
| Numbers
| Strings
| Lparen expr rparen
;
Post_expr
: Pri_expr
| ID lparen rparen
| ID lparen pam_list rparen
;
 
Mul_expr
: Post_expr
| Mul_expr mul_op post_expr
;

Add_expr
: Mul_expr
| Add_expr add_op mul_expr
;

Cmp_expr
: Add_expr
| Add_expr cmp_op add_expr
;

Logic_expr
: Cmp_expr
| Logic_expr logic_op2 cmp_expr
| Logic_op1 cmp_expr
;

Expr
: Logic_expr
| ID assign_op expr
;

 

%

Use bison ++-o-v bnf.txt to compile and generate O. Output and other files.

I only use the output of O. output.

Part of O. Output

State 69 contains 1 shift/reduce conflict. // There is a conflict about the hanging else. Here, the default state transfer of YACC is correct and no other processing is required.

Grammar

Syntax Rules, // I generate a statute function through this recognition.

---------------
Rule 1 prog-> main lparen rparen cpd_smt
Rule 2 cpd_smt-> lbrace smt_seq rbrace
Rule 3 smt_seq-> lb_smt
--------------

State transfer, the program builds an analysis table by identifying the State transfer line.

The left side is the identifier of the input, and the right side is the action.

------------------------

State 0

Main shift, and go to state 1

Prog go to state 80
-------------------------

There may be four types of actions

Shift, and go to State [N]

Reduce using rule [N]...

Go to State [N]

Accept

Create an analysis table using the status transition table.

Here I wrote a small program to implement automatic generation of analysis tables and statute functions.

Lpcstr lablename [] = {"ID", "if", "else", "Switch", "Goto", "Return", "Number", "string ", "Main ",
"Add_op", "mul_op", "assign_op", "cmp_op", "logic_op1", "logic_op2 ",
"Lparen", "rparen", "lbrace", "rbrace", "colon", "comma", "semi ",

"Prog", "cpd_smt", "smt_seq", "lable", "lb_smt", "SMT", "case", "cases ",
"Numbers", "strings", "pam_list", "pri_expr", "post_expr", "mul_expr", "add_expr", "cmp_expr", "logic_expr", "expr ", "$ end"
};

# Define CNT (sizeof (lablename)/sizeof (lablename [0])
Char * gettoken (char * & P ){
While (* P ){
If (* P = '') | (* P = '/t ')){
++ P;
} Else {
Char * r = P;
While (* P ){
If ('/N' = * P) | ('/t' = * P) | (''= * p )){
* P = 0;
++ P;
Break;
} Else {
++ P;
}
}
Return R;

}

};
Return NULL;
 
}
Bool Sm (lpcstr S, lpcstr d ){
If (S & D ){
Return 0 = strcmp (S, d );
}
Return false;
}

# Define M (x) (Sm (gettoken (P), x ))
Void yy2ini (){
File * fp = fopen ("lalranalysis table .txt", "R ");
File * FPO = fopen ("lalr. ini", "W ");
File * FP1 = fopen ("rfun. c", "W ");
Char TMP [4096];
While (fgets (TMP, 4096, FP )){
Char * P = TMP;
Char * r = gettoken (P );
Int I;
If (Sm (R, "State ")){
R = gettoken (P );
If (r)
{
I = atoi (R );
Fprintf (FPO, "[S % d]/n", I );
}
} Else if (Sm (R, "rule ")){
Char * R1 = gettoken (P );
If (R1 ){
Int n = atoi (R1 );
Char * TMP [1024];
Int I = 0;
R = gettoken (P );
If (r) if (M ("-> ")){
While (TMP [I] = gettoken (p) ++ I;
Fprintf (FP1, "// rule [% d] % s->", N, R );
For (Int J = 0; j <I; ++ J)
Fprintf (FP1, "% s", TMP [J]);
Fprintf (FP1,
"/Nvoid reduce % d () {/N", N );
For (Int J = 0; j <I; ++ J)
Fprintf (FP1,
"Assert (tokenstack [% d]-> tokentype = % s);/N",-J-1, TMP [i-j-1]);
If (I> 1)
Fprintf (FP1,
"Tokenstack. Pop (% d);/N", I-1 );
Fprintf (FP1,
"Tokenstack [-1]-> tokentype = % s;/N"
"Statestack. Pop (% d);/N"
"}/N", R, I );

}

}

} Else {
Char * R1 = gettoken (P );
If (Sm (R1, "shift ,"))
{
If (M ("and") & M ("go") & M ("to") & M ("state ")){
R1 = gettoken (P );
If (R1 ){
I = atoi (R1 );
Fprintf (FPO, "% s = S % d/N", R, I );
}
}
} Else if (Sm (R1, "go ")){
If (M ("to") & M ("state ")){
R1 = gettoken (P );
If (R1 ){
I = atoi (R1 );
Fprintf (FPO, "% s = g % d/N", R, I );
}
}
} Else if (Sm (R1, "reduce") // reduce using rule
{
If (M ("using") & M ("rule ")){
R1 = gettoken (P );
If (R1 ){
I = atoi (R1 );
Fprintf (FPO, "% s = R % d/N", R, I );
}

}
}

}
}
Fclose (FP );
Fclose (FPO );

Fprintf (FP1, "typedef void reduce ();/N"
"Reduce * reduce [] = {/N ");
For (INT I = 1; I <44; ++ I)
Fprintf (FP1, "/T & reduce % d,/N", I );

Fprintf (FP1, "};/N ");
Fclose (FP1 );
}

Main Program (lalr Analysis)

Void main (){
Sccompiler SC;
SC. INIT ();
SC. Open ("test. SC ");
Statestack. Push (0 );
Tokenstack. Push (new token (START, 0 ));
While (1)
Try {
Token * P = SC. gettoken ();

// Printf ("Get % s @ % d/N", lablename [p-> tokentype], p-> line );
Rescan:
If (statestack [st_top] = 80) & P-> tokentype = endofstream)
Break;
Uint32_t r = lalrtab [statestack [st_top] [p-> tokentype & 0 xFFFF];
Switch (R & 0xf0000 ){
Case smask:
Tokenstack. Push (P );
Statestack. Push (R & 0 xFFFF );
Break;
Case rmask :{
Uint32_t id = R;
Do {
ID & = 0 xFFFF;
Reduce [ID-1] ();
Id = lalrtab [statestack [st_top] [tokenstack [st_top]-> tokentype & 0 xFFFF];
} While (ISR (ID ));
If (ISG (ID )){
Statestack. Push (ID & 0 xFFFF );
// Statestack [0] = (ID & 0 xFFFF );
Goto rescan;
} Else
Assert (false );
}
Default:
Assert (false );
}
} Catch (int err) {printf ("EOF % d", err); break ;}

Printf ("Accept/N ");
Printf ("statestack % d/N", statestack [st_top]);

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.