Latest commit

History

533 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

compiler-in-python

In this project we will try to build a compiler using Python and some powerful libraries.

Compilers

A compiler can be any program that translates one text into another. Since a computer can only read 1s and 0s, and humans write better Code than they do binary, compilers were made to turn that human-readable text into computer-readable machine code.

Compilers take source code and produce binary. They have several steps of processing to do before their programs are runnable:

  1. Reads the individual characters of the source code you give it.
  2. Sorts the characters into words, numbers, symbols, and operators. (These are called Tokens)
  3. Takes the sorted characters and determines the operations they are trying to perform by matching them against patterns, and making a tree of the operations.
  4. Iterates over evry operation in the tree made in the last step, and finally, generates the equivalent binary.

Our compiler can be divided intro three components:

  • Lexer
  • Parser
  • Code Generator

For the Lexer and Parser we’ll be using RPLY, really similar to PLY: a Python library with lexical and parsing tools, but with a better API. And for the Code Generator, we’ll use LLVMlite, a Python library for binding LLVM components. Using LLVM, it is possible to optimize your compilation without learning compiling optimization, and LLVMLite it´s a really good library to work with compilers.

alt text

How to run this project

  1. Clone the project
git clone https://github.com/Pishgard/compiler-in-python.git
  1. Make sure you are in compiler-in-python folder
cd compiler-in-python
  1. Install all dependencies
pip install -r requirements.txt
  1. Run Main
python main.py

Lexical Analysis

The first step is to split the input up character by character. This step is called Lexical Analysis or Tokenization. The major idea is that we group characters together to form our words, identifiers, symbols, and more.

alt text

We use minimal structures to define or tokens, for example:

print(4 + 4 - 2);

Our Lexer would divide this string into this list of Tokens

TOKEN('PRINT','print')
TOKEN('OPEN_PAREN','\(')
TOKEN('NUMBER','4')
TOKEN('SUM','+')
TOKEN('NUMBER','4')
TOKEN('SUB','-')
TOKEN('NUMBER','2')
TOKEN('SEMI_COLON',';')

Parser

Parsing, syntax analysis, or syntactic analysis is the process of analysing a string of symbols, either in natural language, computer languages or data structures, conforming to the rules of a formal grammar. That´s why our second component in our compiler is the Parser. It will take the list of tokens as input and create a AST as output.

alt text

Inside an ast.py file in which we put all clases that are going to be called on the Parser and create the AST. For example: class Number(), class BinaryOp(), class Sum(), class Sub(), class Mul(), class Div(), class Mod(), class Print().

Next we need to create the parser, in which we’ll use ParserGenerator from RPLY inside a file name parser.py. And finally, we’ll update our file main.py to combine Parser with Lexer.

We’ll see the output being the result of print(4 + 4 — 2), which is equal to printing 6. With these two components, we have a functional compiler that interprets our own language with Python. However, it still doesn’t create a machine language code and is not well optimized. To do this, we’ll need the most complex part of the compiler, code generation with LLVM.

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Latest commit

History

533 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

compiler-in-python

In this project we will try to build a compiler using Python and some powerful libraries.

Compilers

A compiler can be any program that translates one text into another. Since a computer can only read 1s and 0s, and humans write better Code than they do binary, compilers were made to turn that human-readable text into computer-readable machine code.

Compilers take source code and produce binary. They have several steps of processing to do before their programs are runnable:

  1. Reads the individual characters of the source code you give it.
  2. Sorts the characters into words, numbers, symbols, and operators. (These are called Tokens)
  3. Takes the sorted characters and determines the operations they are trying to perform by matching them against patterns, and making a tree of the operations.
  4. Iterates over evry operation in the tree made in the last step, and finally, generates the equivalent binary.

Our compiler can be divided intro three components:

  • Lexer
  • Parser
  • Code Generator

For the Lexer and Parser we’ll be using RPLY, really similar to PLY: a Python library with lexical and parsing tools, but with a better API. And for the Code Generator, we’ll use LLVMlite, a Python library for binding LLVM components. Using LLVM, it is possible to optimize your compilation without learning compiling optimization, and LLVMLite it´s a really good library to work with compilers.

alt text

How to run this project

  1. Clone the project
git clone https://github.com/Pishgard/compiler-in-python.git
  1. Make sure you are in compiler-in-python folder
cd compiler-in-python
  1. Install all dependencies
pip install -r requirements.txt
  1. Run Main
python main.py

Lexical Analysis

The first step is to split the input up character by character. This step is called Lexical Analysis or Tokenization. The major idea is that we group characters together to form our words, identifiers, symbols, and more.

alt text

We use minimal structures to define or tokens, for example:

print(4 + 4 - 2);

Our Lexer would divide this string into this list of Tokens

TOKEN('PRINT','print')
TOKEN('OPEN_PAREN','\(')
TOKEN('NUMBER','4')
TOKEN('SUM','+')
TOKEN('NUMBER','4')
TOKEN('SUB','-')
TOKEN('NUMBER','2')
TOKEN('SEMI_COLON',';')

Parser

Parsing, syntax analysis, or syntactic analysis is the process of analysing a string of symbols, either in natural language, computer languages or data structures, conforming to the rules of a formal grammar. That´s why our second component in our compiler is the Parser. It will take the list of tokens as input and create a AST as output.

alt text

Inside an ast.py file in which we put all clases that are going to be called on the Parser and create the AST. For example: class Number(), class BinaryOp(), class Sum(), class Sub(), class Mul(), class Div(), class Mod(), class Print().

Next we need to create the parser, in which we’ll use ParserGenerator from RPLY inside a file name parser.py. And finally, we’ll update our file main.py to combine Parser with Lexer.

We’ll see the output being the result of print(4 + 4 — 2), which is equal to printing 6. With these two components, we have a functional compiler that interprets our own language with Python. However, it still doesn’t create a machine language code and is not well optimized. To do this, we’ll need the most complex part of the compiler, code generation with LLVM.

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Latest commit

History

533 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

compiler-in-python

In this project we will try to build a compiler using Python and some powerful libraries.

Compilers

A compiler can be any program that translates one text into another. Since a computer can only read 1s and 0s, and humans write better Code than they do binary, compilers were made to turn that human-readable text into computer-readable machine code.

Compilers take source code and produce binary. They have several steps of processing to do before their programs are runnable:

  1. Reads the individual characters of the source code you give it.
  2. Sorts the characters into words, numbers, symbols, and operators. (These are called Tokens)
  3. Takes the sorted characters and determines the operations they are trying to perform by matching them against patterns, and making a tree of the operations.
  4. Iterates over evry operation in the tree made in the last step, and finally, generates the equivalent binary.

Our compiler can be divided intro three components:

  • Lexer
  • Parser
  • Code Generator

For the Lexer and Parser we’ll be using RPLY, really similar to PLY: a Python library with lexical and parsing tools, but with a better API. And for the Code Generator, we’ll use LLVMlite, a Python library for binding LLVM components. Using LLVM, it is possible to optimize your compilation without learning compiling optimization, and LLVMLite it´s a really good library to work with compilers.

alt text

How to run this project

  1. Clone the project
git clone https://github.com/Pishgard/compiler-in-python.git
  1. Make sure you are in compiler-in-python folder
cd compiler-in-python
  1. Install all dependencies
pip install -r requirements.txt
  1. Run Main
python main.py

Lexical Analysis

The first step is to split the input up character by character. This step is called Lexical Analysis or Tokenization. The major idea is that we group characters together to form our words, identifiers, symbols, and more.

alt text

We use minimal structures to define or tokens, for example:

print(4 + 4 - 2);

Our Lexer would divide this string into this list of Tokens

TOKEN('PRINT','print')
TOKEN('OPEN_PAREN','\(')
TOKEN('NUMBER','4')
TOKEN('SUM','+')
TOKEN('NUMBER','4')
TOKEN('SUB','-')
TOKEN('NUMBER','2')
TOKEN('SEMI_COLON',';')

Parser

Parsing, syntax analysis, or syntactic analysis is the process of analysing a string of symbols, either in natural language, computer languages or data structures, conforming to the rules of a formal grammar. That´s why our second component in our compiler is the Parser. It will take the list of tokens as input and create a AST as output.

alt text

Inside an ast.py file in which we put all clases that are going to be called on the Parser and create the AST. For example: class Number(), class BinaryOp(), class Sum(), class Sub(), class Mul(), class Div(), class Mod(), class Print().

Next we need to create the parser, in which we’ll use ParserGenerator from RPLY inside a file name parser.py. And finally, we’ll update our file main.py to combine Parser with Lexer.

We’ll see the output being the result of print(4 + 4 — 2), which is equal to printing 6. With these two components, we have a functional compiler that interprets our own language with Python. However, it still doesn’t create a machine language code and is not well optimized. To do this, we’ll need the most complex part of the compiler, code generation with LLVM.

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Latest commit

History

533 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

compiler-in-python

In this project we will try to build a compiler using Python and some powerful libraries.

Compilers

A compiler can be any program that translates one text into another. Since a computer can only read 1s and 0s, and humans write better Code than they do binary, compilers were made to turn that human-readable text into computer-readable machine code.

Compilers take source code and produce binary. They have several steps of processing to do before their programs are runnable:

  1. Reads the individual characters of the source code you give it.
  2. Sorts the characters into words, numbers, symbols, and operators. (These are called Tokens)
  3. Takes the sorted characters and determines the operations they are trying to perform by matching them against patterns, and making a tree of the operations.
  4. Iterates over evry operation in the tree made in the last step, and finally, generates the equivalent binary.

Our compiler can be divided intro three components:

  • Lexer
  • Parser
  • Code Generator

For the Lexer and Parser we’ll be using RPLY, really similar to PLY: a Python library with lexical and parsing tools, but with a better API. And for the Code Generator, we’ll use LLVMlite, a Python library for binding LLVM components. Using LLVM, it is possible to optimize your compilation without learning compiling optimization, and LLVMLite it´s a really good library to work with compilers.

alt text

How to run this project

  1. Clone the project
git clone https://github.com/Pishgard/compiler-in-python.git
  1. Make sure you are in compiler-in-python folder
cd compiler-in-python
  1. Install all dependencies
pip install -r requirements.txt
  1. Run Main
python main.py

Lexical Analysis

The first step is to split the input up character by character. This step is called Lexical Analysis or Tokenization. The major idea is that we group characters together to form our words, identifiers, symbols, and more.

alt text

We use minimal structures to define or tokens, for example:

print(4 + 4 - 2);

Our Lexer would divide this string into this list of Tokens

TOKEN('PRINT','print')
TOKEN('OPEN_PAREN','\(')
TOKEN('NUMBER','4')
TOKEN('SUM','+')
TOKEN('NUMBER','4')
TOKEN('SUB','-')
TOKEN('NUMBER','2')
TOKEN('SEMI_COLON',';')

Parser

Parsing, syntax analysis, or syntactic analysis is the process of analysing a string of symbols, either in natural language, computer languages or data structures, conforming to the rules of a formal grammar. That´s why our second component in our compiler is the Parser. It will take the list of tokens as input and create a AST as output.

alt text

Inside an ast.py file in which we put all clases that are going to be called on the Parser and create the AST. For example: class Number(), class BinaryOp(), class Sum(), class Sub(), class Mul(), class Div(), class Mod(), class Print().

Next we need to create the parser, in which we’ll use ParserGenerator from RPLY inside a file name parser.py. And finally, we’ll update our file main.py to combine Parser with Lexer.

We’ll see the output being the result of print(4 + 4 — 2), which is equal to printing 6. With these two components, we have a functional compiler that interprets our own language with Python. However, it still doesn’t create a machine language code and is not well optimized. To do this, we’ll need the most complex part of the compiler, code generation with LLVM.

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Latest commit

History

533 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

compiler-in-python

In this project we will try to build a compiler using Python and some powerful libraries.

Compilers

A compiler can be any program that translates one text into another. Since a computer can only read 1s and 0s, and humans write better Code than they do binary, compilers were made to turn that human-readable text into computer-readable machine code.

Compilers take source code and produce binary. They have several steps of processing to do before their programs are runnable:

  1. Reads the individual characters of the source code you give it.
  2. Sorts the characters into words, numbers, symbols, and operators. (These are called Tokens)
  3. Takes the sorted characters and determines the operations they are trying to perform by matching them against patterns, and making a tree of the operations.
  4. Iterates over evry operation in the tree made in the last step, and finally, generates the equivalent binary.

Our compiler can be divided intro three components:

  • Lexer
  • Parser
  • Code Generator

For the Lexer and Parser we’ll be using RPLY, really similar to PLY: a Python library with lexical and parsing tools, but with a better API. And for the Code Generator, we’ll use LLVMlite, a Python library for binding LLVM components. Using LLVM, it is possible to optimize your compilation without learning compiling optimization, and LLVMLite it´s a really good library to work with compilers.

alt text

How to run this project

  1. Clone the project
git clone https://github.com/Pishgard/compiler-in-python.git
  1. Make sure you are in compiler-in-python folder
cd compiler-in-python
  1. Install all dependencies
pip install -r requirements.txt
  1. Run Main
python main.py

Lexical Analysis

The first step is to split the input up character by character. This step is called Lexical Analysis or Tokenization. The major idea is that we group characters together to form our words, identifiers, symbols, and more.

alt text

We use minimal structures to define or tokens, for example:

print(4 + 4 - 2);

Our Lexer would divide this string into this list of Tokens

TOKEN('PRINT','print')
TOKEN('OPEN_PAREN','\(')
TOKEN('NUMBER','4')
TOKEN('SUM','+')
TOKEN('NUMBER','4')
TOKEN('SUB','-')
TOKEN('NUMBER','2')
TOKEN('SEMI_COLON',';')

Parser

Parsing, syntax analysis, or syntactic analysis is the process of analysing a string of symbols, either in natural language, computer languages or data structures, conforming to the rules of a formal grammar. That´s why our second component in our compiler is the Parser. It will take the list of tokens as input and create a AST as output.

alt text

Inside an ast.py file in which we put all clases that are going to be called on the Parser and create the AST. For example: class Number(), class BinaryOp(), class Sum(), class Sub(), class Mul(), class Div(), class Mod(), class Print().

Next we need to create the parser, in which we’ll use ParserGenerator from RPLY inside a file name parser.py. And finally, we’ll update our file main.py to combine Parser with Lexer.

We’ll see the output being the result of print(4 + 4 — 2), which is equal to printing 6. With these two components, we have a functional compiler that interprets our own language with Python. However, it still doesn’t create a machine language code and is not well optimized. To do this, we’ll need the most complex part of the compiler, code generation with LLVM.

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Latest commit

History

533 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

compiler-in-python

In this project we will try to build a compiler using Python and some powerful libraries.

Compilers

A compiler can be any program that translates one text into another. Since a computer can only read 1s and 0s, and humans write better Code than they do binary, compilers were made to turn that human-readable text into computer-readable machine code.

Compilers take source code and produce binary. They have several steps of processing to do before their programs are runnable:

  1. Reads the individual characters of the source code you give it.
  2. Sorts the characters into words, numbers, symbols, and operators. (These are called Tokens)
  3. Takes the sorted characters and determines the operations they are trying to perform by matching them against patterns, and making a tree of the operations.
  4. Iterates over evry operation in the tree made in the last step, and finally, generates the equivalent binary.

Our compiler can be divided intro three components:

  • Lexer
  • Parser
  • Code Generator

For the Lexer and Parser we’ll be using RPLY, really similar to PLY: a Python library with lexical and parsing tools, but with a better API. And for the Code Generator, we’ll use LLVMlite, a Python library for binding LLVM components. Using LLVM, it is possible to optimize your compilation without learning compiling optimization, and LLVMLite it´s a really good library to work with compilers.

alt text

How to run this project

  1. Clone the project
git clone https://github.com/Pishgard/compiler-in-python.git
  1. Make sure you are in compiler-in-python folder
cd compiler-in-python
  1. Install all dependencies
pip install -r requirements.txt
  1. Run Main
python main.py

Lexical Analysis

The first step is to split the input up character by character. This step is called Lexical Analysis or Tokenization. The major idea is that we group characters together to form our words, identifiers, symbols, and more.

alt text

We use minimal structures to define or tokens, for example:

print(4 + 4 - 2);

Our Lexer would divide this string into this list of Tokens

TOKEN('PRINT','print')
TOKEN('OPEN_PAREN','\(')
TOKEN('NUMBER','4')
TOKEN('SUM','+')
TOKEN('NUMBER','4')
TOKEN('SUB','-')
TOKEN('NUMBER','2')
TOKEN('SEMI_COLON',';')

Parser

Parsing, syntax analysis, or syntactic analysis is the process of analysing a string of symbols, either in natural language, computer languages or data structures, conforming to the rules of a formal grammar. That´s why our second component in our compiler is the Parser. It will take the list of tokens as input and create a AST as output.

alt text

Inside an ast.py file in which we put all clases that are going to be called on the Parser and create the AST. For example: class Number(), class BinaryOp(), class Sum(), class Sub(), class Mul(), class Div(), class Mod(), class Print().

Next we need to create the parser, in which we’ll use ParserGenerator from RPLY inside a file name parser.py. And finally, we’ll update our file main.py to combine Parser with Lexer.

We’ll see the output being the result of print(4 + 4 — 2), which is equal to printing 6. With these two components, we have a functional compiler that interprets our own language with Python. However, it still doesn’t create a machine language code and is not well optimized. To do this, we’ll need the most complex part of the compiler, code generation with LLVM.

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Latest commit

History

533 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

compiler-in-python

In this project we will try to build a compiler using Python and some powerful libraries.

Compilers

A compiler can be any program that translates one text into another. Since a computer can only read 1s and 0s, and humans write better Code than they do binary, compilers were made to turn that human-readable text into computer-readable machine code.

Compilers take source code and produce binary. They have several steps of processing to do before their programs are runnable:

  1. Reads the individual characters of the source code you give it.
  2. Sorts the characters into words, numbers, symbols, and operators. (These are called Tokens)
  3. Takes the sorted characters and determines the operations they are trying to perform by matching them against patterns, and making a tree of the operations.
  4. Iterates over evry operation in the tree made in the last step, and finally, generates the equivalent binary.

Our compiler can be divided intro three components:

  • Lexer
  • Parser
  • Code Generator

For the Lexer and Parser we’ll be using RPLY, really similar to PLY: a Python library with lexical and parsing tools, but with a better API. And for the Code Generator, we’ll use LLVMlite, a Python library for binding LLVM components. Using LLVM, it is possible to optimize your compilation without learning compiling optimization, and LLVMLite it´s a really good library to work with compilers.

alt text

How to run this project

  1. Clone the project
git clone https://github.com/Pishgard/compiler-in-python.git
  1. Make sure you are in compiler-in-python folder
cd compiler-in-python
  1. Install all dependencies
pip install -r requirements.txt
  1. Run Main
python main.py

Lexical Analysis

The first step is to split the input up character by character. This step is called Lexical Analysis or Tokenization. The major idea is that we group characters together to form our words, identifiers, symbols, and more.

alt text

We use minimal structures to define or tokens, for example:

print(4 + 4 - 2);

Our Lexer would divide this string into this list of Tokens

TOKEN('PRINT','print')
TOKEN('OPEN_PAREN','\(')
TOKEN('NUMBER','4')
TOKEN('SUM','+')
TOKEN('NUMBER','4')
TOKEN('SUB','-')
TOKEN('NUMBER','2')
TOKEN('SEMI_COLON',';')

Parser

Parsing, syntax analysis, or syntactic analysis is the process of analysing a string of symbols, either in natural language, computer languages or data structures, conforming to the rules of a formal grammar. That´s why our second component in our compiler is the Parser. It will take the list of tokens as input and create a AST as output.

alt text

Inside an ast.py file in which we put all clases that are going to be called on the Parser and create the AST. For example: class Number(), class BinaryOp(), class Sum(), class Sub(), class Mul(), class Div(), class Mod(), class Print().

Next we need to create the parser, in which we’ll use ParserGenerator from RPLY inside a file name parser.py. And finally, we’ll update our file main.py to combine Parser with Lexer.

We’ll see the output being the result of print(4 + 4 — 2), which is equal to printing 6. With these two components, we have a functional compiler that interprets our own language with Python. However, it still doesn’t create a machine language code and is not well optimized. To do this, we’ll need the most complex part of the compiler, code generation with LLVM.

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Latest commit

History

533 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

compiler-in-python

In this project we will try to build a compiler using Python and some powerful libraries.

Compilers

A compiler can be any program that translates one text into another. Since a computer can only read 1s and 0s, and humans write better Code than they do binary, compilers were made to turn that human-readable text into computer-readable machine code.

Compilers take source code and produce binary. They have several steps of processing to do before their programs are runnable:

  1. Reads the individual characters of the source code you give it.
  2. Sorts the characters into words, numbers, symbols, and operators. (These are called Tokens)
  3. Takes the sorted characters and determines the operations they are trying to perform by matching them against patterns, and making a tree of the operations.
  4. Iterates over evry operation in the tree made in the last step, and finally, generates the equivalent binary.

Our compiler can be divided intro three components:

  • Lexer
  • Parser
  • Code Generator

For the Lexer and Parser we’ll be using RPLY, really similar to PLY: a Python library with lexical and parsing tools, but with a better API. And for the Code Generator, we’ll use LLVMlite, a Python library for binding LLVM components. Using LLVM, it is possible to optimize your compilation without learning compiling optimization, and LLVMLite it´s a really good library to work with compilers.

alt text

How to run this project

  1. Clone the project
git clone https://github.com/Pishgard/compiler-in-python.git
  1. Make sure you are in compiler-in-python folder
cd compiler-in-python
  1. Install all dependencies
pip install -r requirements.txt
  1. Run Main
python main.py

Lexical Analysis

The first step is to split the input up character by character. This step is called Lexical Analysis or Tokenization. The major idea is that we group characters together to form our words, identifiers, symbols, and more.

alt text

We use minimal structures to define or tokens, for example:

print(4 + 4 - 2);

Our Lexer would divide this string into this list of Tokens

TOKEN('PRINT','print')
TOKEN('OPEN_PAREN','\(')
TOKEN('NUMBER','4')
TOKEN('SUM','+')
TOKEN('NUMBER','4')
TOKEN('SUB','-')
TOKEN('NUMBER','2')
TOKEN('SEMI_COLON',';')

Parser

Parsing, syntax analysis, or syntactic analysis is the process of analysing a string of symbols, either in natural language, computer languages or data structures, conforming to the rules of a formal grammar. That´s why our second component in our compiler is the Parser. It will take the list of tokens as input and create a AST as output.

alt text

Inside an ast.py file in which we put all clases that are going to be called on the Parser and create the AST. For example: class Number(), class BinaryOp(), class Sum(), class Sub(), class Mul(), class Div(), class Mod(), class Print().

Next we need to create the parser, in which we’ll use ParserGenerator from RPLY inside a file name parser.py. And finally, we’ll update our file main.py to combine Parser with Lexer.

We’ll see the output being the result of print(4 + 4 — 2), which is equal to printing 6. With these two components, we have a functional compiler that interprets our own language with Python. However, it still doesn’t create a machine language code and is not well optimized. To do this, we’ll need the most complex part of the compiler, code generation with LLVM.

Releases

Packages

Contributors

Languages