A topdown parsing algorithm parses an input string

  • Slides: 26
Download presentation

하향식 파싱 A top-down parsing algorithm parses an input string of tokens by tracing

하향식 파싱 A top-down parsing algorithm parses an input string of tokens by tracing out the steps in a leftmost derivation. Such an algorithm is called top-down because the implied traversal of the parse tree is a preorder traversal. 3

예제: 재귀적 순환 파싱 Grammar rule: factor ( exp ) | number Code: void

예제: 재귀적 순환 파싱 Grammar rule: factor ( exp ) | number Code: void factor(void) { if (token == number) match(number); else { match(‘(‘); void match(expected. Token) exp(); { if (token == expeced. Token) match(‘)’); get. Token(); } else } error; } 7

예제: 재귀적 순환 파싱 • 재귀적 순환 파서는 값을 계산하거나 구문 트 리를 구성할

예제: 재귀적 순환 파싱 • 재귀적 순환 파서는 값을 계산하거나 구문 트 리를 구성할 수 있다. factor ( exp ) | number int factor(void) { if (token == number) { int temp = atoi(tok. Str); match(number); return temp; } else { match(‘(‘); int temp = exp(); match(‘)’); return temp; } } 8

좌순환 규칙 존재는? exp addop term | term void exp(void) { if (token ==

좌순환 규칙 존재는? exp addop term | term void exp(void) { if (token == ? ? ) { exp(); addop(); term(); } else term(); } 코드의 문 제점은? 9

EBNF가 해결책 exp term { addop term } void exp(void) { term(); while (token

EBNF가 해결책 exp term { addop term } void exp(void) { term(); while (token is an addop) { addop(); term(); } } 10

우순환 규칙 존재는? exp term [ addop exp ] void exp(void) { term(); if

우순환 규칙 존재는? exp term [ addop exp ] void exp(void) { term(); if (token is an addop) { addop(); exp(); } } No problem!! 11

exp addop term | term addop + | term multop factor | factor multop

exp addop term | term addop + | term multop factor | factor multop * factor ( exp ) | number Example int exp () // compute values { var temp : integer; temp : = term(); while (token = ‘+’ or token = ‘-’ ) do case token of ‘+’ : match(+); temp : = temp + term(); ‘-’ : match(-); temp : = temp – term(); end case; } return temp; } 연산의 좌결 합 규칙이 유 지되는가? 13

Simple integer arithmetic calculator (1) /* EBNF: <exp> -> <term> {<addop><term>} int exp(void) <addop>

Simple integer arithmetic calculator (1) /* EBNF: <exp> -> <term> {<addop><term>} int exp(void) <addop> -> + | <term> -><factor> {<mulop> <factor>} { int tmp = term(); while((token == ‘+’) || (token== ‘-’)) <mulop> -> * switch (token) { <factor> -> (<exp)> | number case ‘+’: match(‘+’); */ temp += term(); break; main() case ‘-’: match(‘+’); { int result; temp -= term(); break; token = get. Token(); } result = exp(); return temp; if (token == ‘n’) } printf(“Result = %dn”, result); else error(); return 0; } 14

Simple integer arithmetic calculator (2) /* EBNF: <exp> -> <term> {<addop><term> <addop> -> +

Simple integer arithmetic calculator (2) /* EBNF: <exp> -> <term> {<addop><term> <addop> -> + | <term> <factor> {<mulop> <factor>} <mulop> -> * <factor> -> (<exp)> | Number */ int factor(void) { int temp if (token == ‘(‘) { match(‘(‘); temp = exp(); match(‘)’); } else if (isdigit(token)) { ungetc(token, stdin)); scanf(“%d”, &temp); token = getchar(); } else error(); return temp; int term(void) { int tmp = factor(); while(token == ‘*’) { match(‘*’); temp *= factor(); } return temp; } } 15

Example • 수식에 대한 구문 트리를 어떻게 구성할 것인가? exp addop term | term

Example • 수식에 대한 구문 트리를 어떻게 구성할 것인가? exp addop term | term addop + | term multop factor | factor multop * factor ( exp ) | number + 3+4+5 5 + 3 4 16

Example: 수식 구문트리 syntax. Tree exp () // construct syntax tree { var temp,

Example: 수식 구문트리 syntax. Tree exp () // construct syntax tree { var temp, newtemp: syntax. Tree; temp : = term(); while (token = + or token = - ) do newtemp : = make. Op. Node(token); match(token); left. Child(newtemp) : = temp; right. Child(newtemp) : = term(); temp : = newtemp; } return temp; } exp addop term | term addop + | term multop factor | factor multop * factor ( exp ) | number typedef enum {Plus, Minus, Times} Op. Kind; typedef enum {Op. K, Const. K} Exp. Kind; typedef struct streenode { Exp. Kind kind; Op. Kind op; struct streenode *lchild, *rchild; int val; } STree. Node; typedef STree. Node *Syntax. Tree; + 5 + 3 3+4+5 4 17

TINY Grammar: EBNF로 변환하 면? program stmt-sequence ; statement | statement if-stmt | repeat-stmt

TINY Grammar: EBNF로 변환하 면? program stmt-sequence ; statement | statement if-stmt | repeat-stmt | assign-stmt | read-stmt | write-stmt if-stmt if exp then stmt-sequence end | if exp then stmt-sequence else stmt-sequence end repeat-stmt repeat stmt-sequence until exp assign-stmt identifier : = exp read-stmt read identifier write-stmt write exp simple-exp comparison-op simple-exp | simple-exp comparison-op < | = simple-exp addop term | term addop + | term mulop factor | factor mulop * | / factor ( exp ) | number | identifier 20

TINY 문법의 EBNF 버전 program stmt-sequence statement { ; statement } statement if-stmt |

TINY 문법의 EBNF 버전 program stmt-sequence statement { ; statement } statement if-stmt | repeat-stmt | assign-stmt | read-stmt | write-stmt if-stmt if exp then stmt-sequence [ else stmt-sequence ] end repeat-stmt repeat stmt-sequence until exp program stmt-sequence ; statement | assign-stmt identifier : = exp statement if-stmt | repeat-stmt | assignread-stmt read identifier stmt | read-stmt | write-stmt write exp if-stmt if exp then stmt-sequence end exp simple-exp [ comparison-op simple-exp ] comparison-op < | = simple-exp term { addop term } addop + | term factor { mulop factor } mulop * | / factor ( exp ) | number | identifier | if exp then stmt-sequence else stmt-sequence end repeat-stmt repeat stmt-sequence until exp assign-stmt identifier : = exp read-stmt read identifier write-stmt write exp simple-exp comparison-op simple-exp | simple-exp comparison-op < | = simple-exp addop term | term addop + | 21 term mulop factor | factor mulop * | /

Recall: TINY 구문 트리 구조 typedef enum {Stmt. K, Exp. K} Node. Kind; typedef

Recall: TINY 구문 트리 구조 typedef enum {Stmt. K, Exp. K} Node. Kind; typedef enum {If. K, Repeat. K, Assign. K, Read. K, Write. K} Stmt. Kind; typedef enum {Op. K, Const. K, Id. K} Exp. Kind; /* Exp. Type is used for type checking */ typedef enum {Void, Integer, Boolean} Exp. Type; #define MAXCHILDREN 3 typedef struct tree. Node { struct tree. Node * child[MAXCHILDREN]; struct tree. Node * sibling; int lineno; Node. Kind nodekind; union {Stmt. Kind stmt; Exp. Kind exp; } kind; union {Token. Type op; int val; char * name; } attr; Exp. Type type; /* for type checking of exps */ } Tree. Node; 23

Recall: sample. tny read x; if 0 < x then fact : = 1;

Recall: sample. tny read x; if 0 < x then fact : = 1; repeat fact : = fact * x; x : = x – 1; until x = 0; write fact end 24

TINY 파서의 재귀적 순환 파서 코드 (구문 트리 생성) statement if-stmt | repeat-stmt |

TINY 파서의 재귀적 순환 파서 코드 (구문 트리 생성) statement if-stmt | repeat-stmt | assign-stmt | read-stmt | write-stmt Tree. Node * statement(void) { Tree. Node * t = NULL; switch (token) { case IF : t = if_stmt(); break; case REPEAT : t = repeat_stmt(); break; case ID : t = assign_stmt(); break; case READ : t = read_stmt(); break; case WRITE : t = write_stmt(); break; default : syntax. Error("unexpected token -> "); print. Token(token, token. String); token = get. Token(); statement if-stmt | repeat-stmt | assign-stmt | read-stmt | write-stmt break; if-stmt if exp then stmt-sequence end } /* end case */ | if exp then stmt-sequence else stmt-sequence end return t; repeat-stmt repeat stmt-sequence until } exp assign-stmt identifier : = exp read-stmt read identifier write-stmt write exp 25

TINY 파서의 재귀적 순환 파서 코드 (2) if-stmt if exp then stmt-sequence [ else

TINY 파서의 재귀적 순환 파서 코드 (2) if-stmt if exp then stmt-sequence [ else stmt-sequence ] end Tree. Node * if_stmt(void) { Tree. Node * t = new. Stmt. Node(If. K); match(IF); if (t!=NULL) t->child[0] = exp(); match(THEN); if (t!=NULL) t->child[1] = stmt_sequence(); if (token==ELSE) { match(ELSE); if (t!=NULL) t->child[2] = stmt_sequence(); } statement if-stmt | repeat-stmt | assign-stmt match(END); | read-stmt | write-stmt return t; if-stmt if exp then stmt-sequence end } | if exp then stmt-sequence else stmt-sequence end repeat-stmt repeat stmt-sequence until exp assign-stmt identifier : = exp 26 read-stmt read identifier write-stmt write exp