基本定义
- F
- 令G是一个不含左递归的文法,对G的所有非终结符的每个候选α定义它的终结首符集FIRST(α)为:
FIRST(α)={a | α=>*a…, a∈VT} - 若α=>*ε,则规定ε∈FIRST(α)
- FIRST(α)是α的所有可能推导的开头终结符或可能的ε
- 如果非终结符A的所有候选首符集两两不相交,即A的任何两个不同候选αi和αj
FIRST(αi) ∩FIRST(αj)=Φ - 那么当要求A匹配输入串时,A就能根据它所面临的第一个输入符号a,准确的指派某一个候选前去执行任务。这个候选就是那个终结首符集含a的α。
- 令G是一个不含左递归的文法,对G的所有非终结符的每个候选α定义它的终结首符集FIRST(α)为:
- F
-
- 假定S是文法G的开始符号,对于G的任何非终结符A,我们定义
FOLLOW(A)={a | S=>*…Aa…,a∈VT} - FOLLOW(A)是所有句型中出现在紧接A之后的终结符或“#”。开始符号的FOLLOW集初始化时加入“#”。
- 当非终结符A面临输入符号a,且a不属于A的任意候选首符集但A的某个候选首符集包含ε时,只有当a∈FOLLOW(A)时,才可能允许A自动匹配。
- 假定S是文法G的开始符号,对于G的任何非终结符A,我们定义
- LL(1)文法
- 文法不含左递归
- 对于文法中每一个非终结符A的各个产生式的候选首符集两两不相交。即,若A→α1 |α2 | … |αn,则FIRST(αi)∩FIRST(αj)=Φ (i≠j)
- 对文法中的每个非终结符A,若它存在某个候选首符集包含ε,则,FIRST(A)∩FOLLOW(A)=Φ
如果一个文法G满足以上条件,则称该文法G为LL(1)文法。 - LL(1)文法是不带回溯的自顶向下的文法
- 预测分析表:
- 预测分析表示一个M[A,a]形式的矩阵。其中A为非终结符,a是终结符或‘#’ 。
- 矩阵元素M[A,a]中存放着一条关于A的产生式,指出当A面临输入符号a时所应采用的候选。
M[A,a]中也可能存放一个“出错标志”,指出A根本不该面临输入符号a。
预测分析表的构造
F
要构造F
,根据定义:α=X
那么对于从前到后的X
我们进行分类讨论:
- 如果X
- 如果X
- 只要X
- 那么我们通过记录每个a∈V
- ,采取递归的形式实现
-
F
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <algorithm> 5 #include <cstdlib> 6 #include <vector> 7 #include <string> 8 #include <cctype> 9 #include <map> 10 #include <set> 11 #define MAX 507 12 13 using namespace std; 14 15 16 //大写字母为非终止符(可以多一个'的标号做区分),小写字母为终止符,用~代替epsilon 17 class WF 18 { 19 public: 20 string left; 21 set<string> right; 22 WF ( char s[] ) 23 { 24 left = s; 25 } 26 void print ( ) 27 { 28 printf ( "%s->" , left.c_str() ); 29 set<string>::iterator it = right.begin(); 30 if ( right.begin()!= right.end() ) 31 { 32 printf ( "%s" , it->c_str() ); 33 it++; 34 } 35 for(; it != right.end() ; it++ ) 36 printf ( "|%s" , it->c_str() ); 37 puts(""); 38 } 39 void insert ( char s[] ) 40 { 41 right.insert ( s ); 42 } 43 }; 44 45 map<string,set<char> > first; 46 map<string,set<char> > follow; 47 map<string,int> VN_dic; 48 vector<WF> VN_set; 49 bool used[MAX]; 50 51 void dfs ( int x ) 52 { 53 if ( used[x] ) return; 54 used[x] = 1; 55 string& left = VN_set[x].left; 56 set<string>& right = VN_set[x].right; 57 set<string>::iterator it = right.begin(); 58 for ( ; it!= right.end() ; it++ ) 59 for ( int i = 0 ; i < it->length() ; i++ ) 60 { 61 if ( !isupper( it->at(i) ) && it->at(i) != '\'' ) 62 { 63 first[left].insert ( it->at(i) ); 64 break; 65 } 66 if ( isupper( it->at(i) ) ) 67 { 68 int y; 69 if ( i != it->length()-1 && it->at(i+1) == '\'' ) 70 y = VN_dic[it->substr(i,2)]-1; 71 else y = VN_dic[it->substr(i,1)]-1; 72 string& tleft = VN_set[y].left; 73 dfs ( y ); 74 set<char>& temp = first[tleft]; 75 set<char>::iterator it1 = temp.begin(); 76 bool flag = true; 77 for ( ; it1 != temp.end() ; it1++ ) 78 { 79 if ( *it1 == '~' ) flag = false; 80 first[left].insert( *it1 ); 81 } 82 if ( flag ) break; 83 } 84 else continue; 85 } 86 } 87 88 void make_first ( ) 89 { 90 memset ( used , 0 , sizeof ( used ) ); 91 for ( int i = 0 ; i < VN_set.size() ; i++ ) 92 dfs ( i ); 93 #define DEBUG 94 #ifdef DEBUG 95 map<string,set<char> >::iterator it = first.begin(); 96 for ( ; it != first.end() ; it++ ) 97 { 98 printf ( "FIRST(%s)={" , it->first.c_str() ); 99 set<char> & temp = it->second; 100 set<char>::iterator it1 = temp.begin(); 101 bool flag = false; 102 for ( ; it1 != temp.end() ; it1++ ) 103 { 104 if ( flag ) printf ( "," ); 105 printf ( "%c" , *it1 ); 106 flag = true; 107 } 108 puts ("}"); 109 } 110 #endif 111 } 112 113 int main ( ) 114 { 115 int n; 116 char s[MAX]; 117 while ( ~scanf ( "%d" , &n ) ) 118 { 119 for ( int i = 0 ; i < n ; i++ ) 120 { 121 scanf ( "%s" , s ); 122 int len = strlen ( s ),j; 123 for ( j = 0 ; j < len ; j++ ) 124 if ( s[j] == '-' ) break; 125 s[j] = 0; 126 if ( !VN_dic[s] ) 127 { 128 VN_set.push_back ( s ); 129 VN_dic[s] = VN_set.size(); 130 } 131 int x = VN_dic[s]-1; 132 VN_set[x].insert ( s+j+2 ); 133 } 134 make_first(); 135 } 136 }