Skills DirectorySkills Directory
SkillsLearnSecurityCategoriesDocsCommunityBlog
Sign InSubmit Skill
Skills Directory

Security-tested agent skills for Claude, coding agents, and AI workflows.

Directory

  • Browse Skills
  • All Skills A–Z
  • Claude Skills
  • Claude Code Skills
  • Agent Skills
  • Categories
  • Submit a Skill

Learn

  • Learn Hub
  • Install Claude Skills
  • Write SKILL.md
  • Skills vs MCP
  • Directories Compared

Security

  • Security
  • Methodology
  • Secure Claude Skills
  • Security Badges

Company

  • About
  • Community
  • Blog
  • API Docs
  • Advertise

2026 Skills Directory. All rights reserved.

Back to skills

Compiler Frontend

ASecurity

Use when building a lexer, Pratt or recursive-descent parser, AST, symbol table, type checker, or LLVM IR emitter for a language or DSL. Not for optimizing IR: use llvm-passes.

54 stars
0 votes
0 copies
0 views
Added 9/20/2026
developmentrustgonodeexpressgitapifrontend

Works with

terminalapi

Security Analysis

A100/100

Scanned 9/20/2026

Install to Claude Code

$npx -y skills add OutlineDriven/outline-driven-development --skill compiler-frontend --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Compiler Frontend?

Add the live security badge to your README — it updates automatically with every re-scan.

Security grade badge for Compiler Frontend
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/outlinedriven-compiler-frontend-outline-driven-development/badge)](https://www.skillsdirectory.com/skills/outlinedriven-compiler-frontend-outline-driven-development)

More formats (shields.io, HTML) on the badges page.

Download Zip
Files
SKILL.md
---
name: compiler-frontend
description: 'Use when building a lexer, Pratt or recursive-descent parser, AST, symbol table, type checker, or LLVM IR emitter for a language or DSL. Not for optimizing IR: use llvm-passes.'
---

# Compiler frontend

## Contract

| Field | Bound contract |
|---|---|
| Trigger | A user implements a language or DSL, adds expression parsing to an interpreter or config format, designs AST nodes in C or Rust, needs scoped symbols, basic type checking, error recovery, or wants a typed AST lowered to LLVM IR. |
| Authority | Reversible local: writes only the frontend source files the user names inside the project; rollback is version control. No remote mutation. |
| Side effect | Frontend source files are created or edited; a test input is lexed, parsed, checked, and, when requested, emitted as IR and verified. |
| Done | Each requested stage compiles, runs on the supplied test inputs, and the verification named for that stage passes: token stream matches, precedence tests pass, undefined and mismatched types are reported, generated IR passes the LLVM verifier. |

## Inputs

1. Language description (required): the token set, the grammar or a set of example programs, and the operators with their precedence and associativity.
2. Implementation language (required): C or Rust. C samples below use the LLVM C API in `llvm-c/`; in Rust use the `inkwell` or `llvm-sys` crates.
3. Requested stages (required): any subset of lexer, parser, symbol table, type checker, IR emitter.
4. Test inputs (required): at least one valid program per stage and one program with an error the stage must report.

## Procedure

1. Fix the pipeline: source to lexer (tokens) to parser (AST) to type checker to IR generator to LLVM IR. Write down which stages this task delivers. Done when: the delivered stages and their input and output types are listed.
2. Write the lexer as a hand-written state machine. Tokens carry a kind, a pointer into the source, a length, and any literal value. Skip whitespace, then dispatch on the first character: digits build an integer, letters build an identifier, single characters map to punctuation.

   ```c
   typedef enum { TOK_EOF, TOK_INT, TOK_IDENT, TOK_PLUS, TOK_MINUS,
                  TOK_LPAREN, TOK_RPAREN, TOK_SEMI, TOK_EQ, TOK_RETURN } TokenKind;

   typedef struct { TokenKind kind; const char *start; int length; int64_t int_val; } Token;
   typedef struct { const char *src; int pos; int line; } Lexer;

   Token lexer_next(Lexer *l) {
       while (l->src[l->pos] == ' ' || l->src[l->pos] == '\n') l->pos++;
       const char *start = &l->src[l->pos];
       if (isdigit((unsigned char)l->src[l->pos])) {
           int64_t val = 0;
           while (isdigit((unsigned char)l->src[l->pos]))
               val = val * 10 + (l->src[l->pos++] - '0');
           return (Token){ TOK_INT, start, (int)(&l->src[l->pos] - start), val };
       }
       if (isalpha((unsigned char)l->src[l->pos])) {
           while (isalnum((unsigned char)l->src[l->pos])) l->pos++;
           return (Token){ TOK_IDENT, start, (int)(&l->src[l->pos] - start), 0 };
       }
       switch (l->src[l->pos++]) {
           case '+': return (Token){ TOK_PLUS, start, 1, 0 };
           case '(': return (Token){ TOK_LPAREN, start, 1, 0 };
           case ')': return (Token){ TOK_RPAREN, start, 1, 0 };
           case ';': return (Token){ TOK_SEMI, start, 1, 0 };
           default:  return (Token){ TOK_EOF, start, 0, 0 };
       }
   }
   ```

   A generated lexer is the alternative when the token set is large: `flex lexer.l && gcc -o lexer lex.yy.c -lfl`. With flex, order rules so the longest match wins and keywords precede the identifier rule. Done when: every test input produces the expected token stream, including the EOF token.
3. Parse expressions with a Pratt parser. Each infix operator has a left and a right binding power; a higher power binds tighter, and right associativity is a right power one below the left. The loop consumes operators while their left power is at least the minimum.

   ```c
   typedef enum { AST_INT, AST_BINOP, AST_VAR } AstKind;
   typedef struct AstNode {
       AstKind kind;
       union {
           int64_t int_val;
           struct { int op; struct AstNode *lhs, *rhs; } binop;
           char *name;
       };
   } AstNode;

   enum { BP_NONE = 0, BP_SUM = 10, BP_PRODUCT = 20 };

   AstNode *parse_expression(Parser *p, int min_bp) {
       AstNode *left = parse_prefix(p);
       for (;;) {
           int lbp, rbp;
           if (!infix_binding_power(p->cur.kind, &lbp, &rbp) || lbp < min_bp) break;
           int op = p->cur.kind;
           advance(p);
           AstNode *right = parse_expression(p, rbp);
           left = make_binop(op, left, right);
       }
       return left;
   }
   ```

   Capture the operator before `advance`; reading `p->cur.kind` after the recursive call returns the wrong token. Done when: a table of expressions with expected trees passes, including mixed precedence and associativity cases.
4. Parse statements with recursive descent, one function per nonterminal. Every branch must consume at least one token or return; a branch that neither advances nor returns is the cause of an infinite loop.

   ```c
   AstNode *parse_statement(Parser *p) {
       if (p->cur.kind == TOK_IDENT && peek(p) == TOK_EQ) {
           char *name = take_ident(p);
           advance(p);
           AstNode *expr = parse_expression(p, BP_NONE);
           expect(p, TOK_SEMI);
           return make_assign(name, expr);
       }
       if (match(p, TOK_RETURN)) {
           AstNode *expr = parse_expression(p, BP_NONE);
           expect(p, TOK_SEMI);
           return make_return(expr);
       }
       return parse_expression_statement(p);
   }
   ```

   Done when: every statement form in the test inputs parses and every branch is audited for token progress.
5. Build the symbol table as a chain of scopes. Lookup walks from the innermost scope to the root; definition writes only into the current scope, so shadowing an outer name is allowed and redefining a name in the same scope is an error.

   ```c
   typedef struct Symbol { char *name; Type *type; LLVMValueRef llvm_val; struct Symbol *next; } Symbol;
   typedef struct Scope { Symbol *symbols; struct Scope *parent; } Scope;

   Symbol *scope_lookup(Scope *s, const char *name) {
       for (Scope *cur = s; cur; cur = cur->parent)
           for (Symbol *sym = cur->symbols; sym; sym = sym->next)
               if (strcmp(sym->name, name) == 0) return sym;
       return NULL;
   }

   void scope_define(Scope *s, const char *name, Type *type) {
       Symbol *sym = malloc(sizeof *sym);
       if (!sym) abort();
       sym->name = strdup(name); sym->type = type; sym->llvm_val = NULL;
       sym->next = s->symbols; s->symbols = sym;
   }
   ```

   Replace the linked list with a hash map when scopes hold more than a few dozen names. Done when: shadowing resolves to the inner name and a same-scope duplicate is rejected.
6. Type-check by walking the AST and returning a type per node. Integers have the integer type; a variable takes its symbol's type or reports "undefined"; a binary operation requires equal operand types.

   ```c
   Type *check_expr(Scope *s, AstNode *node) {
       switch (node->kind) {
       case AST_INT: return type_int();
       case AST_VAR: {
           Symbol *sym = scope_lookup(s, node->name);
           if (!sym) error("undefined variable %s", node->name);
           return sym->type;
       }
       case AST_BINOP: {
           Type *lt = check_expr(s, node->binop.lhs);
           Type *rt = check_expr(s, node->binop.rhs);
           if (!type_equal(lt, rt)) error("type mismatch in binary op");
           return lt;
       }
       }
       return type_void();
   }
   ```

   For an ML-style language with inference, assign a type variable to each unknown and unify on constraints (Hindley-Milner); this is a separate stage, not a change to the checker above. Done when: each error test input produces the expected diagnostic and valid inputs pass.
7. Recover from syntax errors with panic mode: on error, advance until a synchronizing token, then resume. Pick the synchronizing set per nonterminal (statement end `;`, block end `}`, statement-start keywords).

   ```c
   void synchronize(Parser *p) {
       advance(p);
       while (p->cur.kind != TOK_EOF) {
           if (p->prev.kind == TOK_SEMI) return;
           if (p->cur.kind == TOK_RETURN || p->cur.kind == TOK_IDENT) return;
           advance(p);
       }
   }
   ```

   Error productions for common mistakes and single-token insertion or deletion are the next steps when the frontend serves an editor. Done when: an input with two independent errors reports both, not a cascade from the first.
8. Emit LLVM IR from the typed AST through the C API. Create types from a context, build instructions through a builder, and use the typed load: the untyped `LLVMBuildLoad` is gone from the current C API (LLVM 23.1.0) and `LLVMInt32Type()` without a context is deprecated.

   ```c
   #include <llvm-c/Core.h>
   #include <llvm-c/Analysis.h>

   LLVMContextRef ctx; LLVMModuleRef module; LLVMBuilderRef builder;

   LLVMValueRef codegen_expr(Scope *s, AstNode *node) {
       switch (node->kind) {
       case AST_INT:
           return LLVMConstInt(LLVMInt32TypeInContext(ctx), (unsigned long long)node->int_val, 1);
       case AST_BINOP: {
           LLVMValueRef l = codegen_expr(s, node->binop.lhs);
           LLVMValueRef r = codegen_expr(s, node->binop.rhs);
           if (node->binop.op == TOK_PLUS) return LLVMBuildAdd(builder, l, r, "add");
           break;
       }
       case AST_VAR: {
           Symbol *sym = scope_lookup(s, node->name);
           return LLVMBuildLoad2(builder, LLVMInt32TypeInContext(ctx), sym->llvm_val, node->name);
       }
       }
       return NULL;
   }
   ```

   After emitting, dump and verify: `LLVMDumpModule(module);` and `LLVMVerifyModule(module, LLVMReturnStatusAction, &err);` where `LLVMVerifyModule` is declared in `llvm-c/Analysis.h`. Done when: the verifier returns success on every valid test input.

## Failure and recovery

| Failure class | Behavior |
|---|---|
| Parser loops forever | A branch consumed no token. Audit every branch of the failing nonterminal for `advance` or `return`; add the missing progress. |
| Wrong precedence | Binding powers are wrong. Fix the table and re-run the expression table test. |
| Duplicate symbol accepted or shadowing rejected | Lookup and define use the wrong scope. Lookup walks parents; define writes the current scope only. |
| LLVM verifier fails | An IR type mismatch, usually signedness, pointer level, or a load with the wrong type argument. Read the verifier message; fix the emitter for that node kind. |
| flex token clash | Overlapping patterns. Rely on longest match and order keyword rules before the identifier rule. |
| Error cascade | No synchronization. Implement panic-mode recovery per step 7. |

No partial result is claimed complete. If a stage cannot finish, the report states which stages passed their verification and which are blocked.

## Output

A frontend delivery containing:
1. Files written: each source file created or edited, per stage.
2. Verification: per stage, the test inputs run and the observed token stream, tree, diagnostic, or verifier result.
3. Open decisions: any grammar ambiguity or type rule the language description left undefined, with the choice made.

Attribution

OutlineDrivenOutlineDriven
View sourceMore from OutlineDriven →
SSkills DirectorySkills Directory

Your tool, in front of Claude Code builders.

3 founder slots · $299/mo · GSC-verified traffic · sponsors can never buy grades.

See placements

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments (0)

No comments yet. Be the first to comment!

SSkills DirectorySkills Directory

Your tool, in front of Claude Code builders.

3 founder slots · $299/mo · GSC-verified traffic · sponsors can never buy grades.

See placements

Related Skills

Browser Extension Developer

Use this skill when developing or maintaining browser extension code in the `browser/` directory, including Chrome/Firefox/Edge compatibility, content scripts, background scripts, or i18n updates.

281612 votes

Seo Optimizer

SEO optimization with keyword analysis, readability assessment, technical validation, content quality. Use for search rankings, blog posts, content audits, or encountering keyword density, readability scores, meta tags, schema markup errors.

2132 votes

Google Official Seo Guide

Official Google SEO guide covering search optimization, best practices, Search Console, crawling, indexing, and improving website search visibility based on official Google documentation

1862 votes

Tanstack Start

Build a full-stack TanStack Start app on Cloudflare Workers from scratch — SSR, file-based routing, server functions, D1+Drizzle, better-auth, Tailwind v4+shadcn/ui. Use whenever the user mentions TanStack Start, asks to scaffold a full-stack Cloudflare app with SSR, wants an SSR dashboard, or asks for a React 19 + Cloudflare Workers app with file-based routing and server functions — even if they don't name TanStack Start specifically. No template repo — Claude generates every file fresh per ...

9881 votes

Pentest

PTES-aligned adversarial security audit for backend, frontend, and mobile applications. Produces a CVSS-scored Hacker Report with verified PoCs and phased remediation.

5491 votes
View all in development →