munificent / lark Goto Github PK
View Code? Open in Web Editor NEWThe Lark programming language.
License: Other
The Lark programming language.
License: Other
Lark ---- Lark is an experiment in designing a homoiconic language with a syntax inspired by SmallTalk. It's very early, so there isn't much to see yet, but you can play with it. Lark Syntax =========== Core syntax ----------- Internally, Lark has a very simple syntax. It's more complex than Scheme, but just barely. It has three core expression types: - Atoms are things like names, numbers and other literals. - Lists are an ordered set of other expressions. - Calls are a pair of expressions, the function and the argument. That's it. Scheme has the first two, and Lark just adds one more. Every expression in Lark can be desugared to these core elements. The rest of this section explains the syntactic sugar added on top of that, but that's handled only by the parser. To the interpreter, the above is the only syntax. This *should* mean that it'll be as easy to make powerful macros in Lark as it is in Scheme. Names ----- The simplest syntactical element in Lark are names, identifiers. There are three kinds of identifiers. Regular ones start with a letter and don't contain any colons. Like: a, abs, do-something, what?!, abc123 They are used for regular prefix function calls and don't trigger any special parsing, so you can just stick them anywhere. Operators start with a punctuation character, like: +, -, !can-have-letters-too!, !@#%#$$&$ An operator name will cause the parser to parse an infix expression. If you don't want that, and just want to use the name of an operator for something (for example, to pass it to a function), you can do so by surrounding it in (). This: (+) (1, 2) is the same as: 1 + 2 Keywords start with a letter and contain at least one colon. A colon by itself is also a keyword. Ex: if:, :, multiple:colons:in:one: Like operators, keywords will trigger special parsing, so must be put in parentheses if you just want to treat it like a name. Prefix functions ---------------- The basic Lark syntax looks much like C. A regular name followed by an expression will call that named function and pass it the given argument. Ex: square 123 Dotted functions ---------------- Lark also allows functions to be called using the dot operator. It's functionally equivalent to a regular function call, but has two minor differences: the function and argument are swapped, and the precedence is higher. For example: a.b c.d is desugared to: (b(a))(d(c)) Swapping the argument and function may sound a bit arbitrary, but it allows you to write in an "object.method" style familiar to many OOP programmers. For example, instead of: length list you can use: list.length Operators --------- Operators are parsed like SmallTalk. All operators have the same precedence (no Dear Aunt Sally), and are parsed from left to right. The expression: a + b * c @#%! d is equivalent to: @#%!(*(+(a, b), c), d) Keywords -------- Lark has keywords that work similar to SmallTalk. The parser will translate a series of keywords separated by arguments into a single keyword name followed by the list of arguments. This: if: a then: b else: c is parsed as: if:then:else:(a, b, c) Lists ----- A list can be created by separating expressions with commas, like so: 1, 2, 3 Parentheses are not necessary, but are often useful since commas have low precedence. For example: this: means: difference 1, 2 ===> (difference(1), 2) difference (1, 2) ===> difference(1, 2) Braces ------ A series of expressions separated by semicolons and surrounded by curly braces is syntactical sugar for a "do" function call. This gives us a simple syntax for expressing a sequence of things that executed in order (which is what the "do" special form is for). So this: { print 1, 2; print 3, 4 } is parsed as: do (print (1, 2), print (3, 4)) Note that the semicolons are *separators*, not *terminators*. The last expression does not have one after it. Precedence ---------- The precedence rules follow SmallTalk. From highest to lowest, it is prefix functions, operators, keywords, then ",". So, the following: if: a < b then: c, d is parsed as: (if:then:(<(a, b), c), d) That's the basic syntax. The Lark parser reads that and immediately translates it to the much simpler core syntax. Running Lark ============ Lark is a Java application stored in a single jar, you can run it by doing either: $ java -jar lark.jar Or, if you have bash installed, just: $ ./lark This starts up the Lark REPL, like this: lark v0.0.0 ----------- Type 'q' and press Enter to quit. > From there you can enter expressions, which the interpreter will evaluate and print the result. You can also tell lark to load and interpret a script stored in a separate file by passing in the path to the file to lark: $./lark path/to/my/file.lark Built-in functions ================== So what can you actually do with it? Not much, yet. Only a few built-in functions are implemented: ' <expr> The quote function simply returns its argument in unevaluated form. Ex: > ` print 123 : print 123 (note: does not call print function) do <expr> If the expression is anything but a list, it simply evaluates it and returns. If it's a list, it evaluates each item in the list, in order, and then returns the evaluated value of the last item. In other words, it's Lark's version of a { } block in C. Ex: > do (print 1, print 2, print 3) 1 2 3 : () print <expr> Simply evaluates the argument and prints it to the console. <params> => <body> Creates an anonymous function (a lambda). <params> should either be a single name or a list of parameter names. <body> is an expression that forms the body of the function. Ex: > (a => do (print a, print a)) 123 123 123 : () def: <name> is: <expr> Binds a value to a variable in the current scope. <name> should be a single name. <expr> will be evaluated and the result bound to the name. Ex: > def: a is: 123 : () > a : 123 if: <condition> then: <expr> if: <condition> then: <expr> else: <else> Evaluates the condition. If it evaluates to true, then it evaluates and returns <expr>. If it evaluates to false, it will either return () or, if an else: clause is given, evaluate and return that. Ex: > if: true then: print 1 else: print 2 2 : () bool? <expr> int? <expr> list? <expr> name? <expr> unit? <expr> Evaluates <expr> then returns true if it is the given type. Note that ().list? returns *true* because unit is the empty list. Ex: > 123.int? : true > ('foo).name? : true > 123.list? : false <int> <expr> Evaluates <expr>, expecting it to be a list. Returns the item at the <int> position in the list (zero-based). Basically, this means an int is a function you can pass a list to to get an item from it. Ex: > 0 (1, 2, 3) : 1 > (4, 5, 6, 7).3 : 7 count <expr> Evaluates <expr>, expecting it to be a list. Returns the number of items in the list. Ex: > (1, 2, 3).count : 3 That's it so far. Like I said, very early...
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.