GithubHelp home page GithubHelp logo

vishvam10 / nanoscript Goto Github PK

View Code? Open in Web Editor NEW
1.0 1.0 0.0 68 KB

๐Ÿ› ๏ธ A minimalist programming language created from scratch using pure Python without PLY or PyBison.

License: MIT License

Python 100.00%
interpreter lexer parser programming-language python3

nanoscript's Introduction

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
    
    
        // Example
    
        const a = 5;
        let b = 10;
        let x = y = x = 12;
    
        b = 5;      // works
        a = 10;     // throws an error
    
        const c;    // throws an error
    
        let a = 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
    
        // Example
    
        let obj = {
            a : 32,
            b : 39 + 23 - 5 * 4 % 2
            nested : {
                foo : {
                    bar : 1
                }
            }
        };
    
        a = b + 15          // throws : Cannot resolve b as it does not exist
        obj.a = obj.b + 15  // this is valid
    
        // accessing nested properties
        obj.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
    
        fn add(x, y) {
            const res = x + y;
            res                     // res is returned
        }
    
        let a = 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
    
        let res;                    // A. this is in global scope
        let a;                      // A. this is in global scope
        let b;                      // A. this is in global scope
        
        fn calc(x, y) {
            let res;                // B. this is in the 'calc' function's scope
        
            fn add(x, y) {
                const VAL = 1; 
                res = x + y         // refers to B.
                res   
            }
        
            fn sub(x, y) {
                res = x - y         // refers to B.
                res   
            }
    
            res = {                 // refers to B
                a : 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.

nanoscript's People

Contributors

vishvam10 avatar

Stargazers

 avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.