Programming Languagues

jinhyukko·2026년 1월 19일

0 . Introduction

Definition

[!tip] Programming Language
A notation system that represents computations in a form that can be performed by computers and read by humans.

0.1 Language Spectrum

![[Language Spectrum.canvas|Language Spectrum]]

1 . [[Programming language Implementation]]

![[Screenshot 2023-10-08 at 12.41.05 AM.png]]

1.4.1 Compilation- [[Compiler Design]]:

  1. Process: In compilation, the source code of a program is translated into machine code or an intermediate code by a compiler before execution.
    • Compiler: A compiler is a software tool that takes the entire source code as input and generates an executable binary or intermediate code file as output.
    • Execution: The compiled code can be executed directly by the computer's processor without the need for the original source code or the compiler. It typically runs faster than interpreted code because the translation phase is done beforehand.
    • Examples: Programming languages like [[C]], [[C++]], and Rust use compilation as their primary implementation method.

1.4.2 Interpretation- [[Interpretor]]

  1. Process: In interpretation, the source code is executed line-by-line or statement-by-statement by an interpreter without the need for a separate compilation step.
    • Interpreter: An interpreter is a program that reads the source code, translates it into machine code or performs the operations directly, and then executes it immediately.
    • Execution: Programs written in interpreted languages are executed directly from the source code. This means that changes to the code are immediately reflected during execution, making it easier to debug.
    • Examples: Languages like [[Python]], [[JavaScript]], and Ruby are typically interpreted, although some of them use Just-In-Time (JIT) compilation for optimization.

1.4.3 Hybrid (Just-In-Time Compilation - [[JIT]])

    • Process: A hybrid approach combines elements of both compilation and interpretation. In JIT compilation, the source code is initially interpreted, but certain parts of the code are compiled into machine code during runtime for execution.
    • Advantages: JIT compilation can provide a balance between the speed of compiled languages and the flexibility of interpreted languages. It can optimize frequently executed code segments and adapt to runtime conditions.
    • Examples: [[Java]], [[C#]], and some versions of [[JavaScript]] (e.g., V8 engine) use JIT compilation. For instance, Java initially compiles source code into bytecode, which is then interpreted by the Java Virtual Machine ([[JVM]]), and later, frequently used code is compiled to native machine code for faster execution.## Syntax

1.5. Evaluation Criteria

![[Screenshot 2023-10-08 at 12.54.16 AM.png]]

2 . [[Paradigm]]

![[Screenshot 2023-10-08 at 1.03.57 AM.png]]

2.1 [[Imperative Programming]]

2.1.1 [[Procedural Programming]]

2.1.2 [[Object-Oriented Programming]]

2.2 [[Declarative Programming]]

2.2.1 [[Functional Programming]]

3 . [[Syntax]] & [Semantics]

3.1 Syntax

![[Screenshot 2023-10-09 at 11.35.49 PM.png|500]]

[!Definition]

  1. Syntax: Syntax refers to the set of rules that dictate how valid sentences or statements are structured in a programming language
  2. Tokens: Tokens are the smallest units of a programming language's syntax.
  3. Terminal: ~Symbols~ that appear in the source code and have no further productions or rules associated with them.
  4. . Nonterminal: ~Symbols~ in a formal grammar that can be replaced by a sequence of terminals and/or other nonterminals through production rules.
  5. CFG (Context-Free Grammar): a formal notation used to describe the syntax of a programming language or any formal language. It consists of a set of production rules that define how nonterminals can be replaced by other nonterminals and terminals.
  6. Rule: A rule in CFG specifies how a nonterminal can be replaced by a sequence of symbols (terminals and/or other nonterminals). A rule consists of a left-hand side (the nonterminal to be replaced) and a right-hand side (the sequence of symbols that replace it).

3.1.1 BNF

Nonterminal + Terminal + MetaSymbols

[!meta Symbols]
1. : := : (define)
2. | : (or)
3. <> : (nonterminal)

<if문> ::= if <논리식> then <문장> | if<논리식> then <문장> else <문장>
<식별자> ::= <letter> | <식별자><digit> | <식별자><letter> 
<letter> ::= A|B|C|D|...|Z||a|b|...|y||z|
<digit> ::= 0|1|2|3|4|5|6|7|8|9

<IF>::=IF<LOGICS>THEN<STATEMENTS><IF 문> ::= IF <LOGICS> THEN <STATEMENTS>

3.1.2 EBNF

[!Meta Symbols][] :(optional)
{} :(zero or more)
() :(or)
'' : (use meta symbols)

<if문> ::= if <논리식> then <문장> [else <문장>]
<identifier> ::= <letter>{<letter>|<digit>}
<unsigned integer> ::= <digit>{<digit>}
<expression> ::= <expression>(+|-|*|/|%)<expression>

3.1.3 Syntax Diagram

[!Units]
1. Square = Nonterminal
2. Circle = Terminal
3. Arrow = Rule

![[Screenshot 2023-11-17 at 9.17.25 PM.png]]

[ ]
![[Screenshot 2023-11-17 at 9.17.40 PM.png]]
( | | | )

![[Screenshot 2023-11-17 at 9.17.46 PM.png]]

{ }
![[Screenshot 2023-11-17 at 9.18.33 PM.png]]
{ | }

3.2 Semantics

자연어로 시작하긴했지만 형식 의미론이 개발됨

  1. 정적의미론 : 프로그래밍 수행하기전 의미가 맞는지 확인
    1. 속성 문법
  2. 동적의미론 : 수행 시 나타남
    1. 기능적 의미론
    2. 표기적 의미론
    3. 공리적의미론

3.2.1 Attribute Grammar

비단말기호마다의 타입 속성이 있다고 가정하여 규칙 설명

<선언> ::= <T><id><L>;
<T>:: = int|char
<L>::= <id><L> | Ɛ
id.t = T.t 
T.t = 정수 | 문자
L.t =T .t

3.2.2 Operational Sematics

기계의 상태의 변화를 표현

<수행할 명령어, 메모리상태>

< z=x; x=y ; y=z , [x->5,y->7,z->0] >
=> < x=y; y=z;, [x->5,y->7,z->5] >
=> < y=z; [x->7,y->7,z->5] >
=> < , [x->7,y->5,z->5] >

x 와 y 값 교환

3.2.3 Denotational Semantics

표기적 의미론

각 구문요소를 수학적 표기에 대응(의미함수)

<Binary> ::= 0 | 1 | <Binary>0 | <Binary>1
Bin[[0]]=0
Bin[[1]]=1
Bin[[B0]]=2*Bin[[B]]
Bin[[B1]]= 2*Bin[[B]] + 1

의미함수 Bin

3.2.4 Axiomatic Semantics

공리적 의미론

{P}S{Q}

4. Syntax Analysis

4.1 Lexical Analysis

Token 을 찾아내자

  1. reserved word
  2. identifier
  3. . ; ,
      • =
  4. ..

4.2 Syntax Analysis

유도가 가능한 프로그램 = 구문 규칙이 에러가없음

<exp>::= <exp> |<exp> (+|-|*|/) <exp>  | <digit>
<exp>
<exp>+<exp>
<exp>+<exp>*<exp>
<digit>+<digit>*<digit>
1+5*2

유도 ⇒ 문법 오류 x

4.2.1 Parse Tree

![[Screenshot 2023-11-18 at 3.46.43 AM.png]]
![[Screenshot 2023-11-18 at 3.47.34 AM.png]]

1+5*은 문법오류다

![[Screenshot 2023-11-18 at 3.49.05 AM.png]]

구문적으론 부합하지만 의미론적으로 다름

4.2.2 Ambiguity

  1. 연산자 우선순위
  2. 좌결합 연산자
  3. 중첩된 if 문의 else
<exp> ::= <exp>( + | - )<exp> | <term>
<term> ::= <term>( * | / )<term> | <factor>
<factor> :: = (<exp>) | <digit>

![[Screenshot 2023-11-18 at 3.54.08 AM.png]]

<exp> ::= <exp>( + | - )<term> | <term> 
<term> ::=<term>( * | / )<factor> | <factor>
<factor> ::= (<exp>) | <digit>

왼쪽부터 계산 좌결합 연산자

5 . Variable

Type + Identifier + Address + Value

![[Screenshot 2023-11-18 at 4.04.33 AM.png]]

배런의 표기법

5.1 Binding

변수명 → 타입 → 주소 → 값 순
바인딩 = 언어 구성요소의 속성이 결정됨
![[Screenshot 2023-11-18 at 4.07.36 AM.png]]

로드시점까지는 정적 바인딩
프로그램 수행시점은 동적 바인딩

Identifier Binding

  1. 명시적선언
    1. int x12;
  2. 묵시적선언
    1. k =123;

Type Binding

  1. 명시적선언
    1. int a =3
  2. 묵시적선언
    1. k=123

[!tip]
대부분 정적바인딩으로하나
파이썬같은 경우 동적바인딩됨 k=123; k='abc' → 프로그램 수행전에 타입 바인딩 불가능

Address Binding

주소 바인딩 = 할당(allocation)

[!tip]
변수의 수명은 변수가 메모리를 할당 받고있는기간

  1. 자동할당 : 명시적선언 + 묵시적선언 ⇒ Stack or Data

    1. int x= 3; ⇒ Stack + 동적바인딩
    2. static int x =3; ⇒ Data + 정적바인딩
  2. 수동할당 : 지정한 크기의 동적할당 ⇒ [[Memory Structure|Heap]]

    1. int *p = new int ⇒ Heap + 동적바인딩 + 동적(수동)할당
  3. 정적바인딩 ⇒ 로드시점에 전역/정적변수 저장하여 프로그램이 끝날때까지 유지

    1. 정적변수 : static
  4. 동적바인딩 ⇒ 실행 시점에 동적세그먼트(스택,힙) 의 주소를 바인딩

    1. 힙 동적변수 : 동적할당,동적타입바인딩in파이썬
    2. 스택 동적변수 : 지역변수

Value Binding

x=3;

5.2 Scope

수명의시작
1. 동적바인딩
2. 정적바인딩

scope = 실제로 사용할 수 있는 범위 수명 != 영역

  1. 지역변수 : 블록안에서 선언
  2. 자유변수 : 선언없는 대입
    1. 비지역변수 : 블록 밖에서 선언
    2. 오류 : 선언 없음
  3. 참조환경 : 사용할 수 있는 모든 변수의 모음
    ![[Screenshot 2023-11-19 at 1.44.36 AM.png]]

Scope Rule

변수의 참조 위치를 결정하는 법 (언어마다 다름)

Static Scope Rule

블록들의 정적 내포 관계이용

  1. 컴파일 타임에 변수나 함수의 유효범위를 정함
  2. C,C++,JAVA, PYTHON

![[Screenshot 2023-11-19 at 1.55.41 AM.png]]

Static Ancestor, Static Parent(가장가까운 정적조상)
![[Screenshot 2023-11-19 at 2.14.48 AM.png]]

#### Dynamic Scope Rule

서브프로그램의 호출 관계로 내포관계 정함

  1. 변수의 유효범위가 함수가 호출되는 순간 결정됨→ 잘사용안함
  2. BASH

![[Screenshot 2023-11-19 at 2.15.24 AM.png]]

Sub2를 호출한 Main의 A를 참조하게됨

Name Space

int i=0;
int main(){
	int i=5; // 영역 구멍 생성
	::i++; //1 영역연산자 -> 전역변수
	i++; //6 지역변수
}

5.3 Type

데이터 집합 + 연산 집합

  1. Strongly Typed : 타입 오류가 발생 x
    1. 명시적형변환만 가능
    2. Java
  2. Weakly Typed : 일부허용
    1. 묵시적형변환 명시적형변환 가능
    2. C
  3. Typeless : 타입 선언 x ⇒ python
  1. Primitive Type
    1. int float char bool
  2. User-Defined Type
    1. Array , Struct , Enum, Union
  3. Simple Type
  4. Structure Type

5.3.1 Simple Type

int

![[Screenshot 2023-11-19 at 2.26.40 AM.png]]

      • / %

char

float

![[Screenshot 2023-11-19 at 2.28.41 AM.png]]

bool

  1. {0,1}
  2. && || !

enum

    enum color {red, green, blue};
    color c = red;
    cout << blue << endl;//2
    cout << c << endl ; //0

5.3.2 Structure Type

Array

  1. 동질형 데이터의 모음
  2. 행우선 저장을 주로함

String

  1. 문자가 모인 집합

Associative Array Type

  1. 동질형 데이터의 모음 (순서없음)
  2. 키로 구분하여 키를 해싱하면 찾을수잇음
    ![[Screenshot 2023-11-19 at 2.49.46 AM.png]]
#include <map>
map<string, int> walk {{"monday", 1}, {"tuesday", 2},{"wednesday", 3}};
cout << walk["monday"] << endl;

Struct

  1. 다양한 데이터의모음
    ![[Screenshot 2023-11-19 at 2.53.32 AM.png]]
struct person {
char name[20];
int birth;
double height;
double weight;
};

Union

  1. 저장공간을 공유하는 데이터 모음
    ![[Screenshot 2023-11-19 at 2.57.33 AM.png]]
union uni{
	int i;
	char a;
	double f;
}

![[Screenshot 2023-11-19 at 3.01.58 AM.png]]

Pointer

  1. 주소 자체를 데이터로 저장
  2. 단순타입 복합 타입 모두가능
int *ptr;

Reference

  1. 타입이 저장된 주소 자체를 자신의 주소로 사용함 (alias)
int &a= b;

![[Screenshot 2023-11-19 at 3.01.52 AM.png]]

6 . Statement

6.1 Expression & Operator

연산자(함수) + 피연산자
f(피연산자) = 값
1. Expression : 하나의 값을 나타냄`

int f(){
	return 100;
} 

-5.3 // No Operator
i+3 // 두개의 Operand + Operator
"good" + "morning"
f()//No Operand - 100

![[Pasted image 20231120023256.png]]

6.1.1 Arithmetic Operator

R×RRR\times R → R
1. 묵시적 타입변환
1. 데이터 집합이 더 커지는 확대변환만 가능

7.5*4 // 7.5 * 4.0 = 확대변환 30.0
  1. 명시적 타입변환 Type Casting
    1. 확대 축소 둘다됨
(int)7.5*4 // 7 * 4 = 28 
7.5*(double)4 // 7.5*4.0 = 30.0

![[Screenshot 2023-11-20 at 2.31.48 AM.png]]
![[Screenshot 2023-11-20 at 2.32.09 AM.png]]

6.1.2 Relational Operator

R×RBR \times R → B

2>1

![[Screenshot 2023-11-20 at 2.43.59 AM.png]]

6.1.3 Logical Operator

B×BBB\times B → B

true && false

![[Screenshot 2023-11-20 at 2.47.24 AM.png]]

6.1.4 Assignment Operator

![[Screenshot 2023-11-20 at 2.56.59 AM.png]]

6.2 Statement

처리를 나타냄
문장은 ; 로 끝냄
1. 선언문 : 변수명 타입 바인딩
2. 실행문 : 데이터를 처리함
1. 대입문
2. 제어문
1. 조건문
2. 반복문

y = add(3,4);

6.2.1 Declaration

int y;
int add(int,int); //프로토콜

6.2.2 Assignment

A = B = C =5;

6.2.3 Control Statement

if y>3:
	y=10
	print(y)
else:
	y=0
	print(y)
for (i=0;i<100;i++){
	y+=i;
}

7 . Sub-Program

입력 + 출력을 갖춘 프로그램조각

  1. 하나의 입구 (Entry Point) → f( Entry )
  2. 1개이상의 출구 (Exit Point) → {Return}
  3. return이없으면 블록의 끝이 출구

SORTS
1. Function
1. 인수 o 반환 o
2. Procedure (void 함수)
1. 반환 x
3. SubRoutine
1. 인수 x 반환 x

7.1 Sub-Program

  1. When subproram is overloading ⇒ Signature helps you find the way
  2. Parameter Profile(Signature) ⇒ Parameter's Type, Counts , Order (Name x)
  3. Protocol(Prototype) ⇒ must be defined before a call
//Declaration
int hi (int); // Protocol (Prototype)

//Definition
int hi (int i){ // header
//body
}




hi(); // call

Declartion = Protocol = int hi (Profile);
Definition = Body + Header

7.2 Argument & Parameter

거의 구분 x

  1. Formal Parameter :

    1. int a (String s){}
  2. Actual Parameter :

    1. a("hey")
  3. Positional Correspondence

  4. Keyword Correspondence

  1. Default Argument
    1. void arr(int size=5, int* p){}
  2. Variadic Function
int sum(int ...ns){ // Variadic Arguments
		int s =0;
		for (int n :ns){
			
		}
}

7.3 Inheritance Model

인수 전달 모델들

7.3.1 Semantic model

In Mode

Out Mode

In-Out Mode

7.3.2 Conceptual Model

Call-By-Value

물리적으로 실인수값을 복사하여 전달

Call-By-Reference

실인수를 참조할 참조 경로를 전달

7.3.3 Implementation Model

Call-By-Value

  1. In-Mode 구현
  2. 값 복사에 따른 비효율성
  3. 별칭 문제가 안생김
  4. 포인터는 포인터 값을 복사하여 전달
int elem(Matrix m,int row, int col);
int elem(const Matrix* mp,int row,int col); //메모리아낌

Call-By-Result

  1. Out-Mode 구현
  2. 값 복사에 따른 비효율성
  3. 실인수의 주소값은 호출시에 결정
void sub(int &x,int &y){ // 흉내내는 것일뿐 실제로 지원안함
	x=2;
	y=3;
}
sub(a,b); //a,b에 대입

Call-By-Value-Result

  1. In-Out-Mode 구현
  2. 값 복사에 따른 비효율성

Call-By-Reference

  1. In-Out-Mode 구현
  2. 주소만 전달함으로 효율적
  3. 별칭문제가 생김(한 대상을 다른이름으로 지칭)
int Hypotenuse(int &a, int &b){
	a*=a
	b*=b
	return a+b; //a^2 + b^2
}
a=2
sqSum(a,a); // 32 aliasing problem

Call-By-Name

글자 그대로 치환

  1. 특정 의미적모델, 개념적 모델에 대응 안됨
procedure dobule(x);
	interger x;
begin
	x := x * 2
end;

i :=2;
double(i);
i:=2;
i:=i*2;
void swap(int a, int b){
	int temp = a;
	a = b;
	b = temp;
}
int main(){
	int list[3]={1,2,3};
	int i =0;
	swap(i,list[i]);
	return;
}

이 예제에서 swap 이 참조 전달(실인수 주소값이 이미 정해짐)인경우
스왑이 일어나나 이름 전달일경우 이상한 결과가 나온다.

7.4 Generic Sub-Program

범용 서브프로그램 : 여러타입을 다룰 수있는(polymorphism) 서브프로그램
C++ : Template , JAVA : Generic

Polymorphic Data Structure

#define MAX(a,b) (a>b?a:b)
int MAX(void* a, void* b){
    return *(float*)a > *(int*)b ? *(float*)a : *(int*)b;
}
int main(){
	float a = 13.0;
	int a = 14;
	MAX(a,b);
	return 0;
}

c언어 다형 서브프로그램

less<int>();

C++ 다형서브프로그램 : 템플릿

7.4 Separate & Independent Compilation

  1. 분리 컴파일 : 인터페이스 정보를 이용하여 프로그램 일부 컴파일
  2. 독립 컴파일 : 인터페이스 정보없이 프로그램을 분리시켜 컴파일
    C++ 은 독립 컴파일 지원
int printf(const char *s,...);
int main(){
	printf("hello");
	return 0;
}

<stdio.h>없이도 아무문제없이 컴파일가능

7.5 Implementation

profile
Cloud Security, Pentesting, AWS

0개의 댓글