역시 SB 네요.
좋 습 니 다. 우리 라면 말단 부터 시작 해 야 합 니 다. 저 는 handwritten C 나 C 의 작은 부분 집합 인 one - pass 컴 파일 러 를 먼저 시도 해 보 겠 습 니 다. 깊 은 경험 을 한 다음 에 깊 은 형식 이론 을 연구 하 는 것 도 늦 지 않 습 니 다.그래서 저 는 며칠 동안 간단 한 품사 분석 을 했 고 힘 도 들 었 습 니 다. 급 한 아 이 큐 로 문법 트 리 같은 것 을 만들어 서 네 가지 연산 식 을 해석 할 수 있 습 니 다.책 에서 손 으로 쓴 컴 파일 러 는 재 귀 하강 법 이 가장 적합 하 다 고 말 했 는데, 나 는 한참 을 생각 했 지만 어떻게 재 귀 하강 해 야 할 지 몰 랐 다.방금 책 을 읽 은 간단 한 손 글씨 문법 분석 기 를 보 았 는데 모두 100 줄 밖 에 안 되 었 다. 나 는 책 을 보고 감탄 할 수 밖 에 없 었 다. 아, 바닥 이 전혀 딱딱 하지 않 아서 멀 었 다.
며칠 동안 hardcode 의 소감 을 썼 습 니 다.
마침내 왜 책 에서 우리 에 게 문법의 BNF 생 성식 을 모두 열거 하 라 고 했 는 지 알 게 되 었 다. 그리고 그 에 상응하는 모든 생 성식 을 위해 함 수 를 썼 다. 이것 은 사실 알고리즘 결합 을 풀 고 있 는 것 이다.예 를 들 어 우 리 는 아래 의 재 귀 하강 문법 기 는 unary operator 를 지원 하지 않 는 다 는 것 을 테스트 할 수 있다. 예 를 들 어 3 * - 2.이 연산 규칙 에 가입 하려 면 문법 에 규칙 을 새로 추가 한 다음 에 문법 을 수리 하고 마지막 으로 인 코딩: 순환 이 떨 어 지 는 단계 에 unary () 함 수 를 추가 하고 하층 은 factor () 이 며 상층 은 term () 이 며 완성 합 니 다.이렇게 하면 새로운 함 수 를 추가 하여 논리 연산 을 지원 하고 비교 연산 을 확장 할 수 있다.나 처럼 하 드 코드 라면...확장 할 때 비상 하 는 느낌 이 단번에 나 왔 다.
그리고 이와 같은 문법 적 특성 을 고려 하면:
a = b = c = 1;
재 귀 하강 법 을 이용 해도 완벽 하고 간결 하 게 해결 할 수 있 잖 아!
왜 원 리 를 컴 파일 해 야 합 니까?제 가 손 으로 쓴 것 은 점점 이탈리아 국수 가 되 었 기 때문에 하나의 feature 를 확대 할 때마다 온몸 을 움 직 였 습 니 다. 다른 곳 에 bug 를 도 입 했 는 지 전혀 확실 하지 않 습 니 다. 마지막 에 일반적인 C 코드 파일 을 컴 파일 할 수 있 을 지도 모 릅 니 다. 그런데 저 는 TM 가 왜 작 동 하 는 지 모 르 겠 습 니 다. 다른 플랫폼 에 이식 하거나 다른 언어의 컴 파일 러 를 다시 만 들 려 고 할 때어 리 석 을 수 밖 에 없다. 이것 이 바로 '인품 으로 프로 그래 밍' 이다. 이것 이 우리 의 상징적 인 특징 이다. 먼저 기능 을 끝내 고 bug 는 없 는 말 을 하지 못 한다. 야근 으로 보충 하 는 것 은 아니 지........................................................................................
코드 붙 이기:
표준 재 귀 하강 문법 기:
1 #include <stdio.h>
2 #include <stdlib.h>
3
4 char token; /* */
5
6 /* */
7 int exp( void );
8 int term( void );
9 int factor( void );
10
11 void error( void ) /* */
12 {
13 fprintf( stderr, "
");
14 exit( 1 );
15 }
16
17 void match( char expectedToken ) /* */
18 {
19 if( token == expectedToken ) token = getchar(); /* , */
20 else error(); /* , */
21 }
22 void Message(void)
23 {
24 printf("================================================================
");
25 printf("* *
");
26 printf("****************************************************************
");
27 printf(" : , . 45*(12-2)[ ]
");
28 printf("*****************************************************************
");
29 }
30 main()
31 {
32 int result; /* */
33 Message();
34 printf(" >> : ");
35 token = getchar(); /* */
36
37 result = exp(); /* */
38 if( token == '
' ) /* */
39 printf( " >> : %d
", result );
40 else error(); /* */
41 puts("
...
");
42 getch();
43 return 0;
44 }
45
46 int exp( void )
47 {
48 int temp = term(); /* */
49 while(( token == '+' ) || ( token == '-' ))
50 switch( token ) {
51 case '+': match('+'); /* */
52 temp += term();
53 break;
54 case '-': match('-');
55 temp -= term(); /* */
56 break;
57 }
58 return temp;
59 }
60
61 int term( void )
62 {
63 int div; /* */
64 int temp = factor(); /* */
65 while(( token == '*' ) || ( token == '/' ))
66 switch( token ) {
67 case '*': match('*'); /* */
68 temp *= factor();
69 break;
70 case '/': match('/'); /* */
71 div = factor();
72 if( div == 0 ) /* 0*/
73 {
74 fprintf( stderr, " 0.
" );
75 exit(1);
76 }
77 temp /= div;
78 break;
79 }
80 return temp;
81 }
82
83 int factor( void )
84 {
85 int temp;
86 if( token == '(' ) /* */
87 {
88 match( '(' );
89 temp = exp();
90 match(')');
91 }
92 else if ( isdigit( token )) /* */
93 {
94 ungetc( token, stdin ); /* */
95 scanf( "%d", &temp ); /* */
96 token = getchar(); /* */
97 }
98 else error(); /* */
99 return temp;
100 }
나의 비상 코드:
1 #include "StdAfx.h"
2 #include "SyntaxTree.h"
3 #include "Compiler.h"
4
5 eTokenType SyntaxTree::lastTokenType = eTokenType_Invalid;
6
7 int SyntaxTreeOpNode::Evaluate()
8 {
9 if (!strcmp(op, "+"))
10 {
11 return lchild->Evaluate() + rchild->Evaluate();
12 }
13 else if (!strcmp(op, "-"))
14 {
15 return lchild->Evaluate() - rchild->Evaluate();
16 }
17 else if (!strcmp(op, "*"))
18 {
19 return lchild->Evaluate() * rchild->Evaluate();
20 }
21 else if (!strcmp(op, "/"))
22 {
23 return lchild->Evaluate() / rchild->Evaluate();
24 }
25 else
26 {
27 //TODO: refactoring for no ugly if-else
28 assert(0);
29 return 0;
30 }
31 }
32
33 bool SyntaxTreeOpNode::IsThisOpPriorityHigher( const char* s )
34 {
35 return cl.opPriorityMap[op] >= cl.opPriorityMap[s];
36 }
37
38 int SyntaxTreeLeafNode::Evaluate()
39 {
40 return value;
41 }
42
43 int SyntaxTreeRootNode::Evaluate()
44 {
45 assert(rchild && "WTF!? This is not my tree!");
46 return rchild->Evaluate();
47 }
48
49 SyntaxTree::SyntaxTree()
50 :root(nullptr)
51 {
52 }
53
54 SyntaxTree::~SyntaxTree()
55 {
56 ResetTree();
57 }
58
59 bool SyntaxTree::ConstructTree(int len)
60 {
61 const char* expstart = cl.sentence + cl.sentence_curpos;
62 assert(expstart[0] != 0);
63 char op[MAX_IDENT_LEN];
64 eTokenType type;
65 SyntaxTreeNode* curNode = root;
66 std::vector<int> vecNums;
67 std::vector<SyntaxTreeOpNode*> vecFlatNodes;
68
69 //1.
70 while (cl.sentence_curpos < len)
71 {
72 type = cl.ScanWord(op);
73 if (type == eTokenType_Operator)
74 {
75 auto iter = cl.opPriorityMap.find(op);
76 assert(iter != cl.opPriorityMap.end() && "Invalid op!");
77 SyntaxTreeOpNode* node = new SyntaxTreeOpNode;
78 strcpy_s(node->op, ARRAYSIZE(node->op), op);
79
80 //unary op process
81 bool bUnary = op[1]==0 && (op[0]=='+' || op[0]=='-');
82 if (lastTokenType==eTokenType_Operator || lastTokenType==eTokenType_LBracket && bUnary)
83 {
84 vecNums.push_back(0);
85 curNode->rchild = node;
86 node->parent = curNode;
87 }
88 else if (curNode->IsThisOpPriorityHigher(op))
89 {
90 assert(node->parent == nullptr);
91 curNode->parent = node;
92 node->lchild = curNode;
93 // root
94 root->rchild = node;
95 node->parent = root;
96 }
97 else
98 {
99 curNode->rchild = node;
100 node->parent = curNode;
101 }
102 curNode = node;
103 vecFlatNodes.push_back(node);
104 }
105 else if (type == eTokenType_ConstantNumber)
106 {
107 vecNums.push_back(atoi(op));
108 }
109 else if (type == eTokenType_LBracket)
110 {
111 int substr_len = len - 1;
112 //must find a matching r-bracket!
113 bool bFind = false;
114 while (substr_len >= cl.sentence_curpos)
115 {
116 if(cl.sentence[substr_len] == ')')
117 {
118 bFind = true;
119 break;
120 }
121 --substr_len;
122 }
123 if (bFind)
124 {
125 // , ...
126 SyntaxTree tmpTree;
127 tmpTree.ResetTree();
128 if(tmpTree.ConstructTree(substr_len))
129 vecNums.push_back(tmpTree.Evaluate());
130 else
131 return false;
132
133 assert(cl.sentence[cl.sentence_curpos] == ')' && "Can't be true!...");
134 ++cl.sentence_curpos;
135 }
136 else
137 {
138 LOG_ERR(eErr_NotMatchBracket);
139 return false;
140 }
141 type = eTokenType_ConstantNumber;
142 }
143 else
144 {
145 LOG_ERR(eErr_InvalidExpression);
146 return false;
147 }
148 lastTokenType = type;
149 }
150
151 //2.
152 if (root->rchild == nullptr)
153 {
154 LOG_ERR(eErr_InvalidExpression);
155 return false;
156 }
157
158 size_t leaf = 0, totalLeaf = vecNums.size();
159 for (size_t i=0; i<vecFlatNodes.size(); ++i)
160 {
161 SyntaxTreeOpNode* node = vecFlatNodes[i];
162 if (!node->lchild)
163 {
164 if (leaf < totalLeaf)
165 {
166 SyntaxTreeLeafNode* leafNode = new SyntaxTreeLeafNode;
167 leafNode->value = vecNums[leaf];
168 node->lchild = leafNode;
169 leafNode->parent = node;
170 ++leaf;
171 }
172 else
173 {
174 LOG_ERR(eErr_InvalidExpression);
175 return false;
176 }
177 }
178 if (!node->rchild)
179 {
180 if (leaf < totalLeaf)
181 {
182 SyntaxTreeLeafNode* leafNode = new SyntaxTreeLeafNode;
183 leafNode->value = vecNums[leaf];
184 node->rchild = leafNode;
185 leafNode->parent = node;
186 ++leaf;
187 }
188 else
189 {
190 LOG_ERR(eErr_InvalidExpression);
191 return false;
192 }
193 }
194 }
195
196 return true;
197 }
198
199 void SyntaxTree::ResetTree()
200 {
201 SAFE_DELETE(root);
202 root = new SyntaxTreeRootNode;
203 }
204
205 int SyntaxTree::Evaluate()
206 {
207 return root->Evaluate();
208 }
마지막 으로 본의 아니 게 이 친구 가 만 지 작 거 리 는 걸 봤 어 요. 나 보다 못 한 것 같 아 요..................................................와 하하 하, 슬 픈 우리 야
http://blog.csdn.net/zhouzxi/article/details/7897301
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.