language-design
Use when designing language features - covers lexer, parser, AST, and interpreter patterns
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
메뉴
Use when designing language features - covers lexer, parser, AST, and interpreter patterns
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
SOC 직업 분류 기준
Use when configuring ESLint - covers flat config, TypeScript integration, and custom rules
Use when creating GitHub Actions workflows - covers CI/CD, matrix testing, and release automation
Use when writing Jest tests - covers testing patterns for interpreters, parsers, and async code
Use when implementing Language Server Protocol features - covers completions, hover, diagnostics, and navigation
Use when creating Mermaid diagrams - covers flowcharts, sequence diagrams, and AST visualization
Use when publishing npm packages - covers package.json configuration, versioning, and provenance
| name | language-design |
| description | Use when designing language features - covers lexer, parser, AST, and interpreter patterns |
Source Code → Lexer → Tokens → Parser → AST → Interpreter → Result
enum TokenType {
// Literals
NUMBER, STRING, IDENTIFIER,
// Keywords
LET, IF, ELSE, RETURN,
// Operators
PLUS, MINUS, STAR, SLASH,
PIPE, // />
// Delimiters
LPAREN, RPAREN, LBRACE, RBRACE,
// Special
EOF, NEWLINE,
}
class Lexer {
private source: string;
private pos = 0;
private line = 1;
private column = 1;
nextToken(): Token {
this.skipWhitespace();
if (this.isAtEnd()) return this.makeToken(TokenType.EOF);
const char = this.advance();
if (this.isDigit(char)) return this.number();
if (this.isAlpha(char)) return this.identifier();
if (char === '"') return this.string();
// Operators
switch (char) {
case '+': return this.makeToken(TokenType.PLUS);
case '/':
if (this.match('>')) return this.makeToken(TokenType.PIPE);
return this.makeToken(TokenType.SLASH);
}
throw new LexerError(`Unexpected character: ${char}`, this.line, this.column);
}
}
class Parser {
private tokens: Token[];
private current = 0;
parse(): Program {
const statements: Stmt[] = [];
while (!this.isAtEnd()) {
statements.push(this.statement());
}
return { type: "Program", body: statements };
}
// Precedence climbing
private expression(): Expr {
return this.pipe();
}
private pipe(): Expr {
let left = this.equality();
while (this.match(TokenType.PIPE)) {
const right = this.equality();
left = { type: "PipeExpr", left, right };
}
return left;
}
private equality(): Expr {
let left = this.comparison();
while (this.match(TokenType.EQEQ, TokenType.NEQ)) {
const op = this.previous().type;
const right = this.comparison();
left = { type: "BinaryExpr", op, left, right };
}
return left;
}
// Continue down precedence...
}
1. Ternary ? : (lowest)
2. Equality == !=
3. Comparison < > <= >=
4. Term + - ++
5. Factor * / %
6. Pipe />
7. Unary -
8. Call fn()
9. Primary literals (highest)
type Expr =
| { type: "NumberLiteral"; value: number; line: number }
| { type: "StringLiteral"; value: string; line: number }
| { type: "Identifier"; name: string; line: number }
| { type: "BinaryExpr"; op: string; left: Expr; right: Expr; line: number }
| { type: "PipeExpr"; left: Expr; right: Expr; line: number }
| { type: "CallExpr"; callee: Expr; args: Expr[]; line: number };
type Stmt =
| { type: "LetStmt"; name: string; value: Expr; line: number }
| { type: "ExprStmt"; expression: Expr; line: number };
class Interpreter {
private env = new Environment();
evaluate(expr: Expr): Value {
switch (expr.type) {
case "NumberLiteral":
return expr.value;
case "BinaryExpr":
const left = this.evaluate(expr.left);
const right = this.evaluate(expr.right);
return this.applyOperator(expr.op, left, right);
case "PipeExpr":
const value = this.evaluate(expr.left);
const fn = this.evaluate(expr.right);
return this.call(fn, [value]);
case "Identifier":
return this.env.get(expr.name);
}
}
}
class Environment {
private values = new Map<string, Value>();
private parent?: Environment;
constructor(parent?: Environment) {
this.parent = parent;
}
define(name: string, value: Value): void {
this.values.set(name, value);
}
get(name: string): Value {
if (this.values.has(name)) return this.values.get(name)!;
if (this.parent) return this.parent.get(name);
throw new RuntimeError(`Undefined variable: ${name}`);
}
}