言語処理系構成論(3 構文解析(syntax...

9
2012/04/23 言語処理系構成論(3岡山大学大学院自然科学研究科 渡邊 誠也 1 2012/04/23 構文解析(syntax analysis2 2012/04/23 #3 Copyright (C) Nobuya WATANABE コンパイラの構成(論理的構成) ! フロントエンド(解析部) ! 字句解析 ! 構文解析 ! 意味解析 ! 中間コード生成 ! バックエンド(合成部) ! 最適化 ! コード生成 3 lexical analysis syntax analysis semantic analysis optimization target code generation intermediate code generation source program object program frontend backend tables, etc. (name, symbol, string, ...) 2012/04/23 #3 Copyright (C) Nobuya WATANABE コンパイラの構成(論理的構成) ! フロントエンド(解析部) ! 字句解析 ! 構文解析 ! 意味解析 ! 中間コード生成 ! バックエンド(合成部) ! 最適化 ! コード生成 3 lexical analysis syntax analysis semantic analysis optimization target code generation intermediate code generation source program object program frontend backend tables, etc. (name, symbol, string, ...) 2012/04/23 #3 Copyright (C) Nobuya WATANABE 構文解析(syntax analysis, parsing! 字句解析が出力したトークンを 読み込みながら,そのトークンの 列がプログラミング言語の文法で 許されているパターンと一致する かを解析 ! 許されているパターンであれば, トークンの列は構文規則にしたがっ て構成され,字句を葉とする解析木 を生成 ! 解析結果は,構文木と呼ばれる木構 造として出力 4 lexical analysis source program syntax analysis request a token return a token syntax tree 2012/04/23 #3 Copyright (C) Nobuya WATANABE 構文,制約,意味 ! プログラミング言語は次の3つによって定義 ! プログラムの構成要素の構造を規定する構文(syntax! 構文的に正しいプログラムを実行するために要求される さまざまな制約(constraint ! プログラムの構成要素がどのように実行されるかを 定義する意味(semantics5 (例)C言語の if 【構文】if (expr) stat1 else stat2 【制約】 expr は真偽値を表す型(算術式またはポインタ型)でなければならない 【意味】まず expr を計算し,その値が真(0以外の値)であれば stat1 を実行.偽 であれば stat2 を実行.

Transcript of 言語処理系構成論(3 構文解析(syntax...

Page 1: 言語処理系構成論(3 構文解析(syntax analysisnobuya/lecture/plpc/PLPC2012-03_handout.pdf · プログラミング言語の形式的な記述!プログラミング言語の文法の記述方法!バッカス記法

2012/04/23

言語処理系構成論(3)

岡山大学大学院自然科学研究科渡邊 誠也

1 2012/04/23

構文解析(syntax analysis)

2

2012/04/23

�#3

����������� Copyright (C) Nobuya WATANABE

コンパイラの構成(論理的構成)! フロントエンド(解析部)

! 字句解析 ! 構文解析! 意味解析! 中間コード生成

! バックエンド(合成部)! 最適化! コード生成

3

lexical

analysis

syntax

analysis

semantic

analysis

optimization

target code

generation

intermediate

code generation

source

program

object

program

frontend

backend

tables, etc.

(name,

symbol,

string, ...)

2012/04/23

�#3

����������� Copyright (C) Nobuya WATANABE

コンパイラの構成(論理的構成)! フロントエンド(解析部)

! 字句解析 ! 構文解析! 意味解析! 中間コード生成

! バックエンド(合成部)! 最適化! コード生成

3

lexical

analysis

syntax

analysis

semantic

analysis

optimization

target code

generation

intermediate

code generation

source

program

object

program

frontend

backend

tables, etc.

(name,

symbol,

string, ...)

2012/04/23

�#3

����������� Copyright (C) Nobuya WATANABE

構文解析(syntax analysis, parsing)! 字句解析が出力したトークンを読み込みながら,そのトークンの列がプログラミング言語の文法で許されているパターンと一致するかを解析! 許されているパターンであれば,トークンの列は構文規則にしたがって構成され,字句を葉とする解析木を生成

! 解析結果は,構文木と呼ばれる木構造として出力

4

lexical

analysis

source

program

syntax

analysis

request a token return a token

syntax tree

2012/04/23

�#3

����������� Copyright (C) Nobuya WATANABE

構文,制約,意味

! プログラミング言語は次の3つによって定義! プログラムの構成要素の構造を規定する構文(syntax)! 構文的に正しいプログラムを実行するために要求されるさまざまな制約(constraint)

! プログラムの構成要素がどのように実行されるかを定義する意味(semantics)

5

(例)C言語の if 文【構文】if (expr) stat1 else stat2

【制約】 expr は真偽値を表す型(算術式またはポインタ型)でなければならない【意味】まず expr を計算し,その値が真(0以外の値)であれば stat1 を実行.偽

であれば stat2 を実行.

Page 2: 言語処理系構成論(3 構文解析(syntax analysisnobuya/lecture/plpc/PLPC2012-03_handout.pdf · プログラミング言語の形式的な記述!プログラミング言語の文法の記述方法!バッカス記法

2012/04/23

�#3

����������� Copyright (C) Nobuya WATANABE

構文,制約,意味

! プログラミング言語は次の3つによって定義! プログラムの構成要素の構造を規定する構文(syntax)! 構文的に正しいプログラムを実行するために要求されるさまざまな制約(constraint)

! プログラムの構成要素がどのように実行されるかを定義する意味(semantics)

! 構文と制約によって定義されるプログラミング言語全体の規定を文法(grammar)と呼ぶことが多い! 与えられたプログラムを実行するのに最低限必要な規定

! 構文解析について議論する際には,制約については言及しないのが普通,制約ぬきの文法(構文のみ)を単に「文法」と呼ぶことがある

6 2012/04/23

�#3

����������� Copyright (C) Nobuya WATANABE

内容! 構文解析を学習するのに必要な基礎知識

! プログラミング言語の形式的な記述! BNF, 拡張BNF

! 文法の基本的な概念や記法! 解析木とあいまい性! 演算子の優先順位と結合性! 文脈自由文法

! 構文解析法! 再帰的下向き構文解析! LR構文解析法(上向き構文解析法)

7

2012/04/23

�#3

����������� Copyright (C) Nobuya WATANABE

プログラミング言語の形式的な記述! プログラミング言語の文法の記述方法

! バッカス記法 BNF (Backus Naur Form, Backus Normal Form)! ALGOL60の文法記述のために開発された記法

! J. Backus, P. Naur: 正規言語を使って任意言語の構文を記述する方法(1959)

! 記述例〈program〉::= program〈identifier〉(〈identifier-list〉); 〈block〉.      | program〈identifier〉;〈block〉.〈identifier-list〉::= 〈identifier〉| 〈identifier-list〉, 〈identifier〉

! 拡張BNF(Extended BNF)! 記述例

〈identifier-list〉::=  {〈identifier〉, } 〈identifier〉

8

メタ記号(meta-symbol)

2012/04/23

�#3

����������� Copyright (C) Nobuya WATANABE

プログラミング言語の形式的な記述! プログラミング言語の文法の記述方法

! バッカス記法 BNF (Backus Naur Form, Backus Normal Form)! ALGOL60の文法記述のために開発された記法

! J. Backus, P. Naur: 正規言語を使って任意言語の構文を記述する方法(1959)

! 記述例〈program〉::= program〈identifier〉(〈identifier-list〉); 〈block〉.      | program〈identifier〉;〈block〉.〈identifier-list〉::= 〈identifier〉| 〈identifier-list〉, 〈identifier〉

! 拡張BNF(Extended BNF)! 記述例

〈identifier-list〉::=  {〈identifier〉, } 〈identifier〉

8

終端記号(terminal symbol)

2012/04/23

�#3

����������� Copyright (C) Nobuya WATANABE

プログラミング言語の形式的な記述! プログラミング言語の文法の記述方法

! バッカス記法 BNF (Backus Naur Form, Backus Normal Form)! ALGOL60の文法記述のために開発された記法

! J. Backus, P. Naur: 正規言語を使って任意言語の構文を記述する方法(1959)

! 記述例〈program〉::= program〈identifier〉(〈identifier-list〉); 〈block〉.      | program〈identifier〉;〈block〉.〈identifier-list〉::= 〈identifier〉| 〈identifier-list〉, 〈identifier〉

! 拡張BNF(Extended BNF)! 記述例

〈identifier-list〉::=  {〈identifier〉, } 〈identifier〉

8

非終端記号(nonterminal symbol)

2012/04/23

�#3

����������� Copyright (C) Nobuya WATANABE

プログラミング言語の形式的な記述! プログラミング言語の文法の記述方法

! バッカス記法 BNF (Backus Naur Form, Backus Normal Form)! ALGOL60の文法記述のために開発された記法

! J. Backus, P. Naur: 正規言語を使って任意言語の構文を記述する方法(1959)

! 記述例〈program〉::= program〈identifier〉(〈identifier-list〉); 〈block〉.      | program〈identifier〉;〈block〉.〈identifier-list〉::= 〈identifier〉| 〈identifier-list〉, 〈identifier〉

! 拡張BNF(Extended BNF)! 記述例

〈identifier-list〉::=  {〈identifier〉, } 〈identifier〉

8

0回以上の繰り返し

Page 3: 言語処理系構成論(3 構文解析(syntax analysisnobuya/lecture/plpc/PLPC2012-03_handout.pdf · プログラミング言語の形式的な記述!プログラミング言語の文法の記述方法!バッカス記法

2012/04/23

�#3

����������� Copyright (C) Nobuya WATANABE

文法表記の例! ANSI C

! 識別子の並びidentifier-list: identifier identifier-list , identifier

! for文for ( expropt ; expropt ; expropt ) stat

! Java Language Specification

! Scheme

9 2012/04/23

�#3

����������� Copyright (C) Nobuya WATANABE

! 生成規則

! ε 規則

! 文法! 生成規則の集合! 出発記号

! 語彙(vocabulary)! 非終端記号! 終端記号

文法

10

A� �

A� �

PS

G = �P, S⇥

VN

VT

V = VN � VT

VN ⇥ VT = �

S � VN

記号列(空でもよい)

文法とは,生成規則の集合Pと,出発記号と呼ばれる記号Sとの組〈P, S〉

2012/04/23

�#3

����������� Copyright (C) Nobuya WATANABE

文法の例

11

P1 = {

}

E � T

T � FF � ( E )

T � T * F

E � E + T

F � i

VN = {E, T, F}

VT = {+, *, (, ), i}

V = VN � VT = {E, T, F, +, *, (, ), i}

! 文法! 生成規則集合

! 非終端記号

! 終端記号

! 語彙

左辺が同一の生成規則をまとめて,次のように表記することもあるP1 = {

}F � ( E )T � T * FE � E + T | T

| F| i

G1 = �P1, E⇥

四つ組で表記することもあるG = �VN , VT , P, S⇥

2012/04/23

�#3

����������� Copyright (C) Nobuya WATANABE

生成(produce)/ 還元(reduce)! 直接生成(directly produce)直接還元(directly reduce)

! 文法 に対して,記号列 と がそれぞれ , と書け,生成規則 が に含まれるとき,   と表記し, は  を直接生成するという 

! は に直接還元されるという! 生成と還元

! 記号列 と に対して, となる記号列 が存在するとき, と表記

! または のとき,   と表記し, は  を生成するという.また, は  に還元されるという

12

G = �VN , VT , P, S⇥ v wv = xAy w = x�y A� � P

v � w v w(u, w, x, y � (VN ⇥ VT )�)

w v

v w v ⇥ u1 ⇥ u2 · · ·⇥ un ⇥ wu1, u2, . . . , un(n � 1) v

+� w

v+� w v = w v

�� w v ww v

v に現れるいずれかの非終端記号Aを,Aを左辺とする生成規則A→αの右辺αで置き換えると,wが得られることを意味する

2012/04/23

�#3

����������� Copyright (C) Nobuya WATANABE

生成(produce)/ 還元(reduce)! 直接生成(directly produce)直接還元(directly reduce)

! 文法 に対して,記号列 と がそれぞれ , と書け,生成規則 が に含まれるとき,   と表記し, は  を直接生成するという 

! は に直接還元されるという! 生成と還元

! 記号列 と に対して, となる記号列 が存在するとき, と表記

! または のとき,   と表記し, は  を生成するという.また, は  に還元されるという

12

G = �VN , VT , P, S⇥ v wv = xAy w = x�y A� � P

v � w v w(u, w, x, y � (VN ⇥ VT )�)

w v

v w v ⇥ u1 ⇥ u2 · · ·⇥ un ⇥ wu1, u2, . . . , un(n � 1) v

+� w

v+� w v = w v

�� w v ww v

v に生成規則を1回以上適用すると,w が得られることを意味する

2012/04/23

�#3

����������� Copyright (C) Nobuya WATANABE

文形式,文,言語! 文形式(sentential form)

! 文法G= �P, S��に対して,   のとき,x は G の文形式という

! 文(sentence)! x が終端記号だけからなるとき,x は G の文という

! 言語(language)! G の文全体の集合をL(G)と表記し,Gの定義する言語という

13

S�� x

E � E+T � T+T � T+T*F � F+T*F� F+T*i� F+F*i� F+i*i� i+i*i

G1の文形式【例】文法G1

Page 4: 言語処理系構成論(3 構文解析(syntax analysisnobuya/lecture/plpc/PLPC2012-03_handout.pdf · プログラミング言語の形式的な記述!プログラミング言語の文法の記述方法!バッカス記法

2012/04/23

�#3

����������� Copyright (C) Nobuya WATANABE

文形式,文,言語! 文形式(sentential form)

! 文法G= �P, S��に対して,   のとき,x は G の文形式という

! 文(sentence)! x が終端記号だけからなるとき,x は G の文という

! 言語(language)! G の文全体の集合をL(G)と表記し,Gの定義する言語という

13

S�� x

E � E+T � T+T � T+T*F � F+T*F� F+T*i� F+F*i� F+i*i� i+i*i G1の文

【例】文法G1

※無限に多くの文が存在

2012/04/23

�#3

����������� Copyright (C) Nobuya WATANABE

導出(derive)! 導出

! ある記号列 v に生成規則を何回か適用して,   である記号列 w を求めることを,v から w を導出するという

! 最左導出(left-most derivation)! 記号列の中の最も左に位置する非終端記号に生成規則を適用する導出

! 最右導出(right-most derivation)! 記号列の中の最も右に位置する非終端記号に生成規則を適用する導出

14

v�� w

v �lm

w

v �rm

w v��

rmw

v��lm

w

2012/04/23

�#3

����������� Copyright (C) Nobuya WATANABE

解析木(parse tree)! 解析木

! 文法 G=〈P, S〉の文が,その出発記号 S から導出される様子を木構造で表現したもの

15

E

E

T

T

F

F

i i

i

+

*T

F

節(node)... Gの記号

P1 = {

}

E � T

T � FF � ( E )

T � T * F

E � E + T

F � i

文法G1における    の解析木i+i*i

2012/04/23

�#3

����������� Copyright (C) Nobuya WATANABE

解析木(parse tree)! 解析木

! 文法 G=〈P, S〉の文が,その出発記号 S から導出される様子を木構造で表現したもの

15

E

E

T

T

F

F

i i

i

+

*T

F

節(node)... Gの記号

節Aからn個の節a1,a2,...anへ枝(edge)が延びる生成規則A→a1 ... anが存在する場合のみ

P1 = {

}

E � T

T � FF � ( E )

T � T * F

E � E + T

F � i

文法G1における    の解析木i+i*i

2012/04/23

�#3

����������� Copyright (C) Nobuya WATANABE

あいまい性! あいまいな文(ambiguous sentence)

! 文法Gの文xに対して,xを導出する2つの異なる解析木が考えられるとき,x はあいまいな文であるという

! あいまいな文法! あいまいな文をもつ文法

【例】G2 = �P2, E�

文    に対して2つの異なる解析木が存在したがって,文   はあいまいな文.文法G2はあいまいな文法

16

P2 = { E � E+E | E*E | (E) | i }i+i*i

i+i*i

E

E

i

i i

+

*

E

E E

E

E

i

i i

+

* E

E E

2012/04/23

�#3

����������� Copyright (C) Nobuya WATANABE

あいまいな文法の例: C言語の if 文! C言語の文(statement)の文法

stat:   if ( expr ) stat  if ( expr ) stat else stat  other

! あいまいな文の例! if (e1) if (e2) s1 else s2

! if (e1) { if (e2) s1 else s2}

! if (e1) { if (e2) s1 } else s2

17

if ( )

else

stat

statexpr

e1 if ( ) statexpr stat

e2 s1 s2

if ( ) else

stat

statexpr

e1 if ( ) statexpr

stat

e2 s1

s2

Page 5: 言語処理系構成論(3 構文解析(syntax analysisnobuya/lecture/plpc/PLPC2012-03_handout.pdf · プログラミング言語の形式的な記述!プログラミング言語の文法の記述方法!バッカス記法

2012/04/23

�#3

����������� Copyright (C) Nobuya WATANABE

演算子の優先順位(precedence)と結合性(associativity)

! 演算子の優先順位! 算術式の中に2つの異なる演算子が連続して現れたとき,そのどちらを先に計算するかを決定する順番

! 例! 掛け算の演算子 * は足し算の演算子 + より優先順位が高い! x + y * z → x +(y * z)

! 結合性! 算術式の中に2つの同じ演算子が連続して現れたとき,そのどちらを先に計算するかを決定する順番

! 例! x - y - z → (x - y)- z! x + y + z → (x + y)+ z

18

演算子 - や + は,左結合的(left associative)であるという

2012/04/23

�#3

����������� Copyright (C) Nobuya WATANABE

演算子の優先順位,結合性の表記方法! 表記

! ある演算子op1とop2に対して,op1に続いてop2が現れたとき,! op1を先に計算する場合! op2を先に計算する場合

! 例

19

op1 <· op2

op1 >· op2

+ <· * = <· =- >· - + >· + + >· -

優先順位 左結合的 右結合的 優先順位: =左結合的

2012/04/23

�#3

����������� Copyright (C) Nobuya WATANABE

文法と演算子の優先順位・結合性! プログラミング言語の文法の定義

! 演算子の優先順位と結合性を生成規則の中に埋め込む方法! 埋め込まないで別途指定する方法

20

E

E

T

T

F

F

i i

i

+

*T

F

i + i * i の解析木

P1 = {

}F � ( E )T � T * FE � E + T | T

| F| i

文法 G1 = �P1, E⇥

+ <· *

2012/04/23

�#3

����������� Copyright (C) Nobuya WATANABE

!     の条件1.        の形の生成規則が存在し,かつ

2.ある非終端記号Cに対して

! の条件1.        の形の生成規則が存在し,かつ

2.ある非終端記号Cに対して

文法と演算子の優先順位・結合性

21

op1 <· op2

A⇥ · · · op1B · · ·

B+⇥ C op2 · · ·

op1 >· op2

B+⇥ · · · op1 C

A

Bop1

op2C

op1 <· op2

A

B op2

op1 C

op1 >· op2A� · · · Bop2 · · ·

2012/04/23

�#3

����������� Copyright (C) Nobuya WATANABE

文脈自由文法(context-free grammar)! 文脈に拘束されずに生成規則を適用できる文法! ある非終端記号Aが文形式に現れていれば,Aの前後の記号に関係なく,Aを左辺とする生成規則を適用可能

! 通常のプログラミング言語は文脈自由文法によって定義

! 文脈依存文法(context sensitive grammar)! 文脈に拘束

22 2012/04/23

構文解析法

23

Page 6: 言語処理系構成論(3 構文解析(syntax analysisnobuya/lecture/plpc/PLPC2012-03_handout.pdf · プログラミング言語の形式的な記述!プログラミング言語の文法の記述方法!バッカス記法

2012/04/23

�#3

����������� Copyright (C) Nobuya WATANABE

! プログラミング言語の構文解析! 様々な方法が考案! おおまかな分類

! 上向き構文解析法(bottom-up parsing)! 生成規則の右辺と一致 → 左辺の記号に置換 ... 還元(reduction)

! 入力記号列を葉(終端記号)として,葉(終端記号)から根(非終端記号)へ向かって解析を進めながら解析木を生成

! 下向き構文解析法(top-down parsing)! 記号列として次に何がくるかを仮定しながら解析を進めていく解析法

! 解析木を上(根)から下(葉)へ向かって解析

構文解析法

24

E

E

T

T

F

F

i i

i

+

*T

F

i + i * i の解析木

P1 = {

}F � ( E )T � T * FE � E + T | T

| F| i

2012/04/23

�#3

����������� Copyright (C) Nobuya WATANABE

さまざまな構文解析法! 再帰的下向き構文解析法(recursive descent parsing)

! LL(k)構文解析(Left-to-right scanning, Left-most derivation)

! LR構文解析法(LR parsing)! Left-to-right scanning, Right-most derivation in reverse 

! SLR(1)構文解析法(Simple LR parsing)! LR(1)構文解析法! LALR(1)構文解析法(Lookahead LR parsing)

25

2012/04/23

�#3

����������� Copyright (C) Nobuya WATANABE

構文木(syntax tree)とその表現! 構文木

! 構文解析の結果として生成されるプログラムの内部表現! 例: a = b * c + (d - e)

26

! 構文木の表現! N組(N-tuple)と呼ばれる構造体を使用して表現

=

a

cb

-*

+

d e

=

+

* -

a

b c d e

N組...N個のメンバを持つ構造体

2012/04/23

�#3

����������� Copyright (C) Nobuya WATANABE

構文木とその表現(続き)! C言語でのN組の実現例

! tuple: N組へのポインタ型! token: トークンへのポインタ型

27

x1 = make_tuple(“*”, b, c);x2 = make_tuple(“-”, d, e);x3 = make_tuple(“+”, x1, x2);x4 = make_tuple(“=”, a, x3);

N組の生成例

int is_a(x)トークンの種別判

=

+

* -

a

b c d etuple make_tuple(A, a1, ..., an)

N組を生成する関数

節の値 枝

トークン x が終端記号 a に対応するかを判定【例】is_if ... キーワード if か?

2012/04/23

再帰的下向き構文解析

28 2012/04/23

�#3

����������� Copyright (C) Nobuya WATANABE

再帰的下向き構文解析法(recursive descent parsing)

! 非終端記号ごとに,解析関数(parsing function)を作成! 関数本体では,非終端記号を左辺とする生成規則を忠実に反映したコードを与える! 文法と構文解析プログラムの対応が明確! 文法を変更した場合にも,プログラムの修正が容易

29

Page 7: 言語処理系構成論(3 構文解析(syntax analysisnobuya/lecture/plpc/PLPC2012-03_handout.pdf · プログラミング言語の形式的な記述!プログラミング言語の文法の記述方法!バッカス記法

2012/04/23

�#3

����������� Copyright (C) Nobuya WATANABE

解析関数! 生成規則

30

A� aAb | c

a1 a2 c1 b1 b2 $

p

Aに還元できるトークン列とは,■cのトークンが1つだけ,あるいは,■aのトークンで始まり,Aに還元できるトークン列が続き,bのトークンで終わる一連のトークン列

tuple parse_A() { token *prev = p, x, z; tuple y; if (is_a(x = *p++) && (y = parse_A()) && is_b(z = *p++)) return make_tuple(“A”, x, y, z); p = prev; if (is_c(x = *p++)) return x; p = prev; return NULL;}

トークンのベクタ

tuple parse() { tuple x = parse_A(); if (x && is_eof(*p)) return x; else syntax_error();}

入力トークン列全体を解析する関数2012/04/23

�#3

����������� Copyright (C) Nobuya WATANABE

左再帰(left recursion)! 文法が左再帰を含む→解析関数の再帰呼出が停止しない! 例: 直接の左再帰(immediate left recursion)

!  

31

E � E + T | Ttuple parse_E() { token *prev = p; tuple x, y; if ((x = parse_E()) && is_plus(*p++) && (y = parse_T())) return make_tuple(“+”, x, y); p = prev; if (x = parse_T()) return x; p = prev; return NULL;}

! 間接的な左再帰も同様A� Ba | c

B � Ab | d

2012/04/23

�#3

����������� Copyright (C) Nobuya WATANABE

C言語における左再帰! 識別子のリスト

! 単純に右再帰に置き換えられない例

32

identifier-list:identifieridentifier-list , identifier

identifier-list:identifieridentifier , identifier-list

additive-expression:multiplicative-expressionadditive-expression + multiplicative-expressionadditive-expression - multiplicative-expression

右再帰に置き換え可能

左結合的が右結合的になってしまう

a - b + c = (a - b) + c ≠ a - (b + c) = a - b - c

C言語の文法に間接的な左再帰はない

2012/04/23

�#3

����������� Copyright (C) Nobuya WATANABE

同じ終端記号列を生成するような左再帰のない生成規則

左再帰の除去(left recursion elimination)! 直接の左再帰の除去

33

A� Aa | b

A⇥lm

Aa⇥lm

Aaa⇥lm

Aaaa⇥lm

· · ·⇥lm

Aan ⇥lm

ban

A� bA�

A� � aA� | �

A⇥rm

bA� ⇥rm

baA� ⇥rm

baaA� ⇥rm

· · ·⇥rm

banA� ⇥rm

ban

2012/04/23

�#3

����������� Copyright (C) Nobuya WATANABE

同じ終端記号列を生成するような左再帰のない生成規則

左再帰の除去(left recursion elimination)! 直接の左再帰の除去

33

A� Aa | b

A⇥lm

Aa⇥lm

Aaa⇥lm

Aaaa⇥lm

· · ·⇥lm

Aan ⇥lm

ban

A� bA�

A� � aA� | �

A⇥rm

bA� ⇥rm

baA� ⇥rm

baaA� ⇥rm

· · ·⇥rm

banA� ⇥rm

ban

tuple parse_A() { token *prev = p; if (is_b(y = *p++)) return parse_A1(y); p = prev; return NULL;}tuple parse_A1(tuple x) { token *prev = p, y; if (is_a(y = *p++)) return parse_A1(make_tuple(“A”, x, y)); p = prev; return x;}

入力トークンのポインタが進んでいる.まったく同じ状態で再帰呼出しされるわけでないので無限呼出にはならない

2012/04/23

�#3

����������� Copyright (C) Nobuya WATANABE

左再帰の除去! 直接の左再帰を含む生成規則の一般形

34

A⇥ A�1 | · · · | A�n | ⇥1 | · · · | ⇥m

A⇥ ⇥1A� | · · · | ⇥mA�

A� ⇥ �1A� | · · · | �nA� | ⇤

�i � V � �i A �i � V +ここで    , は で始まらない.次で置き換えることで除去可能

【例】E � E + T | TT � T * F | FF � (E) | i

E � TE�

E� � + TE� | �T � FT �

T � � * FT � | �F � (E) | i

Page 8: 言語処理系構成論(3 構文解析(syntax analysisnobuya/lecture/plpc/PLPC2012-03_handout.pdf · プログラミング言語の形式的な記述!プログラミング言語の文法の記述方法!バッカス記法

2012/04/23

�#3

����������� Copyright (C) Nobuya WATANABE

バックトラック! いくつかの選択肢が考えられるときに,そのうちの1つを試してみて失敗だったと判断した時点でもとの(その選択肢を選ぶ直前)の状態に戻す処理

35

A� aBcB � b | bd

【例】 tuple parse_A() { token *prev = p, x, z; tuple y; if (is_a(x = *p++) && (y = parse_B()) && is_c(z = *p++)) return make_tuple(“A”, x, y, z); p = prev; return NULL;}tuple parse_B() { token *prev = p, x, y; if (is_b(x = *p++)) return x; p = prev; if (is_b(x = *p++) && is_d(y = *p++)) return make_tuple(“B”, x, y); p = prev; return NULL;}

正しく動作しない(例: abdc)

parse_Aが再度parse_B

を呼出して,もう1つの生成規則を試みるよう指示する必要がある一般的には複雑な機構が必要

2012/04/23

�#3

����������� Copyright (C) Nobuya WATANABE

くくり出しによるバックトラックの回避! くくり出し(factoring)でバックトラックを回避可能

36

B � b | bd

B � b (d | �)

tuple parse_B() { token *prev = p, x, y; if (is_b(x = *p++)) { token *prev1 = p, y; if (is_d(y = *p++)) return make_tuple(“B”, x, y); p = prev1; return x; } p = prev; return NULL;}

 のくくり出しb

A⇥ aBcB ⇥ C | DC ⇥ · · ·D ⇥ · · ·

! 生成規則が終端記号で始まらない場合は適用が困難

バックトラックのもう1つの大きな問題:

適切なエラーメッセージ出力が難しい

2012/04/23

�#3

����������� Copyright (C) Nobuya WATANABE

LL(k)構文解析法! バックトラックをしない再帰的下向き構文解析法! k個の入力トークンを先読みし,どの生成規則を適用するかを決定する方法

37

B � C | D!       の解析関数で,次の入力トークン x を先読みし,1.もし      なら parse_Cを呼び出す2.もし      なら parse_Dを呼び出す3.どちらでもなければ,構文エラー

C+⇥ x · · ·

D+⇥ x · · ·

2012/04/23

�#3

����������� Copyright (C) Nobuya WATANABE

LL(1)文法 ー first集合とfollow集合 ー

!  のfirst集合 ... から生成される記号列の先頭に現れる終端記号の全体

! A のfollow集合 ... Aの直後に現れる可能性のある終端記号の全体

!        なら,! 常に,

38

! 文法         とその記号列G = �VN , VT , P, S⇥ � � (VN ⇥ VT )�

� �

First(�) = {a | a ⇤ VT , ��⇥ a · · · }

Follow(A) = {a | a ⇤ VT , S$ �⇥ · · ·Aa · · · }

$ � Follow(A) S�⇥ · · · A

$ � Follow(S)

a

a

A

S

2012/04/23

�#3

����������� Copyright (C) Nobuya WATANABE

LL(1)文法 ー director集合 ー!     のdirector集合 ... 次にこの生成規則を使った場合に,入力トークン列の先頭に現れる可能性のある終端記号の全体

39

A� �

Director(A,�) =

�First(�) (unless �

�� ⇥)First(�) ⇥ Follow(A) (if �

�� ⇥)LL(1)文法

a

A

S

a

A

$

右辺だけが異なる任意の生成規則    と    に対して,必ず

が成り立つ文法

A� � A� �Direcotr(A,�) ⇥Direcotr(A,⇥) = �

入力トークン列の先頭記号を見れば,次にどの生成規則を使用すべきか決定可能

2012/04/23

�#3

����������� Copyright (C) Nobuya WATANABE

Director集合の例! 文法

40

First(T �) = {*}First(E�) = {+}Follow(E) = Follow(E�) = {$, )}Follow(T ) = Follow(T �) = {+, $, )}Follow(F ) = First(T �) � Follow(T �) = {*, +, $, )}

First(E) = First(T ) = First(F ) = {(, i}

Director(E�, +TE�) ⇥Director(E�, �) = �Director(T �, *FT �) ⇥Director(T �, �) = �Director(F, (E)) ⇥Director(F, i) = �

E � TE�

E� � + TE� | �T � FT �

T � � * FT � | �F � (E) | i

LL(1)文法

Director(E�, +TE�) = {+}

Director(T �, *FT �) = {*}

Director(F, (E)) = {(}Director(F, i) = {i}

Director(E�, �) = First(�) � Follow(E�) = {$, )}

Director(T �, �) = First(�) � Follow(T �) = {+, $, )}

Director(E, TE�) = First(T ) = {(, i}

Director(T, FT �) = First(F ) = {(, i}

Page 9: 言語処理系構成論(3 構文解析(syntax analysisnobuya/lecture/plpc/PLPC2012-03_handout.pdf · プログラミング言語の形式的な記述!プログラミング言語の文法の記述方法!バッカス記法

2012/04/23

�#3

����������� Copyright (C) Nobuya WATANABE

tuple parse_E() { if (is_lpar(*P) || is_i(*p)) { tuple x = parse_T(); return parse_E1(x); } else syntax_error();}tuple parse_E1(tuple x) { if (is_plus(*p)) { tuple y; p++; y = parse_T(); return parse_E1(make_tuple(“+”, x, y)); } else syntax_error();}

LL(1)構文解析法! Left-to-right scanning, Left-most derivation

! 入力トークン列を左から右へ読み込む(バックトラックがない)! 最左導出の順序で構文解析を行う

41

バックトラックがなくなったので1. 適切な時点で構文エラーを検出できる

2. pの値を保存しておく必要がない

非終端記号Aの解析関数入力トークンを調べ,Aを左辺とする生成規則のうちで,director集合にそのトークンを含むものを選択し(なければ構文エラー)構文解析を進める.

Director(E, TE�) = First(T ) = {(, i}

Director(E�, +TE�) = {+}

E � TE�

E� � + TE� | �T � FT �

T � � * FT � | �F � (E) | i

2012/04/23

�#3

����������� Copyright (C) Nobuya WATANABE

LL(1)構文解析法(続き)! 再帰的下向き構文解析法の一種

! 文法が左再帰を含む場合,左再帰を除去した文法を使用! 左辺が同じで,右辺が同じ記号で始まる生成規則が複数存在する場合! director集合には共通の終端記号が含まれる(LL(1)でない)! くくり出しが必要

42

! 変換後の文法は,もとの文法より読みづらくなるのが普通! 結果的に複雑な構文解析プログラムとなってしまうことも

生成規則に左再帰がなければ,直感的に理解しやすい構文解析プログラムを作成可能

もとの文法をそのまま使用する構文解析法 → LR構文解析法

文法を変更(変換)した場合,

2012/04/23

�#3

����������� Copyright (C) Nobuya WATANABE

まとめ! 構文解析に必要な基礎知識について説明

! プログラミングの形式的な表現方法! BNF! 拡張BNF

! 文法の基本的な概念や記法! 生成規則,生成,還元,文形式,文,言語! 導出,最左導出,最右導出

! 解析木とあいまい性! 演算子の優先順位と結合性

! 構文解析法! 再帰的下向き構文解析! LR構文解析法(上向き構文解析法) ... 次回

43