Latest commit

History

29 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

Nanoscript

Nanoscript is a minimalist programming language crafted entirely from scratch using pure Python without relying on external libraries like ply or pybison.

Features

  • Arithmetic Expression Evaluation

    Evaluate numeric expressions like `4 * (3 + 2 - (3 % 4))`, etc
    
  • Variables

     - Syntax : Use the `let` and `const` to define variables.
    - Assignment: Currently supports numbers and arithmetic expressions.
    - Scoping: Support global and function scoping
    
    // Exampleconsta=5;letb=10;letx=y=x=12;b=5;// worksa=10;// throws an errorconstc;// throws an errorleta=12;// throws an error
  • Objects, Nested Objects and Accessors

     - Syntax : Similar to JS objects, use curly braces `{}`
    - Assignment : Currently supports only numbers and arithmetic expressions
    - Scoping : Every property inside the object belongs to the object and are scoped to it
    - Accessors : Use the dot operator (.) to access properties inside an object. For nested properties, see the example below
    
    // Exampleletobj={a : 32,b : 39+23-5*4%2nested : {foo : {bar : 1}}};a=b+15// throws : Cannot resolve b as it does not existobj.a=obj.b+15// this is valid// accessing nested propertiesobj.nested.foo.bar=2
  • Global and User Defined Functions

     - Syntax : - Use the `fn` keyword to create user defined function. - Use the `make_native_fn` macro to create global methods. See `create_global_env()` method in `runtime/environment.py`
    - Note :
    - `return` statement is yet to be implemented. In the current implementation, the last statement / expr in the function declaration is returned
    
    fnadd(x,y){constres=x+y;res// res is returned}leta=add(10,2);
  • Nested Functions and Nested Call Expressions :

     - Syntax : Just like the normal function, use the `fn` keyword and create functions within functions
    - Scoping : Inner functions have access to outer function's scope but not vice-versa. See the example below to understand better about scoping
    
    letres;// A. this is in global scopeleta;// A. this is in global scopeletb;// A. this is in global scopefncalc(x,y){letres;// B. this is in the 'calc' function's scopefnadd(x,y){constVAL=1;res=x+y// refers to B.res}fnsub(x,y){res=x-y// refers to B.res}res={// refers to Ba : add(x,y),b : sub(add(x,y),10)}// throws : Cannot resolve VAL as it does not exist print(VAL)}// refers to A (although, in this case the program terminates // since we are accessing VAL from outer scope)print(res)

Some Notes On Grammar

  • Order of precedence :

    
    lower in the tree or the call stack has the highest precedence
    | Stmt (lowest)
    | Expr | VariableDecl
    | AssignmentExpr
    | ObjectExpr
    | AdditiveExpr
    | MultiplicativeExpr
    | CallExpr
    | MemberExpr
    v PrimaryExpr (highest)
    more precedence = further down the tree
    so, additive calls multiplicative. multiplicative calls primary. similarly, assignment calls object expression, and so on
    At any level of the stack described above, the expr that the parser currently points at will always :
    - return something or
    - call itself or
    - call an expr that has a lower precedence
    - call an expr that has a one level higher precedence
    At no point, an expr calls another expr that has more than one level of precedence difference. It always passes through the above order. So, for example :
    VariableDecl can not directly call PrimaryExpr or say
    AdditiveExpr can not directly call MemberExpr
    Technically speaking, this would be the grammar of this language at this point :
    Stmt := Expr | VariableDecl
    Expr := AssignmentExpr
    AssignmentExpr := AssignmentExpr | ObjectExpr
    ObjectExpr := Expr | AdditiveExpr
    AdditiveExpr := MultiplicativeExpr
    MultiplicativeExpr := PrimaryExpr
    
  • Note :

     - The grammar created here is based on the parser implementation.
    - Ideally, it would the other way around - we write the rules and code a 'meta program' to auto-generate the parser file. For the time being, this is what we will be working with the former.
    - This is bound to change in the future.
    

Getting Started

To dive into Nanoscript, simply clone this repository and start experimenting with the language.

To execute your Nanoscript code use the provided REPL .

git clone https://github.com/Vishvam10/NanoScript
cd src
python repl.py

License

This project is licensed under the MIT License - see the LICENSE file for details.

Acknowledgements

Big thanks to @tlaceby for initiating the guide-to-interpreter series. I absolutely loved it 💛. Your work inspired me to create a Python port, building upon your foundation, with the hope of making it even better.

About

A minimalist programming language created from scratch using pure Python without PLY or PyBison.

Topics

Resources

Stars

1 star

Watchers

1 watching

Forks

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

29 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

Nanoscript

Nanoscript is a minimalist programming language crafted entirely from scratch using pure Python without relying on external libraries like ply or pybison.

Features

  • Arithmetic Expression Evaluation

    Evaluate numeric expressions like `4 * (3 + 2 - (3 % 4))`, etc
    
  • Variables

     - Syntax : Use the `let` and `const` to define variables.
    - Assignment: Currently supports numbers and arithmetic expressions.
    - Scoping: Support global and function scoping
    
    // Exampleconsta=5;letb=10;letx=y=x=12;b=5;// worksa=10;// throws an errorconstc;// throws an errorleta=12;// throws an error
  • Objects, Nested Objects and Accessors

     - Syntax : Similar to JS objects, use curly braces `{}`
    - Assignment : Currently supports only numbers and arithmetic expressions
    - Scoping : Every property inside the object belongs to the object and are scoped to it
    - Accessors : Use the dot operator (.) to access properties inside an object. For nested properties, see the example below
    
    // Exampleletobj={a : 32,b : 39+23-5*4%2nested : {foo : {bar : 1}}};a=b+15// throws : Cannot resolve b as it does not existobj.a=obj.b+15// this is valid// accessing nested propertiesobj.nested.foo.bar=2
  • Global and User Defined Functions

     - Syntax : - Use the `fn` keyword to create user defined function. - Use the `make_native_fn` macro to create global methods. See `create_global_env()` method in `runtime/environment.py`
    - Note :
    - `return` statement is yet to be implemented. In the current implementation, the last statement / expr in the function declaration is returned
    
    fnadd(x,y){constres=x+y;res// res is returned}leta=add(10,2);
  • Nested Functions and Nested Call Expressions :

     - Syntax : Just like the normal function, use the `fn` keyword and create functions within functions
    - Scoping : Inner functions have access to outer function's scope but not vice-versa. See the example below to understand better about scoping
    
    letres;// A. this is in global scopeleta;// A. this is in global scopeletb;// A. this is in global scopefncalc(x,y){letres;// B. this is in the 'calc' function's scopefnadd(x,y){constVAL=1;res=x+y// refers to B.res}fnsub(x,y){res=x-y// refers to B.res}res={// refers to Ba : add(x,y),b : sub(add(x,y),10)}// throws : Cannot resolve VAL as it does not exist print(VAL)}// refers to A (although, in this case the program terminates // since we are accessing VAL from outer scope)print(res)

Some Notes On Grammar

  • Order of precedence :

    
    lower in the tree or the call stack has the highest precedence
    | Stmt (lowest)
    | Expr | VariableDecl
    | AssignmentExpr
    | ObjectExpr
    | AdditiveExpr
    | MultiplicativeExpr
    | CallExpr
    | MemberExpr
    v PrimaryExpr (highest)
    more precedence = further down the tree
    so, additive calls multiplicative. multiplicative calls primary. similarly, assignment calls object expression, and so on
    At any level of the stack described above, the expr that the parser currently points at will always :
    - return something or
    - call itself or
    - call an expr that has a lower precedence
    - call an expr that has a one level higher precedence
    At no point, an expr calls another expr that has more than one level of precedence difference. It always passes through the above order. So, for example :
    VariableDecl can not directly call PrimaryExpr or say
    AdditiveExpr can not directly call MemberExpr
    Technically speaking, this would be the grammar of this language at this point :
    Stmt := Expr | VariableDecl
    Expr := AssignmentExpr
    AssignmentExpr := AssignmentExpr | ObjectExpr
    ObjectExpr := Expr | AdditiveExpr
    AdditiveExpr := MultiplicativeExpr
    MultiplicativeExpr := PrimaryExpr
    
  • Note :

     - The grammar created here is based on the parser implementation.
    - Ideally, it would the other way around - we write the rules and code a 'meta program' to auto-generate the parser file. For the time being, this is what we will be working with the former.
    - This is bound to change in the future.
    

Getting Started

To dive into Nanoscript, simply clone this repository and start experimenting with the language.

To execute your Nanoscript code use the provided REPL .

git clone https://github.com/Vishvam10/NanoScript
cd src
python repl.py

License

This project is licensed under the MIT License - see the LICENSE file for details.

Acknowledgements

Big thanks to @tlaceby for initiating the guide-to-interpreter series. I absolutely loved it 💛. Your work inspired me to create a Python port, building upon your foundation, with the hope of making it even better.

About

A minimalist programming language created from scratch using pure Python without PLY or PyBison.

Topics

Resources

Stars

1 star

Watchers

1 watching

Forks

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

29 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

Nanoscript

Nanoscript is a minimalist programming language crafted entirely from scratch using pure Python without relying on external libraries like ply or pybison.

Features

  • Arithmetic Expression Evaluation

    Evaluate numeric expressions like `4 * (3 + 2 - (3 % 4))`, etc
    
  • Variables

     - Syntax : Use the `let` and `const` to define variables.
    - Assignment: Currently supports numbers and arithmetic expressions.
    - Scoping: Support global and function scoping
    
    // Exampleconsta=5;letb=10;letx=y=x=12;b=5;// worksa=10;// throws an errorconstc;// throws an errorleta=12;// throws an error
  • Objects, Nested Objects and Accessors

     - Syntax : Similar to JS objects, use curly braces `{}`
    - Assignment : Currently supports only numbers and arithmetic expressions
    - Scoping : Every property inside the object belongs to the object and are scoped to it
    - Accessors : Use the dot operator (.) to access properties inside an object. For nested properties, see the example below
    
    // Exampleletobj={a : 32,b : 39+23-5*4%2nested : {foo : {bar : 1}}};a=b+15// throws : Cannot resolve b as it does not existobj.a=obj.b+15// this is valid// accessing nested propertiesobj.nested.foo.bar=2
  • Global and User Defined Functions

     - Syntax : - Use the `fn` keyword to create user defined function. - Use the `make_native_fn` macro to create global methods. See `create_global_env()` method in `runtime/environment.py`
    - Note :
    - `return` statement is yet to be implemented. In the current implementation, the last statement / expr in the function declaration is returned
    
    fnadd(x,y){constres=x+y;res// res is returned}leta=add(10,2);
  • Nested Functions and Nested Call Expressions :

     - Syntax : Just like the normal function, use the `fn` keyword and create functions within functions
    - Scoping : Inner functions have access to outer function's scope but not vice-versa. See the example below to understand better about scoping
    
    letres;// A. this is in global scopeleta;// A. this is in global scopeletb;// A. this is in global scopefncalc(x,y){letres;// B. this is in the 'calc' function's scopefnadd(x,y){constVAL=1;res=x+y// refers to B.res}fnsub(x,y){res=x-y// refers to B.res}res={// refers to Ba : add(x,y),b : sub(add(x,y),10)}// throws : Cannot resolve VAL as it does not exist print(VAL)}// refers to A (although, in this case the program terminates // since we are accessing VAL from outer scope)print(res)

Some Notes On Grammar

  • Order of precedence :

    
    lower in the tree or the call stack has the highest precedence
    | Stmt (lowest)
    | Expr | VariableDecl
    | AssignmentExpr
    | ObjectExpr
    | AdditiveExpr
    | MultiplicativeExpr
    | CallExpr
    | MemberExpr
    v PrimaryExpr (highest)
    more precedence = further down the tree
    so, additive calls multiplicative. multiplicative calls primary. similarly, assignment calls object expression, and so on
    At any level of the stack described above, the expr that the parser currently points at will always :
    - return something or
    - call itself or
    - call an expr that has a lower precedence
    - call an expr that has a one level higher precedence
    At no point, an expr calls another expr that has more than one level of precedence difference. It always passes through the above order. So, for example :
    VariableDecl can not directly call PrimaryExpr or say
    AdditiveExpr can not directly call MemberExpr
    Technically speaking, this would be the grammar of this language at this point :
    Stmt := Expr | VariableDecl
    Expr := AssignmentExpr
    AssignmentExpr := AssignmentExpr | ObjectExpr
    ObjectExpr := Expr | AdditiveExpr
    AdditiveExpr := MultiplicativeExpr
    MultiplicativeExpr := PrimaryExpr
    
  • Note :

     - The grammar created here is based on the parser implementation.
    - Ideally, it would the other way around - we write the rules and code a 'meta program' to auto-generate the parser file. For the time being, this is what we will be working with the former.
    - This is bound to change in the future.
    

Getting Started

To dive into Nanoscript, simply clone this repository and start experimenting with the language.

To execute your Nanoscript code use the provided REPL .

git clone https://github.com/Vishvam10/NanoScript
cd src
python repl.py

License

This project is licensed under the MIT License - see the LICENSE file for details.

Acknowledgements

Big thanks to @tlaceby for initiating the guide-to-interpreter series. I absolutely loved it 💛. Your work inspired me to create a Python port, building upon your foundation, with the hope of making it even better.

About

A minimalist programming language created from scratch using pure Python without PLY or PyBison.

Topics

Resources

Stars

1 star

Watchers

1 watching

Forks

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

29 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

Nanoscript

Nanoscript is a minimalist programming language crafted entirely from scratch using pure Python without relying on external libraries like ply or pybison.

Features

  • Arithmetic Expression Evaluation

    Evaluate numeric expressions like `4 * (3 + 2 - (3 % 4))`, etc
    
  • Variables

     - Syntax : Use the `let` and `const` to define variables.
    - Assignment: Currently supports numbers and arithmetic expressions.
    - Scoping: Support global and function scoping
    
    // Exampleconsta=5;letb=10;letx=y=x=12;b=5;// worksa=10;// throws an errorconstc;// throws an errorleta=12;// throws an error
  • Objects, Nested Objects and Accessors

     - Syntax : Similar to JS objects, use curly braces `{}`
    - Assignment : Currently supports only numbers and arithmetic expressions
    - Scoping : Every property inside the object belongs to the object and are scoped to it
    - Accessors : Use the dot operator (.) to access properties inside an object. For nested properties, see the example below
    
    // Exampleletobj={a : 32,b : 39+23-5*4%2nested : {foo : {bar : 1}}};a=b+15// throws : Cannot resolve b as it does not existobj.a=obj.b+15// this is valid// accessing nested propertiesobj.nested.foo.bar=2
  • Global and User Defined Functions

     - Syntax : - Use the `fn` keyword to create user defined function. - Use the `make_native_fn` macro to create global methods. See `create_global_env()` method in `runtime/environment.py`
    - Note :
    - `return` statement is yet to be implemented. In the current implementation, the last statement / expr in the function declaration is returned
    
    fnadd(x,y){constres=x+y;res// res is returned}leta=add(10,2);
  • Nested Functions and Nested Call Expressions :

     - Syntax : Just like the normal function, use the `fn` keyword and create functions within functions
    - Scoping : Inner functions have access to outer function's scope but not vice-versa. See the example below to understand better about scoping
    
    letres;// A. this is in global scopeleta;// A. this is in global scopeletb;// A. this is in global scopefncalc(x,y){letres;// B. this is in the 'calc' function's scopefnadd(x,y){constVAL=1;res=x+y// refers to B.res}fnsub(x,y){res=x-y// refers to B.res}res={// refers to Ba : add(x,y),b : sub(add(x,y),10)}// throws : Cannot resolve VAL as it does not exist print(VAL)}// refers to A (although, in this case the program terminates // since we are accessing VAL from outer scope)print(res)

Some Notes On Grammar

  • Order of precedence :

    
    lower in the tree or the call stack has the highest precedence
    | Stmt (lowest)
    | Expr | VariableDecl
    | AssignmentExpr
    | ObjectExpr
    | AdditiveExpr
    | MultiplicativeExpr
    | CallExpr
    | MemberExpr
    v PrimaryExpr (highest)
    more precedence = further down the tree
    so, additive calls multiplicative. multiplicative calls primary. similarly, assignment calls object expression, and so on
    At any level of the stack described above, the expr that the parser currently points at will always :
    - return something or
    - call itself or
    - call an expr that has a lower precedence
    - call an expr that has a one level higher precedence
    At no point, an expr calls another expr that has more than one level of precedence difference. It always passes through the above order. So, for example :
    VariableDecl can not directly call PrimaryExpr or say
    AdditiveExpr can not directly call MemberExpr
    Technically speaking, this would be the grammar of this language at this point :
    Stmt := Expr | VariableDecl
    Expr := AssignmentExpr
    AssignmentExpr := AssignmentExpr | ObjectExpr
    ObjectExpr := Expr | AdditiveExpr
    AdditiveExpr := MultiplicativeExpr
    MultiplicativeExpr := PrimaryExpr
    
  • Note :

     - The grammar created here is based on the parser implementation.
    - Ideally, it would the other way around - we write the rules and code a 'meta program' to auto-generate the parser file. For the time being, this is what we will be working with the former.
    - This is bound to change in the future.
    

Getting Started

To dive into Nanoscript, simply clone this repository and start experimenting with the language.

To execute your Nanoscript code use the provided REPL .

git clone https://github.com/Vishvam10/NanoScript
cd src
python repl.py

License

This project is licensed under the MIT License - see the LICENSE file for details.

Acknowledgements

Big thanks to @tlaceby for initiating the guide-to-interpreter series. I absolutely loved it 💛. Your work inspired me to create a Python port, building upon your foundation, with the hope of making it even better.

About

A minimalist programming language created from scratch using pure Python without PLY or PyBison.

Topics

Resources

Stars

1 star

Watchers

1 watching

Forks

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

29 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

Nanoscript

Nanoscript is a minimalist programming language crafted entirely from scratch using pure Python without relying on external libraries like ply or pybison.

Features

  • Arithmetic Expression Evaluation

    Evaluate numeric expressions like `4 * (3 + 2 - (3 % 4))`, etc
    
  • Variables

     - Syntax : Use the `let` and `const` to define variables.
    - Assignment: Currently supports numbers and arithmetic expressions.
    - Scoping: Support global and function scoping
    
    // Exampleconsta=5;letb=10;letx=y=x=12;b=5;// worksa=10;// throws an errorconstc;// throws an errorleta=12;// throws an error
  • Objects, Nested Objects and Accessors

     - Syntax : Similar to JS objects, use curly braces `{}`
    - Assignment : Currently supports only numbers and arithmetic expressions
    - Scoping : Every property inside the object belongs to the object and are scoped to it
    - Accessors : Use the dot operator (.) to access properties inside an object. For nested properties, see the example below
    
    // Exampleletobj={a : 32,b : 39+23-5*4%2nested : {foo : {bar : 1}}};a=b+15// throws : Cannot resolve b as it does not existobj.a=obj.b+15// this is valid// accessing nested propertiesobj.nested.foo.bar=2
  • Global and User Defined Functions

     - Syntax : - Use the `fn` keyword to create user defined function. - Use the `make_native_fn` macro to create global methods. See `create_global_env()` method in `runtime/environment.py`
    - Note :
    - `return` statement is yet to be implemented. In the current implementation, the last statement / expr in the function declaration is returned
    
    fnadd(x,y){constres=x+y;res// res is returned}leta=add(10,2);
  • Nested Functions and Nested Call Expressions :

     - Syntax : Just like the normal function, use the `fn` keyword and create functions within functions
    - Scoping : Inner functions have access to outer function's scope but not vice-versa. See the example below to understand better about scoping
    
    letres;// A. this is in global scopeleta;// A. this is in global scopeletb;// A. this is in global scopefncalc(x,y){letres;// B. this is in the 'calc' function's scopefnadd(x,y){constVAL=1;res=x+y// refers to B.res}fnsub(x,y){res=x-y// refers to B.res}res={// refers to Ba : add(x,y),b : sub(add(x,y),10)}// throws : Cannot resolve VAL as it does not exist print(VAL)}// refers to A (although, in this case the program terminates // since we are accessing VAL from outer scope)print(res)

Some Notes On Grammar

  • Order of precedence :

    
    lower in the tree or the call stack has the highest precedence
    | Stmt (lowest)
    | Expr | VariableDecl
    | AssignmentExpr
    | ObjectExpr
    | AdditiveExpr
    | MultiplicativeExpr
    | CallExpr
    | MemberExpr
    v PrimaryExpr (highest)
    more precedence = further down the tree
    so, additive calls multiplicative. multiplicative calls primary. similarly, assignment calls object expression, and so on
    At any level of the stack described above, the expr that the parser currently points at will always :
    - return something or
    - call itself or
    - call an expr that has a lower precedence
    - call an expr that has a one level higher precedence
    At no point, an expr calls another expr that has more than one level of precedence difference. It always passes through the above order. So, for example :
    VariableDecl can not directly call PrimaryExpr or say
    AdditiveExpr can not directly call MemberExpr
    Technically speaking, this would be the grammar of this language at this point :
    Stmt := Expr | VariableDecl
    Expr := AssignmentExpr
    AssignmentExpr := AssignmentExpr | ObjectExpr
    ObjectExpr := Expr | AdditiveExpr
    AdditiveExpr := MultiplicativeExpr
    MultiplicativeExpr := PrimaryExpr
    
  • Note :

     - The grammar created here is based on the parser implementation.
    - Ideally, it would the other way around - we write the rules and code a 'meta program' to auto-generate the parser file. For the time being, this is what we will be working with the former.
    - This is bound to change in the future.
    

Getting Started

To dive into Nanoscript, simply clone this repository and start experimenting with the language.

To execute your Nanoscript code use the provided REPL .

git clone https://github.com/Vishvam10/NanoScript
cd src
python repl.py

License

This project is licensed under the MIT License - see the LICENSE file for details.

Acknowledgements

Big thanks to @tlaceby for initiating the guide-to-interpreter series. I absolutely loved it 💛. Your work inspired me to create a Python port, building upon your foundation, with the hope of making it even better.

About

A minimalist programming language created from scratch using pure Python without PLY or PyBison.

Topics

Resources

Stars

1 star

Watchers

1 watching

Forks

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

29 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

Nanoscript

Nanoscript is a minimalist programming language crafted entirely from scratch using pure Python without relying on external libraries like ply or pybison.

Features

  • Arithmetic Expression Evaluation

    Evaluate numeric expressions like `4 * (3 + 2 - (3 % 4))`, etc
    
  • Variables

     - Syntax : Use the `let` and `const` to define variables.
    - Assignment: Currently supports numbers and arithmetic expressions.
    - Scoping: Support global and function scoping
    
    // Exampleconsta=5;letb=10;letx=y=x=12;b=5;// worksa=10;// throws an errorconstc;// throws an errorleta=12;// throws an error
  • Objects, Nested Objects and Accessors

     - Syntax : Similar to JS objects, use curly braces `{}`
    - Assignment : Currently supports only numbers and arithmetic expressions
    - Scoping : Every property inside the object belongs to the object and are scoped to it
    - Accessors : Use the dot operator (.) to access properties inside an object. For nested properties, see the example below
    
    // Exampleletobj={a : 32,b : 39+23-5*4%2nested : {foo : {bar : 1}}};a=b+15// throws : Cannot resolve b as it does not existobj.a=obj.b+15// this is valid// accessing nested propertiesobj.nested.foo.bar=2
  • Global and User Defined Functions

     - Syntax : - Use the `fn` keyword to create user defined function. - Use the `make_native_fn` macro to create global methods. See `create_global_env()` method in `runtime/environment.py`
    - Note :
    - `return` statement is yet to be implemented. In the current implementation, the last statement / expr in the function declaration is returned
    
    fnadd(x,y){constres=x+y;res// res is returned}leta=add(10,2);
  • Nested Functions and Nested Call Expressions :

     - Syntax : Just like the normal function, use the `fn` keyword and create functions within functions
    - Scoping : Inner functions have access to outer function's scope but not vice-versa. See the example below to understand better about scoping
    
    letres;// A. this is in global scopeleta;// A. this is in global scopeletb;// A. this is in global scopefncalc(x,y){letres;// B. this is in the 'calc' function's scopefnadd(x,y){constVAL=1;res=x+y// refers to B.res}fnsub(x,y){res=x-y// refers to B.res}res={// refers to Ba : add(x,y),b : sub(add(x,y),10)}// throws : Cannot resolve VAL as it does not exist print(VAL)}// refers to A (although, in this case the program terminates // since we are accessing VAL from outer scope)print(res)

Some Notes On Grammar

  • Order of precedence :

    
    lower in the tree or the call stack has the highest precedence
    | Stmt (lowest)
    | Expr | VariableDecl
    | AssignmentExpr
    | ObjectExpr
    | AdditiveExpr
    | MultiplicativeExpr
    | CallExpr
    | MemberExpr
    v PrimaryExpr (highest)
    more precedence = further down the tree
    so, additive calls multiplicative. multiplicative calls primary. similarly, assignment calls object expression, and so on
    At any level of the stack described above, the expr that the parser currently points at will always :
    - return something or
    - call itself or
    - call an expr that has a lower precedence
    - call an expr that has a one level higher precedence
    At no point, an expr calls another expr that has more than one level of precedence difference. It always passes through the above order. So, for example :
    VariableDecl can not directly call PrimaryExpr or say
    AdditiveExpr can not directly call MemberExpr
    Technically speaking, this would be the grammar of this language at this point :
    Stmt := Expr | VariableDecl
    Expr := AssignmentExpr
    AssignmentExpr := AssignmentExpr | ObjectExpr
    ObjectExpr := Expr | AdditiveExpr
    AdditiveExpr := MultiplicativeExpr
    MultiplicativeExpr := PrimaryExpr
    
  • Note :

     - The grammar created here is based on the parser implementation.
    - Ideally, it would the other way around - we write the rules and code a 'meta program' to auto-generate the parser file. For the time being, this is what we will be working with the former.
    - This is bound to change in the future.
    

Getting Started

To dive into Nanoscript, simply clone this repository and start experimenting with the language.

To execute your Nanoscript code use the provided REPL .

git clone https://github.com/Vishvam10/NanoScript
cd src
python repl.py

License

This project is licensed under the MIT License - see the LICENSE file for details.

Acknowledgements

Big thanks to @tlaceby for initiating the guide-to-interpreter series. I absolutely loved it 💛. Your work inspired me to create a Python port, building upon your foundation, with the hope of making it even better.

About

A minimalist programming language created from scratch using pure Python without PLY or PyBison.

Topics

Resources

Stars

1 star

Watchers

1 watching

Forks

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

29 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

Nanoscript

Nanoscript is a minimalist programming language crafted entirely from scratch using pure Python without relying on external libraries like ply or pybison.

Features

  • Arithmetic Expression Evaluation

    Evaluate numeric expressions like `4 * (3 + 2 - (3 % 4))`, etc
    
  • Variables

     - Syntax : Use the `let` and `const` to define variables.
    - Assignment: Currently supports numbers and arithmetic expressions.
    - Scoping: Support global and function scoping
    
    // Exampleconsta=5;letb=10;letx=y=x=12;b=5;// worksa=10;// throws an errorconstc;// throws an errorleta=12;// throws an error
  • Objects, Nested Objects and Accessors

     - Syntax : Similar to JS objects, use curly braces `{}`
    - Assignment : Currently supports only numbers and arithmetic expressions
    - Scoping : Every property inside the object belongs to the object and are scoped to it
    - Accessors : Use the dot operator (.) to access properties inside an object. For nested properties, see the example below
    
    // Exampleletobj={a : 32,b : 39+23-5*4%2nested : {foo : {bar : 1}}};a=b+15// throws : Cannot resolve b as it does not existobj.a=obj.b+15// this is valid// accessing nested propertiesobj.nested.foo.bar=2
  • Global and User Defined Functions

     - Syntax : - Use the `fn` keyword to create user defined function. - Use the `make_native_fn` macro to create global methods. See `create_global_env()` method in `runtime/environment.py`
    - Note :
    - `return` statement is yet to be implemented. In the current implementation, the last statement / expr in the function declaration is returned
    
    fnadd(x,y){constres=x+y;res// res is returned}leta=add(10,2);
  • Nested Functions and Nested Call Expressions :

     - Syntax : Just like the normal function, use the `fn` keyword and create functions within functions
    - Scoping : Inner functions have access to outer function's scope but not vice-versa. See the example below to understand better about scoping
    
    letres;// A. this is in global scopeleta;// A. this is in global scopeletb;// A. this is in global scopefncalc(x,y){letres;// B. this is in the 'calc' function's scopefnadd(x,y){constVAL=1;res=x+y// refers to B.res}fnsub(x,y){res=x-y// refers to B.res}res={// refers to Ba : add(x,y),b : sub(add(x,y),10)}// throws : Cannot resolve VAL as it does not exist print(VAL)}// refers to A (although, in this case the program terminates // since we are accessing VAL from outer scope)print(res)

Some Notes On Grammar

  • Order of precedence :

    
    lower in the tree or the call stack has the highest precedence
    | Stmt (lowest)
    | Expr | VariableDecl
    | AssignmentExpr
    | ObjectExpr
    | AdditiveExpr
    | MultiplicativeExpr
    | CallExpr
    | MemberExpr
    v PrimaryExpr (highest)
    more precedence = further down the tree
    so, additive calls multiplicative. multiplicative calls primary. similarly, assignment calls object expression, and so on
    At any level of the stack described above, the expr that the parser currently points at will always :
    - return something or
    - call itself or
    - call an expr that has a lower precedence
    - call an expr that has a one level higher precedence
    At no point, an expr calls another expr that has more than one level of precedence difference. It always passes through the above order. So, for example :
    VariableDecl can not directly call PrimaryExpr or say
    AdditiveExpr can not directly call MemberExpr
    Technically speaking, this would be the grammar of this language at this point :
    Stmt := Expr | VariableDecl
    Expr := AssignmentExpr
    AssignmentExpr := AssignmentExpr | ObjectExpr
    ObjectExpr := Expr | AdditiveExpr
    AdditiveExpr := MultiplicativeExpr
    MultiplicativeExpr := PrimaryExpr
    
  • Note :

     - The grammar created here is based on the parser implementation.
    - Ideally, it would the other way around - we write the rules and code a 'meta program' to auto-generate the parser file. For the time being, this is what we will be working with the former.
    - This is bound to change in the future.
    

Getting Started

To dive into Nanoscript, simply clone this repository and start experimenting with the language.

To execute your Nanoscript code use the provided REPL .

git clone https://github.com/Vishvam10/NanoScript
cd src
python repl.py

License

This project is licensed under the MIT License - see the LICENSE file for details.

Acknowledgements

Big thanks to @tlaceby for initiating the guide-to-interpreter series. I absolutely loved it 💛. Your work inspired me to create a Python port, building upon your foundation, with the hope of making it even better.

About

A minimalist programming language created from scratch using pure Python without PLY or PyBison.

Topics

Resources

Stars

1 star

Watchers

1 watching

Forks

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

29 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

Nanoscript

Nanoscript is a minimalist programming language crafted entirely from scratch using pure Python without relying on external libraries like ply or pybison.

Features

  • Arithmetic Expression Evaluation

    Evaluate numeric expressions like `4 * (3 + 2 - (3 % 4))`, etc
    
  • Variables

     - Syntax : Use the `let` and `const` to define variables.
    - Assignment: Currently supports numbers and arithmetic expressions.
    - Scoping: Support global and function scoping
    
    // Exampleconsta=5;letb=10;letx=y=x=12;b=5;// worksa=10;// throws an errorconstc;// throws an errorleta=12;// throws an error
  • Objects, Nested Objects and Accessors

     - Syntax : Similar to JS objects, use curly braces `{}`
    - Assignment : Currently supports only numbers and arithmetic expressions
    - Scoping : Every property inside the object belongs to the object and are scoped to it
    - Accessors : Use the dot operator (.) to access properties inside an object. For nested properties, see the example below
    
    // Exampleletobj={a : 32,b : 39+23-5*4%2nested : {foo : {bar : 1}}};a=b+15// throws : Cannot resolve b as it does not existobj.a=obj.b+15// this is valid// accessing nested propertiesobj.nested.foo.bar=2
  • Global and User Defined Functions

     - Syntax : - Use the `fn` keyword to create user defined function. - Use the `make_native_fn` macro to create global methods. See `create_global_env()` method in `runtime/environment.py`
    - Note :
    - `return` statement is yet to be implemented. In the current implementation, the last statement / expr in the function declaration is returned
    
    fnadd(x,y){constres=x+y;res// res is returned}leta=add(10,2);
  • Nested Functions and Nested Call Expressions :

     - Syntax : Just like the normal function, use the `fn` keyword and create functions within functions
    - Scoping : Inner functions have access to outer function's scope but not vice-versa. See the example below to understand better about scoping
    
    letres;// A. this is in global scopeleta;// A. this is in global scopeletb;// A. this is in global scopefncalc(x,y){letres;// B. this is in the 'calc' function's scopefnadd(x,y){constVAL=1;res=x+y// refers to B.res}fnsub(x,y){res=x-y// refers to B.res}res={// refers to Ba : add(x,y),b : sub(add(x,y),10)}// throws : Cannot resolve VAL as it does not exist print(VAL)}// refers to A (although, in this case the program terminates // since we are accessing VAL from outer scope)print(res)

Some Notes On Grammar

  • Order of precedence :

    
    lower in the tree or the call stack has the highest precedence
    | Stmt (lowest)
    | Expr | VariableDecl
    | AssignmentExpr
    | ObjectExpr
    | AdditiveExpr
    | MultiplicativeExpr
    | CallExpr
    | MemberExpr
    v PrimaryExpr (highest)
    more precedence = further down the tree
    so, additive calls multiplicative. multiplicative calls primary. similarly, assignment calls object expression, and so on
    At any level of the stack described above, the expr that the parser currently points at will always :
    - return something or
    - call itself or
    - call an expr that has a lower precedence
    - call an expr that has a one level higher precedence
    At no point, an expr calls another expr that has more than one level of precedence difference. It always passes through the above order. So, for example :
    VariableDecl can not directly call PrimaryExpr or say
    AdditiveExpr can not directly call MemberExpr
    Technically speaking, this would be the grammar of this language at this point :
    Stmt := Expr | VariableDecl
    Expr := AssignmentExpr
    AssignmentExpr := AssignmentExpr | ObjectExpr
    ObjectExpr := Expr | AdditiveExpr
    AdditiveExpr := MultiplicativeExpr
    MultiplicativeExpr := PrimaryExpr
    
  • Note :

     - The grammar created here is based on the parser implementation.
    - Ideally, it would the other way around - we write the rules and code a 'meta program' to auto-generate the parser file. For the time being, this is what we will be working with the former.
    - This is bound to change in the future.
    

Getting Started

To dive into Nanoscript, simply clone this repository and start experimenting with the language.

To execute your Nanoscript code use the provided REPL .

git clone https://github.com/Vishvam10/NanoScript
cd src
python repl.py

License

This project is licensed under the MIT License - see the LICENSE file for details.

Acknowledgements

Big thanks to @tlaceby for initiating the guide-to-interpreter series. I absolutely loved it 💛. Your work inspired me to create a Python port, building upon your foundation, with the hope of making it even better.

About

A minimalist programming language created from scratch using pure Python without PLY or PyBison.

Topics

Resources

Stars

1 star

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages