add syntax

This commit is contained in:
2025-11-28 20:12:51 +09:00
parent 1f7026bda8
commit 2d185ee8ee
19 changed files with 1203 additions and 716 deletions

View File

@@ -8,13 +8,14 @@
background-color: white; background-color: white;
font-family: NanumGothic; font-family: NanumGothic;
} }
font-size: 11pt; font-size: 10pt;
font-family: NanumMyeongjo; font-family: NanumMyeongjo;
.language-scanres { .language-scanres {
font-size: 6pt; font-size: 6pt;
} }
ol, ul { ol, ul {
margin-top: 0.0pt; margin-top: 0.0pt;
margin-bottom: 0.2rem;
} }
p { p {
margin-bottom: 0.4rem; margin-bottom: 0.4rem;

View File

@@ -68,3 +68,77 @@ Language usually have basic types aka primitive types. Using these types to buil
There are two options: There are two options:
1. Implement a method `Equals(T1, T2)`. 1. Implement a method `Equals(T1, T2)`.
It must compare type trees of T1 and T2. For OOP languages also need sub-types It must compare type trees of T1 and T2. For OOP languages also need sub-types
### Type Checking Methodology
Type checking means verifying whether expressions are given proper types
1. Implement using Syntax-Directed Definitions(SDD)
2. First build the AST, then implement type checking by recursive traversal of the AST nodes
#### SDD
SDD associates semantic rules for the productions in the CFG. It checks types based on the semantic rules associated with the production rules.
#### AST Traversal
Type Checking During AST Traversal.
중간에 새로운 타입이 생길 수 있음.
By Recursive Traversal of the AST nodes, inferencing types of AST nodes.
### Inference
$$\frac{\vdash H_1 \vdash H_2 \vdash H_3}{\vdash \text{conclusion}}[\text{rule name}]$$
#### Soundness
항상 참이 되는 타입
$e : T$ means that $e$ is a sound expression of type $T$, that is $e$ is always the type $T$.
for non expression statements use special unit type (like void or empty type)
$S: \text{void}$
#### Proof Tree
$$\frac{
\frac{1 \text{ is a integer literal}}{\vdash 1: \text{int}} [\text{int}] \;
\frac{2 \text{ is an integer literal}}{\vdash 2: \text{int}} [\text{int}]
}{\vdash 1 + 2 : \text{int}} [\text{int add}]
$$
Proof Tree는 AST를 뒤집은 모양.
If-then-else는 가질 수 있는데, If-then은 타입을 가질 수 없음.
#### Type Environment
어떻게 $x$가 variable이라고 할때 어떤 타입을 가지는지 알 수가 없음.
Type Environment gives types for **free variables**.
$$O \vdash e: T$$
* $O$ is essentially **symbol table**.
Complex Example of Declaration:
```c
for (T1 i = 0;;) {
exp
}
```
$$\frac{O[T1/i] \vdash \text{exp}: T2}{O\vdash \texttt{for}(i: T1) \set{\text{exp}: T2}}$$
Complex Example of Class Attrs
$$O_C(x) = T$$
* forall attrs $x: T$ in class C
$$O_C$$
Complex Example of Class Methods
### Subtyping

379
out/lex.md Normal file
View File

@@ -0,0 +1,379 @@
# Lexical Analysis(Scanner) Report
* 주하진, 2024062806
## Compilation Environment and Method
주어진 `Makefile`을 이용하여 C파일을 컴파일함.
C파일은 `gcc`를 이용해서 컴파일한다.
`Makefile`에서 산출되는 실행파일은 `cminus_cimpl``cminus_lex`가 있으며 각각 `main.c util.c scan.c`, `main.c util.c lex.yy.c`를 컴파일한 오브젝트 파일을 필요로 한다.
`lex.yy.c``flex -o lex.yy.c cminus.l`을 통해 생성된다.
## C-Minus Language
C-Minus에서 필요한 토큰타입변수와 그에 대한 설명은 다음과 같다.
**특수 토큰**
* `ENDFILE`: 파일끝
* `ERROR`: 에러
**키워드 토큰**
* `IF`: `if`
* `THEN`: `then`
* `ELSE`: `else`
* `WHILE`: `while`
* `RETURN`: `return`
* `INT`: `int`
* `VOID`: `void`
**가변길이 토큰**
* `ID`: 식별자
* `NUM`: 숫자
**기호 토큰**
* `ASSIGN`: `=`
* `EQ`: `==`
* `NE`: `!=`
* `LT`: `<`
* `LE`: `<=`
* `GT`: `>`
* `GE`: `>=`
* `PLUS`: `+`
* `MINUS`: `-`
* `TIMES`: `*`
* `OVER`: `/`
* `LPAREN`: `(`
* `RPAREN`: `)`
* `LBRACE`: `[`
* `RBRACE`: `]`
* `LCURLY`: `{`
* `RCURLY`: `}`
* `SEMI`: `;`
* `COMMA`: `,`
**토큰에 포함되지 않는 스펙**
* `/*` - `*/`: 주석 (토큰에 포함하지 않음)
위와 같은 토큰 타입을 기반으로 토크나이징하는 것이 목적이다.
### Using `scan.c`
`scan.c`에서는 올바른 `getToken`을 작성해야 한다.
`getToken`을 작성하기에 앞서 전이가능한 `STATE`를 작성한다. 특히 `<`, `>`, `!`, `=`, `/`의 경우에는 단 한 글자만 받는게 아니라 그 다음 문자에 따라 산출할 토큰이 달라질 수 있으므로 그에 따른 `STATE`를 만든다.
결과적으로 필요한 STATE는 다음과 같다.
```
START, INOVER, INCOMMENT, ASTERCOMMENT, INASSIGN, INLT, INGT, INNE, INNUM, INID, DONE
```
이를 이용해 `getToken`의 DFA를 작성할 수 있다.
```mermaid
stateDiagram-v2
START
state comment {
INOVER
INCOMMENT
ASTERCOMMENT
}
INASSIGN
INLT
INGT
INNE
state multichar {
INNUM
INID
}
state done {
DONE
}
START --> INNUM: isdigit
INNUM --> INNUM: isdigit
INNUM --> DONE: else with unget
START --> INID: isalpha
INID --> INID: isalnum
INID --> DONE: else with unget
START --> INASSIGN: =
INASSIGN --> DONE: =
INASSIGN --> DONE: else with unget
START --> INLT: \<
INLT --> DONE: =
INLT --> DONE: else with unget
START --> INGT: \>
INGT --> DONE: =
INGT --> DONE: else with unget
START --> INNE: !
INNE --> DONE: =
INNE --> DONE: else with unget and</br> return ERROR
START --> INOVER: /
INOVER --> INCOMMENT: \*
INCOMMENT --> ASTERCOMMENT: \*
ASTERCOMMENT --> INCOMMENT: else
ASTERCOMMENT --> START: /
```
이를 통해 `scan.c`를 작성하면 된다.
이때 `tokenString`은 항상 넣되 (하지만 NUM, ID 토큰에서만 필요함) comment때만 안 넣으면 된다. `unget`할때도 안넣어야 한다.
### Using Lex (cminus.l)
tiny의 lex파일처럼 간단하게 넣고 컴파일하면 된다.
하나 중요한 점은 comment를 구현할 때, `prev``now`를 각 과정에서 계속 업데이트 해가면서 `now == '/' && prev == '*'` 일때까지 계속 `input()`을 받아주면 된다.
## Examples & Result
<table>
<tr>
<th>cminus file</th>
<th>result text file</th>
</tr>
<tr>
<td>
```c { .line-numbers }
/* A program to perform Euclid's
Algorithm to computer gcd */
int gcd (int u, int v)
{
if (v == 0) return u;
else return gcd(v,u-u/v*v);
/* u-u/v*v == u mod v */
}
void main(void)
{
int x; int y;
x = input(); y = input();
output(gcd(x,y));
}
```
</td>
<td>
```scanres
C-MINUS COMPILATION: ./test1.cm
4: reserved word: int
4: ID, name= gcd
4: (
4: reserved word: int
4: ID, name= u
4: ,
4: reserved word: int
4: ID, name= v
4: )
5: {
6: reserved word: if
6: (
6: ID, name= v
6: ==
6: NUM, val= 0
6: )
6: reserved word: return
6: ID, name= u
6: ;
7: reserved word: else
7: reserved word: return
7: ID, name= gcd
7: (
7: ID, name= v
7: ,
7: ID, name= u
7: -
7: ID, name= u
7: /
7: ID, name= v
7: *
7: ID, name= v
7: )
7: ;
9: }
11: reserved word: void
11: ID, name= main
11: (
11: reserved word: void
11: )
12: {
13: reserved word: int
13: ID, name= x
13: ;
13: reserved word: int
13: ID, name= y
13: ;
14: ID, name= x
14: =
14: ID, name= input
14: (
14: )
14: ;
14: ID, name= y
14: =
14: ID, name= input
14: (
14: )
14: ;
15: ID, name= output
15: (
15: ID, name= gcd
15: (
15: ID, name= x
15: ,
15: ID, name= y
15: )
15: )
15: ;
16: }
17: EOF
```
</td>
</tr>
<tr>
<td>
```c {.line-numbers}
void main(void)
{
int i; int x[5];
i = 0;
while( i < 5 )
{
x[i] = input();
i = i + 1;
}
i = 0;
while( i <= 4 )
{
if( x[i] != 0 )
{
output(x[i]);
}
}
}
```
</td>
<td>
```scanres
C-MINUS COMPILATION: ./test2.cm
1: reserved word: void
1: ID, name= main
1: (
1: reserved word: void
1: )
2: {
3: reserved word: int
3: ID, name= i
3: ;
3: reserved word: int
3: ID, name= x
3: [
3: NUM, val= 5
3: ]
3: ;
5: ID, name= i
5: =
5: NUM, val= 0
5: ;
6: reserved word: while
6: (
6: ID, name= i
6: <
6: NUM, val= 5
6: )
7: {
8: ID, name= x
8: [
8: ID, name= i
8: ]
8: =
8: ID, name= input
8: (
8: )
8: ;
10: ID, name= i
10: =
10: ID, name= i
10: +
10: NUM, val= 1
10: ;
11: }
13: ID, name= i
13: =
13: NUM, val= 0
13: ;
14: reserved word: while
14: (
14: ID, name= i
14: <=
14: NUM, val= 4
14: )
15: {
16: reserved word: if
16: (
16: ID, name= x
16: [
16: ID, name= i
16: ]
16: !=
16: NUM, val= 0
16: )
17: {
18: ID, name= output
18: (
18: ID, name= x
18: [
18: ID, name= i
18: ]
18: )
18: ;
19: }
20: }
21: }
22: EOF
```
</td>
</tr>
</table>

BIN
out/lex.pdf Normal file

Binary file not shown.

View File

@@ -1,269 +1,135 @@
# Lexical Analysis(Scanner) Report # Syntax Analysis (Parser) Report
* 주하진, 2024062806 * 주하진, 2024062806
## Compilation Environment and Method ## Compilation Environment and Method
주어진 `Makefile`을 이용하여 C파일을 컴파일함. 주어진 `Makefile`을 이용 C파일`cminus.l`, `cminus.y`를 변환함.
C파일은 `gcc`를 이용해서 컴파일한다. C파일은 `gcc`를 이용하고 `*.l``flex`, `*.y``yacc`을 이용함.
`Makefile`에서 산출되는 실행파일은 `cminus_cimpl``cminus_lex`가 있으며 각각 `main.c util.c scan.c`, `main.c util.c lex.yy.c`를 컴파일한 오브젝트 파일을 필요로 한다.
`lex.yy.c` `flex -o lex.yy.c cminus.l`을 통해 생성된다. `Makefile`의 빌드 결과물 `cminus_parser`를 만들기 위해서 `main.c`, `util.c`, `lex.yy.o`, `y.tab.o`를 필요로 한다.
## C-Minus Language ## C-Minus Parser Implementation
C-Minus에서 필요한 토큰타입변수와 그에 대한 설명은 다음과 같다. C-Minus Parser 구현을 위해 다음 세 파일의 큰 수정이 필요했다.
**특수 토큰** * `globals.h`
* `util.c`, `util.h`
* `cminus.y` (Important)
* `ENDFILE`: 파일끝 ### `globals.h`
* `ERROR`: 에러
**키워드 토큰** 여러개의 Kind Enum을 추가하였다.
* NodeKind(큰 분류)
* StmtKind(Statement의 종류)
* ExpKind(Expression의 종류)
* DeclKind(Declaration의 종류)
* TypeKind(Declaration에서 Type을 구분하기 위해 사용, 실제로 파스트리에 들어가진 않음, var_declaration에서 참조하기 위한 목적.)
* `IF`: `if` **StmtKind**
* `THEN`: `then` * IfK: if문
* `ELSE`: `else` * IterK: while문
* `WHILE`: `while` * ReturnK: return문
* `RETURN`: `return` * CompK: 여러개 있는 중괄호(복합) 문
* `INT`: `int`
* `VOID`: `void`
**가변길이 토큰** **ExpKind**
* AssignK: 할당문
* OpK: 연산자가 포함된 표현식
* ConstK: 상수
* IdK: 식별자
* ArrIdK: 배열 식별자
* CallK: 함수 호출
* `ID`: 식별자 **DeclKind**
* `NUM`: 숫자 * FuncK: 함수 선언
* VarK: 변수 선언
* ArrVarK: 배열 변수 선언
* ArrParamK: 배열 매개변수
* NonArrParamK: 매개변수
**기호 토큰** **TypeKind**
* TypeNameK: 선언의 타입
* `ASSIGN`: `=` -----
* `EQ`: `==` `TreeNode`를 추가하였다.
* `NE`: `!=`
* `LT`: `<`
* `LE`: `<=`
* `GT`: `>`
* `GE`: `>=`
* `PLUS`: `+`
* `MINUS`: `-`
* `TIMES`: `*`
* `OVER`: `/`
* `LPAREN`: `(`
* `RPAREN`: `)`
* `LBRACE`: `[`
* `RBRACE`: `]`
* `LCURLY`: `{`
* `RCURLY`: `}`
* `SEMI`: `;`
* `COMMA`: `,`
**토큰에 포함되지 않는 스펙** ```c
typedef struct treeNode {
* `/*` - `*/`: 주석 (토큰에 포함하지 않음) struct treeNode *child[MAXCHILDREN];
struct treeNode *sibling;
위와 같은 토큰 타입을 기반으로 토크나이징하는 것이 목적이다. int lineno;
NodeKind nodekind;
### Using `scan.c` union {
StmtKind stmt;
`scan.c`에서는 올바른 `getToken`을 작성해야 한다. ExpKind exp;
DeclKind decl;
`getToken`을 작성하기에 앞서 전이가능한 `STATE`를 작성한다. 특히 `<`, `>`, `!`, `=`, `/`의 경우에는 단 한 글자만 받는게 아니라 그 다음 문자에 따라 산출할 토큰이 달라질 수 있으므로 그에 따른 `STATE`를 만든다. TypeKind type;
} kind;
결과적으로 필요한 STATE는 다음과 같다. union {
TokenType op;
``` int val;
START, INOVER, INCOMMENT, ASTERCOMMENT, INASSIGN, INLT, INGT, INNE, INNUM, INID, DONE char *name;
} attr;
ExpType type; /* for type checking of exps */
} TreeNode;
``` ```
이를 이용해 `getToken`의 DFA를 작성할 수 있다. TreeNode 타입은 ParseTree의 노드를 나타내며, 자식 노드와 형제 노드를 가리키는 포인터 그리고 노드의 kind와 attr, type을 가진다.
```mermaid ### `util.c`, `util.h`
stateDiagram-v2
START `newStmtNode`, `newExpNode`, `newDeclNode`, `newTypeNode` 함수를 추가 및 수정했다. 각각 Statement, Expression, Declaration, Type 노드를 생성하는 함수이다.
state comment {
INOVER Type을 출력하기 위해 `printType` 함수를 추가하였다.
INCOMMENT
ASTERCOMMENT printTree는 TreeNode를 출력하는 함수이다. nodeKind에 따라 구분하여 출력한다. 이때 type이 필요한 node이면 type도 같이 출력한다.
}
### `cminus.y`(Important)
cminus.y에서 토큰의 선언은 다음과 같이 했다.
```yacc
%token IF ELSE WHILE RETURN INT VOID
%token EQ NE LT LE GT GE LPAREN RPAREN LBRACE LCURLY RBRACE RCURLY SEMI
%token ID NUM
INASSIGN %left PLUS MINUS
INLT %left TIMES OVER
INGT %right ASSIGN
INNE
state multichar {
INNUM
INID
}
%nonassoc THEN
%nonassoc ELSE
state done { %token ERROR
DONE
}
START --> INNUM: isdigit
INNUM --> INNUM: isdigit
INNUM --> DONE: else with unget
START --> INID: isalpha
INID --> INID: isalnum
INID --> DONE: else with unget
START --> INASSIGN: =
INASSIGN --> DONE: =
INASSIGN --> DONE: else with unget
START --> INLT: \<
INLT --> DONE: =
INLT --> DONE: else with unget
START --> INGT: \>
INGT --> DONE: =
INGT --> DONE: else with unget
START --> INNE: !
INNE --> DONE: =
INNE --> DONE: else with unget and</br> return ERROR
START --> INOVER: /
INOVER --> INCOMMENT: \*
INCOMMENT --> ASTERCOMMENT: \*
ASTERCOMMENT --> INCOMMENT: else
ASTERCOMMENT --> START: /
``` ```
이를 통해 `scan.c`를 작성하면 된다. 나머지 부분은 제공된 grammar와 tiny.y의 많은 부분을 참고하여 작성했다.
이때 `tokenString`은 항상 넣되 (하지만 NUM, ID 토큰에서만 필요함) comment때만 안 넣으면 된다. `unget`할때도 안넣어야 한다. 이때 중요한 부분은 **dangling-else** 부분이다.
### Using Lex (cminus.l) ```yacc
selection_stmt : IF LPAREN expression RPAREN statement %prec THEN {
...
} | IF LPAREN expression RPAREN statement ELSE statement {
...
};
```
tiny의 lex파일처럼 간단하게 넣고 컴파일하면 된다. `single-if`문의 우선순위를 `ELSE`보다 낮은 `THEN`으로 지정하여 Shift/Reduce Conflict를 해결했다.
하나 중요한 점은 comment를 구현할 때, `prev``now`를 각 과정에서 계속 업데이트 해가면서 `now == '/' && prev == '*'` 일때까지 계속 `input()`을 받아주면 된다. ## Results
## Examples & Result
다음은 테스트 C-Minus 프로그램과 그에 대한 파스트리 출력 결과이다.
<table> <table>
<tr> <tr>
<th>cminus file</th> <th>C-Minus Test Program</th>
<th>result text file</th> <th>Parse Tree Output</th>
</tr> </tr><tr>
<tr>
<td> <td>
```c { .line-numbers } ```c
/* A program to perform Euclid's
Algorithm to computer gcd */
int gcd (int u, int v)
{
if (v == 0) return u;
else return gcd(v,u-u/v*v);
/* u-u/v*v == u mod v */
}
void main(void)
{
int x; int y;
x = input(); y = input();
output(gcd(x,y));
}
```
</td>
<td>
```scanres
C-MINUS COMPILATION: ./test1.cm
4: reserved word: int
4: ID, name= gcd
4: (
4: reserved word: int
4: ID, name= u
4: ,
4: reserved word: int
4: ID, name= v
4: )
5: {
6: reserved word: if
6: (
6: ID, name= v
6: ==
6: NUM, val= 0
6: )
6: reserved word: return
6: ID, name= u
6: ;
7: reserved word: else
7: reserved word: return
7: ID, name= gcd
7: (
7: ID, name= v
7: ,
7: ID, name= u
7: -
7: ID, name= u
7: /
7: ID, name= v
7: *
7: ID, name= v
7: )
7: ;
9: }
11: reserved word: void
11: ID, name= main
11: (
11: reserved word: void
11: )
12: {
13: reserved word: int
13: ID, name= x
13: ;
13: reserved word: int
13: ID, name= y
13: ;
14: ID, name= x
14: =
14: ID, name= input
14: (
14: )
14: ;
14: ID, name= y
14: =
14: ID, name= input
14: (
14: )
14: ;
15: ID, name= output
15: (
15: ID, name= gcd
15: (
15: ID, name= x
15: ,
15: ID, name= y
15: )
15: )
15: ;
16: }
17: EOF
```
</td>
</tr>
<tr>
<td>
```c {.line-numbers}
void main(void) void main(void)
{ {
int i; int x[5]; int i; int x[5];
@@ -285,95 +151,117 @@ void main(void)
} }
} }
} }
```
</td><td>
```txt
C-MINUS COMPILATION: test.2.txt
Syntax tree:
Function Declaration: name = main, return type = void
Void Parameter
Compound Statement:
Variable Declaration: name = i, type = int
Variable Declaration: name = x, type = int[]
Const: 5
Assign:
Variable: name = i
Const: 0
While Statement:
Op: <
Variable: name = i
Const: 5
Compound Statement:
Assign:
Variable: name = x
Variable: name = i
Call: function name = input
Assign:
Variable: name = i
Op: +
Variable: name = i
Const: 1
Assign:
Variable: name = i
Const: 0
While Statement:
Op: <=
Variable: name = i
Const: 4
Compound Statement:
If Statement:
Op: !=
Variable: name = x
Variable: name = i
Const: 0
Compound Statement:
Call: function name = output
Variable: name = x
Variable: name = i
``` ```
</td> </td></tr>
<td><tr>
<td> <td>
```scanres ```c
int main(void){
C-MINUS COMPILATION: ./test2.cm int a;
1: reserved word: void int b;
1: ID, name= main a = (b = 4) + 3;
1: ( if(a==b+(c*b+d))
1: reserved word: void while(1)
1: ) if(1)
2: { a=2;
3: reserved word: int else a=3;
3: ID, name= i }
3: ;
3: reserved word: int
3: ID, name= x
3: [
3: NUM, val= 5
3: ]
3: ;
5: ID, name= i
5: =
5: NUM, val= 0
5: ;
6: reserved word: while
6: (
6: ID, name= i
6: <
6: NUM, val= 5
6: )
7: {
8: ID, name= x
8: [
8: ID, name= i
8: ]
8: =
8: ID, name= input
8: (
8: )
8: ;
10: ID, name= i
10: =
10: ID, name= i
10: +
10: NUM, val= 1
10: ;
11: }
13: ID, name= i
13: =
13: NUM, val= 0
13: ;
14: reserved word: while
14: (
14: ID, name= i
14: <=
14: NUM, val= 4
14: )
15: {
16: reserved word: if
16: (
16: ID, name= x
16: [
16: ID, name= i
16: ]
16: !=
16: NUM, val= 0
16: )
17: {
18: ID, name= output
18: (
18: ID, name= x
18: [
18: ID, name= i
18: ]
18: )
18: ;
19: }
20: }
21: }
22: EOF
``` ```
</td><td>
```txt
C-MINUS COMPILATION: test.cm
Syntax tree:
Function Declaration: name = main, return type = int
Void Parameter
Compound Statement:
Variable Declaration: name = a, type = int
Variable Declaration: name = b, type = int
Assign:
Variable: name = a
Op: +
Assign:
Variable: name = b
Const: 4
Const: 3
If Statement:
Op: ==
Variable: name = a
Op: +
Variable: name = b
Op: +
Op: *
Variable: name = c
Variable: name = b
Variable: name = d
While Statement:
Const: 1
If-Else Statement:
Const: 1
Assign:
Variable: name = a
Const: 2
Assign:
Variable: name = a
Const: 3
```
</td> </td>
</tr> </tr>
</table> </table>

Binary file not shown.

View File

@@ -1,37 +1,43 @@
# Makefile for C-Minus Scanner # Makefile for C-Minus
# ./lex/tiny.l --> ./cminus.l #
# ./lex/tiny.l --> ./cminus.l (from Project 1)
# ./yacc/tiny.y --> ./cminus.y
# ./yacc/globals.h --> ./globals.h
CC = gcc CC = gcc
CFLAGS = -W -Wall CFLAGS = -W -Wall
OBJS = main.o util.o scan.o OBJS = main.o util.o lex.yy.o y.tab.o
OBJS_LEX = main.o util.o lex.yy.o
.PHONY: all clean .PHONY: all clean
all: cminus_cimpl cminus_lex all: cminus_parser
clean: clean:
-rm -vf cminus_cimpl cminus_lex *.o lex.yy.c rm -vf cminus_parser *.o lex.yy.c y.tab.c y.tab.h y.output
cminus_cimpl: $(OBJS) cminus_parser: $(OBJS)
$(CC) $(CFLAGS) -o $@ $(OBJS) $(CC) $(CFLAGS) $(OBJS) -o $@ -lfl
cminus_lex: $(OBJS_LEX) main.o: main.c globals.h util.h scan.h parse.h y.tab.h
$(CC) $(CFLAGS) -o $@ $(OBJS_LEX) -lfl $(CC) $(CFLAGS) -c main.c
main.o: main.c globals.h util.h scan.h util.o: util.c util.h globals.h y.tab.h
$(CC) $(CFLAGS) -c -o $@ $< $(CC) $(CFLAGS) -c util.c
scan.o: scan.c globals.h util.h scan.h scan.o: scan.c scan.h util.h globals.h y.tab.h
$(CC) $(CFLAGS) -c -o $@ $< $(CC) $(CFLAGS) -c scan.c
util.o: util.c globals.h util.h lex.yy.o: lex.yy.c scan.h util.h globals.h y.tab.h
$(CC) $(CFLAGS) -c -o $@ $< $(CC) $(CFLAGS) -c lex.yy.c
lex.yy.o: lex.yy.c globals.h util.h scan.h
$(CC) $(CFLAGS) -c -o $@ $<
lex.yy.c: cminus.l lex.yy.c: cminus.l
flex -o $@ $< flex cminus.l
y.tab.h: y.tab.c
y.tab.o: y.tab.c parse.h
$(CC) $(CFLAGS) -c y.tab.c
y.tab.c: cminus.y
yacc -d -Wcounterexamples -v cminus.y

328
src/cminus.y Normal file
View File

@@ -0,0 +1,328 @@
/****************************************************/
/* File: tiny.y */
/* The TINY Yacc/Bison specification file */
/* Compiler Construction: Principles and Practice */
/* Kenneth C. Louden */
/****************************************************/
%{
#define YYPARSER /* distinguishes Yacc output from other code files */
#include "globals.h"
#include "util.h"
#include "scan.h"
#include "parse.h"
#define YYSTYPE TreeNode *
static char * savedName; /* for use in assignments */
static int savedNumber;
static int savedLineNo; /* ditto */
static TreeNode * savedTree; /* stores syntax tree for later return */
static int yylex(void); // added 11/2/11 to ensure no conflict with lex
%}
%token IF ELSE WHILE RETURN INT VOID
%token EQ NE LT LE GT GE LPAREN RPAREN LBRACE LCURLY RBRACE RCURLY SEMI COMMA
%token ID NUM
%left PLUS MINUS
%left TIMES OVER
%right ASSIGN
%nonassoc THEN
%nonassoc ELSE
%token ERROR
%% /* Grammar for C-MINUS */
program : declaration_list
{savedTree = $1;};
declaration_list : declaration_list declaration {
YYSTYPE t = $1;
if (t != NULL) {
while (t->sibling != NULL) {
t = t->sibling;
}
t->sibling = $2;
$$ = $1;
} else { $$ = $2; };
}
| declaration { $$ = $1; }
;
declaration : var_declaration {$$ = $1; } | func_declaration { $$ = $1; };
name_specifier : ID {
savedName = copyString(tokenString);
savedLineNo = lineno;
};
number_specifier : NUM {
savedNumber = atoi(tokenString);
savedLineNo = lineno;
};
var_declaration : type_specifier name_specifier SEMI {
$$ = newDeclNode(VarK);
$$->lineno = savedLineNo;
$$->attr.name = savedName;
$$->type = $1->type;
free($1);
} | type_specifier name_specifier LBRACE number_specifier RBRACE SEMI {
$$ = newDeclNode(ArrVarK);
$$->lineno = savedLineNo;
$$->type = IntegerArray;
$$->attr.name = savedName;
free($1);
$$->child[0] = newExpNode(ConstK);
$$->child[0]->type = Integer;
$$->child[0]->attr.val = savedNumber;
};
type_specifier : INT {
$$ = newTypeNode(TypeNameK);
$$->type = Integer;
}
| VOID {
$$ = newTypeNode(TypeNameK);
$$->type = Void;
};
func_declaration : type_specifier name_specifier {
$$ = newDeclNode(FuncK);
$$->lineno = savedLineNo;
$$->attr.name = savedName;
$$->type = $1->type; /* 타입 바로 복사 */
} LPAREN params RPAREN compound_stmt {
$$ = $3;
$$->child[0] = $5; /* params */
$$->child[1] = $7; /* compound_stmt */
};
params : param_list { $$ = $1; } | VOID {
$$ = newDeclNode(NonArrParamK);
$$->type = Void;
};
param_list : param_list COMMA param {
YYSTYPE t = $1;
if (t != NULL) {
while (t->sibling != NULL) {
t = t->sibling;
}
t->sibling = $3;
$$ = $1;
} else {
$$ = $3;
};
} | param {$$ = $1; };
param : type_specifier name_specifier {
$$ = newDeclNode(NonArrParamK );
$$->attr.name = savedName;
$$->type = $1->type;
} | type_specifier name_specifier LBRACE RBRACE {
$$ = newDeclNode(ArrParamK);
$$->type = $1->type;
$$->attr.name = savedName;
};
compound_stmt : LCURLY local_declarations statement_list RCURLY {
$$ = newStmtNode(CompK);
$$->lineno = lineno;
$$->child[0] = $2;
$$->child[1] = $3;
};
local_declarations : local_declarations var_declaration {
YYSTYPE t = $1;
if (t != NULL) {
while (t->sibling != NULL)
t = t->sibling;
t->sibling = $2;
$$ = $1;
} else $$ = $2;
} | { $$ = NULL; };
statement_list : statement_list statement {
YYSTYPE t = $1;
if (t != NULL) {
while (t->sibling != NULL)
t = t->sibling;
t->sibling = $2;
$$ = $1;
} else $$ = $2;
} | { $$ = NULL; };
statement : expression_stmt { $$ = $1; }
| compound_stmt { $$ = $1; }
| selection_stmt { $$ = $1; }
| iteration_stmt { $$ = $1; }
| return_stmt { $$ = $1; }
;
expression_stmt : expression SEMI { $$ = $1; }
| SEMI { $$ = NULL; }
;
selection_stmt : IF LPAREN expression RPAREN statement %prec THEN {
$$ = newStmtNode(IfK);
$$->lineno = lineno;
$$->child[0] = $3;
$$->child[1] = $5;
} | IF LPAREN expression RPAREN statement ELSE statement {
$$ = newStmtNode(IfK);
$$->lineno = lineno;
$$->child[0] = $3;
$$->child[1] = $5;
$$->child[2] = $7;
};
iteration_stmt : WHILE LPAREN expression RPAREN statement {
$$ = newStmtNode(IterK);
$$->lineno = lineno;
$$->child[0] = $3;
$$->child[1] = $5;
};
return_stmt : RETURN SEMI {
$$ = newStmtNode(ReturnK);
$$->lineno = lineno;
} | RETURN expression SEMI {
$$ = newStmtNode(ReturnK);
$$->lineno = lineno;
$$->child[0] = $2;
};
expression : var ASSIGN expression {
$$ = newExpNode(AssignK);
$$->lineno = lineno;
$$->type = $3->type;
$$->child[0] = $1;
$$->child[1] = $3;
} | simple_expression { $$ = $1; };
var : name_specifier {
$$ = newExpNode(IdK);
$$->attr.name = savedName;
} | name_specifier {
$$ = newExpNode(ArrIdK);
$$->attr.name = savedName;
} LBRACE expression RBRACE {
$$ = $2;
$$->child[0] = $4;
};
simple_expression : additive_expression relop additive_expression {
$$ = $2;
$$->lineno = lineno;
$$->child[0] = $1;
$$->child[1] = $3;
$$->type = Integer;
} | additive_expression { $$ = $1; };
relop : LE {
$$ = newExpNode(OpK);
$$->attr.op = LE;
} | LT {
$$ = newExpNode(OpK);
$$->attr.op = LT;
} | GT {
$$ = newExpNode(OpK);
$$->attr.op = GT;
} | GE {
$$ = newExpNode(OpK);
$$->attr.op = GE;
} | EQ {
$$ = newExpNode(OpK);
$$->attr.op = EQ;
} | NE {
$$ = newExpNode(OpK);
$$->attr.op = NE;
};
additive_expression : additive_expression addop term {
$$ = $2;
$$->lineno = lineno;
$$->child[0] = $1;
$$->child[1] = $3;
} | term { $$ = $1; };
addop : PLUS {
$$ = newExpNode(OpK);
$$->attr.op = PLUS;
} | MINUS {
$$ = newExpNode(OpK);
$$->attr.op = MINUS;
};
term : term mulop factor {
$$ = $2;
$$->lineno = lineno;
$$->child[0] = $1;
$$->child[1] = $3;
} | factor { $$ = $1; };
mulop : TIMES {
$$ = newExpNode(OpK);
$$->attr.op = TIMES;
} | OVER {
$$ = newExpNode(OpK);
$$->attr.op = OVER;
};
factor : LPAREN expression RPAREN { $$ = $2; }
| var { $$ = $1; }
| call { $$ = $1; }
| NUM {
$$ = newExpNode(ConstK);
$$->lineno = lineno;
$$->type = Integer;
$$->attr.val = atoi(tokenString);
}
;
call : name_specifier {
$$ = newExpNode(CallK);
$$->lineno = lineno;
$$->attr.name = savedName;
} LPAREN args RPAREN {
$$ = $2;
$$->child[0] = $4;
};
args : arg_list { $$ = $1; } | { $$ = NULL; } ;
arg_list : arg_list COMMA expression {
YYSTYPE t = $1;
if (t != NULL) {
while (t->sibling != NULL)
t = t->sibling;
t->sibling = $3;
$$ = $1;
} else $$ = $3;
} | expression { $$ = $1; } ;
%%
int yyerror(char * message)
{ fprintf(listing,"Syntax error at line %d: %s\n",lineno,message);
fprintf(listing,"Current token: ");
printToken(yychar,tokenString);
Error = TRUE;
return 0;
}
/* yylex calls getToken to make Yacc/Bison output
* compatible with ealier versions of the TINY scanner
*/
static int yylex(void)
{ return getToken(); }
TreeNode * parse(void)
{ yyparse();
return savedTree;
}

View File

@@ -9,9 +9,9 @@
#ifndef _GLOBALS_H_ #ifndef _GLOBALS_H_
#define _GLOBALS_H_ #define _GLOBALS_H_
#include <ctype.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <ctype.h>
#include <string.h> #include <string.h>
#ifndef FALSE #ifndef FALSE
@@ -22,23 +22,56 @@
#define TRUE 1 #define TRUE 1
#endif #endif
#ifndef YYPARSER
#include "y.tab.h"
#define ENDFILE 0
#endif
/* MAXRESERVED = the number of reserved words */ /* MAXRESERVED = the number of reserved words */
#define MAXRESERVED 6 #define MAXRESERVED 6
#if 0
typedef enum typedef enum
/* book-keeping tokens */ /* book-keeping tokens */
{ENDFILE,ERROR, { ENDFILE,
/* reserved words */ ERROR,
IF,ELSE,WHILE,RETURN,INT,VOID, /* reserved words */
/* multicharacter tokens */ IF,
ID,NUM, ELSE,
/* special symbols */ WHILE,
ASSIGN,EQ,NE,LT,LE,GT,GE,PLUS,MINUS,TIMES,OVER,LPAREN,RPAREN,LBRACE,RBRACE,LCURLY,RCURLY,SEMI,COMMA RETURN,
} TokenType; INT,
VOID,
/* multicharacter tokens */
ID,
NUM,
/* special symbols */
ASSIGN,
EQ,
NE,
LT,
LE,
GT,
GE,
PLUS,
MINUS,
TIMES,
OVER,
LPAREN,
RPAREN,
LBRACE,
RBRACE,
LCURLY,
RCURLY,
SEMI,
COMMA
} TokenType;
#endif
extern FILE* source; /* source code text file */ typedef int TokenType;
extern FILE* listing; /* listing output text file */
extern FILE* code; /* code text file for TM simulator */ extern FILE *source; /* source code text file */
extern FILE *listing; /* listing output text file */
extern FILE *code; /* code text file for TM simulator */
extern int lineno; /* source line number for listing */ extern int lineno; /* source line number for listing */
@@ -46,26 +79,52 @@ extern int lineno; /* source line number for listing */
/*********** Syntax tree for parsing ************/ /*********** Syntax tree for parsing ************/
/**************************************************/ /**************************************************/
typedef enum {StmtK,ExpK} NodeKind; typedef enum { StmtK,
typedef enum {IfK,RepeatK,AssignK,ReadK,WriteK} StmtKind; ExpK,
typedef enum {OpK,ConstK,IdK} ExpKind; DeclK,
TypeK } NodeKind;
typedef enum { CompK,
IfK,
IterK, /* WhileK*/
ReturnK } StmtKind;
typedef enum { AssignK,
OpK,
ConstK,
IdK,
ArrIdK,
CallK } ExpKind;
typedef enum { FuncK,
VarK,
ArrVarK,
ArrParamK,
NonArrParamK } DeclKind;
typedef enum { TypeNameK } TypeKind;
/* ExpType is used for type checking */ /* ExpType is used for type checking */
typedef enum {Void,Integer,Boolean} ExpType; typedef enum { Void,
Integer,
IntegerArray } ExpType;
#define MAXCHILDREN 3 #define MAXCHILDREN 3
typedef struct treeNode typedef struct treeNode {
{ struct treeNode * child[MAXCHILDREN]; struct treeNode *child[MAXCHILDREN];
struct treeNode * sibling; struct treeNode *sibling;
int lineno; int lineno;
NodeKind nodekind; NodeKind nodekind;
union { StmtKind stmt; ExpKind exp;} kind; union {
union { TokenType op; StmtKind stmt;
int val; ExpKind exp;
char * name; } attr; DeclKind decl;
ExpType type; /* for type checking of exps */ TypeKind type;
} TreeNode; } kind;
union {
TokenType op;
int val;
char *name;
} attr;
ExpType type; /* for type checking of exps */
} TreeNode;
/**************************************************/ /**************************************************/
/*********** Flags for tracing ************/ /*********** Flags for tracing ************/

View File

@@ -8,7 +8,7 @@
#include "globals.h" #include "globals.h"
/* set NO_PARSE to TRUE to get a scanner-only compiler */ /* set NO_PARSE to TRUE to get a scanner-only compiler */
#define NO_PARSE TRUE #define NO_PARSE FALSE
/* set NO_ANALYZE to TRUE to get a parser-only compiler */ /* set NO_ANALYZE to TRUE to get a parser-only compiler */
#define NO_ANALYZE TRUE #define NO_ANALYZE TRUE
@@ -38,8 +38,8 @@ FILE *code;
/* allocate and set tracing flags */ /* allocate and set tracing flags */
int EchoSource = FALSE; int EchoSource = FALSE;
int TraceScan = TRUE; int TraceScan = FALSE;
int TraceParse = FALSE; int TraceParse = TRUE;
int TraceAnalyze = FALSE; int TraceAnalyze = FALSE;
int TraceCode = FALSE; int TraceCode = FALSE;

View File

@@ -1,73 +0,0 @@
C-MINUS COMPILATION: ./test.1.txt
4: reserved word: int
4: ID, name= gcd
4: (
4: reserved word: int
4: ID, name= u
4: ,
4: reserved word: int
4: ID, name= v
4: )
5: {
6: reserved word: if
6: (
6: ID, name= v
6: ==
6: NUM, val= 0
6: )
6: reserved word: return
6: ID, name= u
6: ;
7: reserved word: else
7: reserved word: return
7: ID, name= gcd
7: (
7: ID, name= v
7: ,
7: ID, name= u
7: -
7: ID, name= u
7: /
7: ID, name= v
7: *
7: ID, name= v
7: )
7: ;
9: }
11: reserved word: void
11: ID, name= main
11: (
11: reserved word: void
11: )
12: {
13: reserved word: int
13: ID, name= x
13: ;
13: reserved word: int
13: ID, name= y
13: ;
14: ID, name= x
14: =
14: ID, name= input
14: (
14: )
14: ;
14: ID, name= y
14: =
14: ID, name= input
14: (
14: )
14: ;
15: ID, name= output
15: (
15: ID, name= gcd
15: (
15: ID, name= x
15: ,
15: ID, name= y
15: )
15: )
15: ;
16: }
17: EOF

View File

@@ -1,77 +0,0 @@
C-MINUS COMPILATION: ./test.2.txt
1: reserved word: void
1: ID, name= main
1: (
1: reserved word: void
1: )
2: {
3: reserved word: int
3: ID, name= i
3: ;
3: reserved word: int
3: ID, name= x
3: [
3: NUM, val= 5
3: ]
3: ;
5: ID, name= i
5: =
5: NUM, val= 0
5: ;
6: reserved word: while
6: (
6: ID, name= i
6: <
6: NUM, val= 5
6: )
7: {
8: ID, name= x
8: [
8: ID, name= i
8: ]
8: =
8: ID, name= input
8: (
8: )
8: ;
10: ID, name= i
10: =
10: ID, name= i
10: +
10: NUM, val= 1
10: ;
11: }
13: ID, name= i
13: =
13: NUM, val= 0
13: ;
14: reserved word: while
14: (
14: ID, name= i
14: <=
14: NUM, val= 4
14: )
15: {
16: reserved word: if
16: (
16: ID, name= x
16: [
16: ID, name= i
16: ]
16: !=
16: NUM, val= 0
16: )
17: {
18: ID, name= output
18: (
18: ID, name= x
18: [
18: ID, name= i
18: ]
18: )
18: ;
19: }
20: }
21: }
22: EOF

View File

@@ -1,73 +0,0 @@
C-MINUS COMPILATION: ./test1.cm
4: reserved word: int
4: ID, name= gcd
4: (
4: reserved word: int
4: ID, name= u
4: ,
4: reserved word: int
4: ID, name= v
4: )
5: {
6: reserved word: if
6: (
6: ID, name= v
6: ==
6: NUM, val= 0
6: )
6: reserved word: return
6: ID, name= u
6: ;
7: reserved word: else
7: reserved word: return
7: ID, name= gcd
7: (
7: ID, name= v
7: ,
7: ID, name= u
7: -
7: ID, name= u
7: /
7: ID, name= v
7: *
7: ID, name= v
7: )
7: ;
9: }
11: reserved word: void
11: ID, name= main
11: (
11: reserved word: void
11: )
12: {
13: reserved word: int
13: ID, name= x
13: ;
13: reserved word: int
13: ID, name= y
13: ;
14: ID, name= x
14: =
14: ID, name= input
14: (
14: )
14: ;
14: ID, name= y
14: =
14: ID, name= input
14: (
14: )
14: ;
15: ID, name= output
15: (
15: ID, name= gcd
15: (
15: ID, name= x
15: ,
15: ID, name= y
15: )
15: )
15: ;
16: }
17: EOF

View File

@@ -1,77 +0,0 @@
C-MINUS COMPILATION: ./test2.cm
1: reserved word: void
1: ID, name= main
1: (
1: reserved word: void
1: )
2: {
3: reserved word: int
3: ID, name= i
3: ;
3: reserved word: int
3: ID, name= x
3: [
3: NUM, val= 5
3: ]
3: ;
5: ID, name= i
5: =
5: NUM, val= 0
5: ;
6: reserved word: while
6: (
6: ID, name= i
6: <
6: NUM, val= 5
6: )
7: {
8: ID, name= x
8: [
8: ID, name= i
8: ]
8: =
8: ID, name= input
8: (
8: )
8: ;
10: ID, name= i
10: =
10: ID, name= i
10: +
10: NUM, val= 1
10: ;
11: }
13: ID, name= i
13: =
13: NUM, val= 0
13: ;
14: reserved word: while
14: (
14: ID, name= i
14: <=
14: NUM, val= 4
14: )
15: {
16: reserved word: if
16: (
16: ID, name= x
16: [
16: ID, name= i
16: ]
16: !=
16: NUM, val= 0
16: )
17: {
18: ID, name= output
18: (
18: ID, name= x
18: [
18: ID, name= i
18: ]
18: )
18: ;
19: }
20: }
21: }
22: EOF

View File

@@ -1,5 +0,0 @@
/*
dddd

View File

@@ -1,16 +0,0 @@
/* A program to perform Euclid's
Algorithm to computer gcd */
int gcd (int u, int v)
{
if (v == 0) return u;
else return gcd(v,u-u/v*v);
/* u-u/v*v == u mod v */
}
void main(void)
{
int x; int y;
x = input(); y = input();
output(gcd(x,y));
}

View File

@@ -1,21 +0,0 @@
void main(void)
{
int i; int x[5];
i = 0;
while( i < 5 )
{
x[i] = input();
i = i + 1;
}
i = 0;
while( i <= 4 )
{
if( x[i] != 0 )
{
output(x[i]);
}
}
}

View File

@@ -137,6 +137,36 @@ TreeNode *newExpNode(ExpKind kind) {
return t; return t;
} }
TreeNode *newDeclNode(DeclKind kind) {
TreeNode *t = (TreeNode *) malloc(sizeof(TreeNode));
int i;
if (t == NULL)
fprintf(listing, "Out of memory error at line %d\n", lineno);
else {
for (i = 0; i < MAXCHILDREN; i++) t->child[i] = NULL;
t->sibling = NULL;
t->nodekind = DeclK;
t->kind.decl = kind;
t->lineno = lineno;
}
return t;
}
TreeNode *newTypeNode(TypeKind kind) {
TreeNode *t = (TreeNode *) malloc(sizeof(TreeNode));
int i;
if (t == NULL)
fprintf(listing, "Out of memory error at line %d\n", lineno);
else {
for (i = 0; i < MAXCHILDREN; i++) t->child[i] = NULL;
t->sibling = NULL;
t->nodekind = TypeK;
t->kind.type = kind;
t->lineno = lineno;
}
return t;
}
/* Function copyString allocates and makes a new /* Function copyString allocates and makes a new
* copy of an existing string * copy of an existing string
*/ */
@@ -169,6 +199,22 @@ static void printSpaces(void) {
fprintf(listing, " "); fprintf(listing, " ");
} }
void printType(TreeNode *tree) {
switch (tree->type) {
case Void:
fprintf(listing, "void");
break;
case Integer:
fprintf(listing, "int");
break;
case IntegerArray:
fprintf(listing, "int[]");
break;
default:
return;
}
}
/* procedure printTree prints a syntax tree to the /* procedure printTree prints a syntax tree to the
* listing file using indentation to indicate subtrees * listing file using indentation to indicate subtrees
*/ */
@@ -179,27 +225,28 @@ void printTree(TreeNode *tree) {
printSpaces(); printSpaces();
if (tree->nodekind == StmtK) { if (tree->nodekind == StmtK) {
switch (tree->kind.stmt) { switch (tree->kind.stmt) {
case CompK:
fprintf(listing, "Compound Statement:\n");
break;
case IfK: case IfK:
fprintf(listing, "If\n"); fprintf(listing, "%s:\n",
(tree->child[2] != NULL) ? "If-Else Statement" : "If Statement");
break; break;
case RepeatK: case IterK:
fprintf(listing, "Repeat\n"); fprintf(listing, "While Statement:\n");
break; break;
case AssignK: case ReturnK:
fprintf(listing, "Assign to: %s\n", tree->attr.name); fprintf(listing, "Return Statement:\n");
break;
case ReadK:
fprintf(listing, "Read: %s\n", tree->attr.name);
break;
case WriteK:
fprintf(listing, "Write\n");
break; break;
default: default:
fprintf(listing, "Unknown ExpNode kind\n"); fprintf(listing, "Unknown StmtNode kind\n");
break; break;
} }
} else if (tree->nodekind == ExpK) { } else if (tree->nodekind == ExpK) {
switch (tree->kind.exp) { switch (tree->kind.exp) {
case AssignK:
fprintf(listing, "Assign:\n");
break;
case OpK: case OpK:
fprintf(listing, "Op: "); fprintf(listing, "Op: ");
printToken(tree->attr.op, "\0"); printToken(tree->attr.op, "\0");
@@ -208,12 +255,55 @@ void printTree(TreeNode *tree) {
fprintf(listing, "Const: %d\n", tree->attr.val); fprintf(listing, "Const: %d\n", tree->attr.val);
break; break;
case IdK: case IdK:
fprintf(listing, "Id: %s\n", tree->attr.name); fprintf(listing, "Variable: name = %s\n", tree->attr.name);
break;
case ArrIdK:
fprintf(listing, "Variable: name = %s\n", tree->attr.name);
break;
case CallK:
fprintf(listing, "Call: function name = %s\n", tree->attr.name);
break; break;
default: default:
fprintf(listing, "Unknown ExpNode kind\n"); fprintf(listing, "Unknown ExpNode kind\n");
break; break;
} }
} else if (tree->nodekind == DeclK) {
switch (tree->kind.decl) {
case FuncK:
fprintf(listing, "Function Declaration: name = %s, return type = ", tree->attr.name);
printType(tree);
fprintf(listing, "\n");
break;
case VarK:
fprintf(listing, "Variable Declaration: name = %s, type = ", tree->attr.name);
printType(tree);
fprintf(listing, "\n");
break;
case ArrVarK:
fprintf(listing, "Variable Declaration: name = %s, type = ", tree->attr.name);
printType(tree);
fprintf(listing, "\n");
break;
case NonArrParamK:
if (tree->type == Void)
fprintf(listing, "Void Parameter\n");
else {
fprintf(listing, "Parameter: name = %s, type = ", tree->attr.name);
printType(tree);
fprintf(listing, "\n");
}
break;
case ArrParamK:
fprintf(listing, "Parameter: name = %s, type = ", tree->attr.name);
printType(tree);
fprintf(listing, "\n");
break;
default:
fprintf(listing, "Unknown DeclNode kind\n");
break;
}
} else if (tree->nodekind == TypeK) {
} else } else
fprintf(listing, "Unknown node kind\n"); fprintf(listing, "Unknown node kind\n");
for (i = 0; i < MAXCHILDREN; i++) for (i = 0; i < MAXCHILDREN; i++)

View File

@@ -25,6 +25,10 @@ TreeNode * newStmtNode(StmtKind);
*/ */
TreeNode * newExpNode(ExpKind); TreeNode * newExpNode(ExpKind);
TreeNode* newDeclNode(DeclKind);
TreeNode* newTypeNode(TypeKind);
/* Function copyString allocates and makes a new /* Function copyString allocates and makes a new
* copy of an existing string * copy of an existing string
*/ */