Skip to content

Commit dea756d

Browse files
committed
chore: 중간 커밋 — 문법 수정 및 semantic 모듈 초기 구현
- grammer.md: for문에 declaration_statement 허용 추가 - lib.rs: semantic 모듈 노출 - main.rs: lexing → parsing → semantic 분석 실행 흐름 구현 - parser/utils.rs: start_pos, end_pos 유틸 메서드 추가 - semantic/: Resolver, Analyzer, 오류 타입 등 기본 뼈대 구현
1 parent ab68242 commit dea756d

File tree

18 files changed

+403
-14
lines changed

18 files changed

+403
-14
lines changed

grammer.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ expression_statement ::= expression? ";"
3939
4040
if_statement ::= "if" "(" expression ")" statement ( "else" statement )?
4141
while_statement ::= "while" "(" expression ")" statement
42-
for_statement ::= "for" "(" expression? ";" expression? ";" expression? ")" statement
42+
for_statement ::= "for" "(" (declaration_statement | expression)? ";" expression? ";" expression? ")" statement
4343
return_statement ::= "return" expression? ";"
4444
break_statement ::= "break" ";"
4545
continue_statement ::= "continue" ";"

src/ast/node.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
use crate::ast::Expr;
2+
use crate::ast::program::Span;
3+
4+
#[derive(Debug, Clone, PartialEq)]
5+
pub struct Node<T> {
6+
pub span: Span,
7+
pub node: T,
8+
}
9+
10+
pub type ExprNode = Node<Expr>;

src/ast/program.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,29 @@ pub struct Program {
55
pub functions: Vec<Function>,
66
}
77

8+
#[derive(Debug, Clone, PartialEq)]
9+
pub struct Span {
10+
pub start: Pos,
11+
pub end: Pos
12+
}
13+
14+
impl Span {
15+
pub fn new(start: Pos, end: Pos) -> Span {
16+
Span { start, end }
17+
}
18+
}
19+
20+
#[derive(Debug, Clone, PartialEq)]
21+
pub struct Pos {
22+
pub line: usize,
23+
pub column: usize,
24+
}
25+
26+
impl Pos {
27+
pub fn new(line: usize, column: usize) -> Pos {
28+
Pos {line, column}
29+
}
30+
}
31+
832
// 프로그램 전체: 0개 이상의 함수 정의
933
// program ::= function_definition*

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
pub mod ast;
22
pub mod lexer;
33
pub mod parser;
4+
pub mod semantic;

src/main.rs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,23 @@
1+
use rustc_tape4::lexer::Lexer;
2+
use rustc_tape4::parser::Parser;
3+
use rustc_tape4::semantic;
4+
use semantic::analyzer::analyzer::Analyzer;
5+
16
mod lexer;
27

38
fn main() {
4-
println!("Hello, world!");
9+
let source = std::fs::read_to_string("tests/fixtures/sample.c").expect("could not read file");
10+
11+
// lexing
12+
let tokens = Lexer::new(&source).collect_spanned_tokens();
13+
14+
// parsing
15+
let mut parser = Parser::new(tokens);
16+
let program = parser.parse_program().expect("Parsing Failed");
17+
18+
// println!("{:#?}", program);
19+
// semantic analysis
20+
let mut analyzer = Analyzer::new(&program);
21+
let result = analyzer.analyze().expect("Analyzing Failed");
22+
// println!("Hello, world!");
523
}

src/parser/utils.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use crate::ast::program::Pos;
12
use crate::lexer::Token;
23
use crate::parser::Parser;
34
use crate::parser::parser::ParseResult;
@@ -79,4 +80,17 @@ impl Parser {
7980
self.unexpected_token(expected)
8081
}
8182
}
83+
84+
/// 아직 소비되지 않은 현재 토큰의 위치
85+
pub fn start_pos(&self) -> Pos {
86+
let st = &self.tokens[self.pos];
87+
Pos::new(st.line, st.column)
88+
}
89+
90+
/// 직전에 소비된 토큰의 위치
91+
pub fn end_pos(&self) -> Pos {
92+
let idx = self.pos.saturating_sub(1);
93+
let st = &self.tokens[idx];
94+
Pos::new(st.line, st.column)
95+
}
8296
}

src/semantic/analyzer/analyzer.rs

Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
use crate::ast::{Expr, Program, Stmt};
2+
use crate::semantic::analyzer::error::SemanticError;
3+
use crate::semantic::resolver::resolver::Resolver;
4+
pub type AnalzeResult<T> = Result<T, SemanticError>;
5+
pub struct Analyzer<'a> {
6+
pub name_resolver: Resolver,
7+
pub program: &'a Program,
8+
pub loop_depth: usize,
9+
}
10+
impl<'a> Analyzer<'a> {
11+
pub fn new(program: &'a Program) -> Self {
12+
Analyzer {
13+
name_resolver: Resolver::new(),
14+
program,
15+
loop_depth: 0,
16+
}
17+
}
18+
pub fn analyze(&mut self) -> AnalzeResult<()> {
19+
for func in self.program.functions.iter() {
20+
self.name_resolver.declare_function(func).map_err(|_| {
21+
SemanticError::DuplicateDeclaration {
22+
name: func.name.clone(),
23+
}
24+
})?;
25+
}
26+
27+
for func in self.program.functions.iter() {
28+
self.name_resolver.push_scope();
29+
for param in &func.params {
30+
self.name_resolver
31+
.declare_variable(&param.name, &param.ty)
32+
.map_err(|_| SemanticError::DuplicateDeclaration {
33+
name: param.name.clone(),
34+
})?;
35+
}
36+
self.analyze_block(&Stmt::Block(func.body.clone()))?;
37+
self.name_resolver.pop_scope();
38+
}
39+
Ok(())
40+
}
41+
fn analyze_block(&mut self, stmt: &Stmt) -> Result<(), SemanticError> {
42+
if let Stmt::Block(block) = stmt {
43+
for s in &block.statements {
44+
self.analyze_stmt(s)?;
45+
}
46+
} else {
47+
// println!("{:?}", stmt);
48+
self.analyze_stmt(stmt)?;
49+
}
50+
Ok(())
51+
}
52+
fn analyze_stmt(&mut self, stmt: &Stmt) -> Result<(), SemanticError> {
53+
match stmt {
54+
Stmt::ExprStmt(expr) => {
55+
if let Some(expr_opt) = expr {
56+
self.analyze_expr(expr_opt)?
57+
}
58+
}
59+
Stmt::If {
60+
cond,
61+
then_branch,
62+
else_branch,
63+
} => {
64+
self.analyze_expr(cond)?;
65+
self.analyze_block(then_branch)?;
66+
if let Some(else_branch_opt) = else_branch {
67+
self.analyze_block(else_branch_opt)?;
68+
}
69+
}
70+
Stmt::While { cond, body } => {
71+
self.loop_depth += 1;
72+
self.analyze_expr(cond)?;
73+
self.analyze_stmt(body)?;
74+
self.loop_depth -= 1;
75+
}
76+
Stmt::Return(expr) => {
77+
if let Some(expr_opt) = expr {
78+
self.analyze_expr(expr_opt)?;
79+
}
80+
}
81+
Stmt::Block(inner_stmts) => {
82+
self.analyze_block(&Stmt::Block(inner_stmts.clone()))?;
83+
}
84+
Stmt::For {
85+
init,
86+
cond,
87+
step,
88+
body,
89+
} => {
90+
self.loop_depth += 1;
91+
self.name_resolver.push_scope();
92+
if let Some(init_stmt) = init {
93+
self.analyze_stmt(init_stmt)?;
94+
}
95+
if let Some(cond_expr) = cond {
96+
self.analyze_expr(cond_expr)?;
97+
}
98+
self.analyze_stmt(body)?;
99+
if let Some(step_expr) = step {
100+
self.analyze_expr(step_expr)?;
101+
}
102+
self.name_resolver.pop_scope();
103+
self.loop_depth -= 1;
104+
}
105+
Stmt::Declaration { ty, declarators } => {
106+
for declarator in declarators {
107+
self.name_resolver
108+
.declare_variable(&declarator.name, ty)
109+
.map_err(|_| SemanticError::DuplicateDeclaration {
110+
name: declarator.name.clone(),
111+
})?;
112+
if let Some(init_expr) = &declarator.init {
113+
self.analyze_expr(&init_expr)?;
114+
}
115+
}
116+
}
117+
Stmt::Continue => {
118+
if self.loop_depth == 0 {
119+
return Err(SemanticError::InvalidContinue);
120+
}
121+
}
122+
Stmt::Break => {
123+
if self.loop_depth == 0 {
124+
return Err(SemanticError::InvalidBreak);
125+
}
126+
}
127+
}
128+
Ok(())
129+
}
130+
fn analyze_expr(&mut self, expr: &Expr) -> Result<(), SemanticError> {
131+
match expr {
132+
Expr::Ident(name) => {
133+
self.name_resolver
134+
.resolve_identifier(name)
135+
.map_err(|_| SemanticError::UndefinedSymbol { name: name.clone() })?;
136+
}
137+
Expr::BinaryOp { lhs, rhs, .. } => {
138+
self.analyze_expr(lhs)?;
139+
self.analyze_expr(rhs)?;
140+
}
141+
Expr::UnaryPostfixOp { lhs, .. } => {
142+
self.analyze_expr(lhs)?;
143+
}
144+
Expr::UnaryPrefixOp { rhs, .. } => {
145+
self.analyze_expr(rhs)?;
146+
}
147+
Expr::Assignment { left, right, .. } => {
148+
self.analyze_expr(left)?;
149+
self.analyze_expr(right)?;
150+
}
151+
Expr::ArrayIndex { array, index } => {
152+
self.analyze_expr(array)?;
153+
self.analyze_expr(index)?;
154+
}
155+
Expr::Call { func, args, .. } => match func.as_ref() {
156+
Expr::Ident(func_name) => {
157+
self.name_resolver
158+
.resolve_identifier(func_name)
159+
.map_err(|_| SemanticError::UndefinedSymbol {
160+
name: func_name.clone(),
161+
})?;
162+
for arg in args {
163+
self.analyze_expr(arg)?;
164+
}
165+
}
166+
_ => unreachable!(),
167+
},
168+
Expr::InitializerList(exprs) => {
169+
for e in exprs {
170+
self.analyze_expr(e)?;
171+
}
172+
}
173+
Expr::CharLiteral(_) | Expr::IntLiteral(_) => {}
174+
}
175+
Ok(())
176+
}
177+
}

src/semantic/analyzer/error.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#[derive(Debug)]
2+
pub enum SemanticError {
3+
UndefinedSymbol { name: String },
4+
DuplicateDeclaration { name: String },
5+
InvalidReturnType { expected: String, found: String },
6+
InvalidContinue,
7+
InvalidBreak,
8+
}

src/semantic/analyzer/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
pub mod analyzer;
2+
mod error;

src/semantic/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
pub mod analyzer;
2+
pub mod resolver;
3+
pub mod symbol;

0 commit comments

Comments
 (0)