aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core.nom8
-rw-r--r--[-rwxr-xr-x]examples/sample_code.nom15
-rw-r--r--examples/sample_game.nom14
-rw-r--r--examples/tutorial.nom124
-rw-r--r--nomsu.lua47
-rwxr-xr-xnomsu.moon42
6 files changed, 136 insertions, 114 deletions
diff --git a/core.nom b/core.nom
index 3b0cf32..830e312 100644
--- a/core.nom
+++ b/core.nom
@@ -1,4 +1,3 @@
-(# Global import #)
lua block ".."
|utils = require('utils')
@@ -107,12 +106,11 @@ macro "%a or %b or %c or %d":
macro "%a mod %b": concat ["(",%a as lua expr," mod ",%b as lua expr,")"]
macro "- %a": concat ["-(",%a as lua expr,")"]
macro "not %a": concat ["not (",%a as lua expr,")"]
-macro "# %a": concat ["#(",%a as lua expr,")"]
-(# This does equivalence checking instead of identity checking. #)
rule "%a == %b":
- lua expr "utils.equivalent(vars.a, vars.b)"
-macro "%a != %b": concat ["not (",%a as lua expr," == ",%b as lua expr,")"]
+ lua expr "((vars.a == vars.b) or utils.equivalent(vars.a, vars.b))"
+rule "%a != %b":
+ lua expr "((vars.a ~= vars.b) or not utils.equivalent(vars.a, vars.b))"
rule "say %str":
lua block ["print(utils.repr(", %str, "))"]
diff --git a/examples/sample_code.nom b/examples/sample_code.nom
index c8b48f7..63078d7 100755..100644
--- a/examples/sample_code.nom
+++ b/examples/sample_code.nom
@@ -1,18 +1,21 @@
-(# This is just a comment #)
-(# Nested comments (# like this #) work fine #)
+# This is just a comment
+#.. Block comments
+ start with a #.. and
+ continue until dedent
+
run file "core.nom"
say "foo"
say (4)
-(# "rule" is just a function that takes a function call spec and a block of code to run,
- and stores the function definition #)
+#.. "rule" is just a function that takes a function call spec and a block of code to run,
+ and stores the function definition
rule "fart": say "poot"
fart
-(# multi-line strings: #)
+# multi-line strings:
say ".."
| Once upon a time
|there was a very
@@ -30,7 +33,7 @@ say ".."
|(done)
|
-rule "doublefart": (# this farts twice #)
+rule "doublefart": # this farts twice
say "poot"
say "poot"
diff --git a/examples/sample_game.nom b/examples/sample_game.nom
index 010e610..8ac7e7a 100644
--- a/examples/sample_game.nom
+++ b/examples/sample_game.nom
@@ -31,13 +31,13 @@ rule "you":
lua expr "(you or 'Anonymous')"
rule ["make %person %action", "make %person do %action"]:
- lua block [..]
- "do"
- "\n local old_you = you"
- "\n you = vars.person"
- "\n ret = compiler:call('do %', vars.action)"
- "\n you = old_you"
- "\nend"
+ lua block ".."
+ |do
+ | local old_you = you
+ | you = vars.person
+ | ret = compiler:call('do %', vars.action)
+ | you = old_you
+ |end
say "===================================================="
say " NEW GAME"
diff --git a/examples/tutorial.nom b/examples/tutorial.nom
index 147a292..4a9c213 100644
--- a/examples/tutorial.nom
+++ b/examples/tutorial.nom
@@ -1,22 +1,24 @@
-(# Comments use (# ... #), and can be nested #)
+# One liner comments start with # and go till end of line
+#.. Multi-line comments start with #.. and
+ continue until dedent
-(# Import files like so: #)
+# Import files like so:
run file "core.nom"
-(# Numbers: #)
+# Numbers:
23
4.5
-(# Since this language cross-compiles to lua, integers and floating point numbers are
- both represented using the same primitive. #)
+#.. Since this language cross-compiles to lua, integers and floating point numbers are
+ both represented using the same primitive.
-(# Strings: #)
+# Strings:
"asdf"
".."
- |This is a multi-line string
+ |This is a multi-line string with a #.. fake comment
|that starts with ".." and includes each indented line that starts with a "|"
|until the indentation ends
-(# Lists: #)
+# Lists:
[1,2,3]
[..]
"like multi-line strings, lists have an indented form", "that can use commas too"
@@ -24,73 +26,73 @@ run file "core.nom"
5
6,7,8
-(# Function calls: #)
+# Function calls:
say "Hello world!"
-(# Function definition: #)
+# Function definition:
rule "say both %first and also %second":
- (# Variables use the "%" sign: #)
+ # Variables use the "%" sign:
say %first
say %second
-(# Function calls can have parts of the function's name spread throughout.
- Everything that's not a literal value is treated as part of the function's name #)
+#.. Function calls can have parts of the function's name spread throughout.
+ Everything that's not a literal value is treated as part of the function's name
say both "Hello" and also "again!"
-(# Functions can even have their name at the end: #)
+# Functions can even have their name at the end:
rule "%what-she-said is what she said":
say %what-she-said
say "-- she said"
"Howdy pardner" is what she said
-(# The language only reserves []{}().,:;% as special characters, so functions and variables
- can have really funky names! #)
-rule ">> %foo-bar###^ --> %@@& _~-^-~_~-^ %1 !":
- say %foo-bar###^
+#.. The language only reserves []{}().,:;% as special characters, so functions and variables
+ can have really funky names!
+rule ">> %foo-bar$$$^ --> %@@& _~-^-~_~-^ %1 !":
+ say %foo-bar$$$^
say %@@&
say %1
>> "wow" --> "so flexible!" _~-^-~_~-^ "even numbers can be variables!" !
-(# Though literals can't be used in function names #)
+# Though literals can't be used in function names
-(# Math and logic operations are just treated the same as function calls in the syntax #)
+# Math and logic operations are just treated the same as function calls in the syntax
say (2 + 3)
-(# So it's easy to define your own operators #)
+# So it's easy to define your own operators
rule "%a ++ %b": 2 * (%a + %b)
say (2 ++ 3)
-(# Code blocks start with ":" and either continue until the end of the line
- or are indented blocks #)
+#.. Code blocks start with ":" and either continue until the end of the line
+ or are indented blocks
-(# One liner: #)
+# One liner:
: say "hi"
-(# Block version: #)
+# Block version:
:
say "one"
say "two"
-(# So the function definitions above are actually just passing a regular string, like
+#.. So the function definitions above are actually just passing a regular string, like
"say both %first and also %second", and a code block to a function called "rule % %"
- that takes two arguments. #)
+ that takes two arguments.
-(# Line continuations work by either ending a line with ".." and continuing with an indented block: #)
+# Line continuations work by either ending a line with ".." and continuing with an indented block:
say..
both "Tom" and
also
"Sawyer"
-(# Or by starting the next line with ".." #)
+# Or by starting the next line with ".."
say both "Bruce"
..and also "Lee"
-(# This can be mixed and matched: #)
+# This can be mixed and matched:
say both..
"Rick"
..and also..
"Moranis"
-(# And combined with the block forms of literals: #)
+# And combined with the block forms of literals:
say both ".."
|Four score and seven years ago our fathers brought forth, upon this continent,
|a new nation, conceived in liberty, and dedicated to the proposition that
@@ -99,31 +101,31 @@ say both ".."
"-- Abraham Lincoln"
rule "my favorite number": return 23
-(# Subexpressions are wrapped in parentheses: #)
-(# printf takes a list of bits that are converted to strings and concatenated together, and printed #)
+# Subexpressions are wrapped in parentheses:
+# printf takes a list of bits that are converted to strings and concatenated together, and printed
printf ["My favorite number is ", my favorite number]
-(# There's a multi-line indented block form for subexpressions too: #)
+# There's a multi-line indented block form for subexpressions too:
printf [..]
"My favorite number is still ", (..)
my favorite
number
-(# There's a few macros in the language for things like conditional branches and logic/math
+#.. There's a few macros in the language for things like conditional branches and logic/math
operations, but they can be thought of as basically the same as functions.
- There are no keywords in the language! #)
+ There are no keywords in the language!
if (1 < 10):
say "One is less than ten"
..else:
say "One is not less than ten"
-(# Breakdown of the above: #)
-(# Function call (actually a macro) to "if % % else %" #)
-(# First argument is a subexpression that is a function call (also a macro) to "% < %"
- that performs a comparison on its arguments, 1 and 10 #)
-(# Second argument is a block of code that includes a function call to "say %", the "if" body #)
-(# Third argument is a block of code that includes a different function call to "say %", the "else" body #)
+#.. Breakdown of the above:
+ Function call (actually a macro) to "if % % else %"
+ First argument is a subexpression that is a function call (also a macro) to "% < %"
+ that performs a comparison on its arguments, 1 and 10
+ Second argument is a block of code that includes a function call to "say %", the "if" body
+ Third argument is a block of code that includes a different function call to "say %", the "else" body
-(# Line continuations can be used for "elseif" #)
+# Line continuations can be used for "elseif"
if (1 > 10):
say "First condition"
..else: if (1 > 5):
@@ -131,7 +133,7 @@ if (1 > 10):
..else:
say "Last condition"
-(# ^that's the same as: #)
+# ^that's the same as:
if (1 > 10):
say "First condition"
..else:
@@ -140,10 +142,10 @@ if (1 > 10):
..else:
say "Last condition"
-(# Variables are modified with a macro, "let % = %" #)
+# Variables are modified with a macro, "let % = %"
let "numbers" = [5,6,7]
-(# Looping: #)
+# Looping:
printf ["Looping over: ",%numbers,"!"]
for "number" in %numbers:
say (%number + 100)
@@ -158,45 +160,45 @@ rule "sing %starting-bottles bottles of beer":
sing 9 bottles of beer
-
-(# Note that because math and logic operations are just macros, they require a lot
- of parentheses to disambiguate. There's no PEMDAS. #)
+#.. Note that because math and logic operations are just macros, they require a lot
+ of parentheses to disambiguate. There's no PEMDAS.
say (5 + (4 * (- (1 + (6 + 2)))))
-(# For convenience, +,*,"and", and "or" have been hand defined to work with up to 4 operands: #)
+# For convenience, +,*,"and", and "or" have been hand defined to work with up to 4 operands:
1 + 2 + 3 + 4
1 * 2 * 3 * 4
1 and 2 and 3 and 4
1 or 2 or 3 or 4
-(# Longer lists can use "sum of %", "product of %", "all of %", and "any of %", respectively, or lots of parentheses. #)
+# Longer lists can use "sum of %", "product of %", "all of %", and "any of %", respectively, or lots of parentheses.
sum of [1,2,3,4,5,6,7]
product of [1,2,3,4,5,6,7]
all of [1,1,1,1,0,1,1]
any of [0,0,0,0,1,0,0]
-(# And 3-operand chained inequality comparisons have been defined: #)
+# And 3-operand chained inequality comparisons have been defined:
1 < 2 <= 3
-(# Macros: #)
-(# The "lua block %" and "lua expr %" macros can be used to write raw lua code: #)
+# Macros:
+# The "lua block %" and "lua expr %" macros can be used to write raw lua code:
rule "say the time":
lua block ".."
|io.write("The OS time is: ")
|io.write(tostring(os.time()).."\n")
say the time
printf ["Math expression result is: ", lua expr "(1 + 2*3 + 3*4)^2"]
-(# In the lua environment, "vars" can be used to get local variables/function args, and
- "compiler" can be used to access the compiler, function defs, and other things #)
+
+#.. In the lua environment, "vars" can be used to get local variables/function args, and
+ "compiler" can be used to access the compiler, function defs, and other things
rule "square root of %n":
return (lua expr "math.sqrt(vars.n)")
printf ["the square root of 2 is ", square root of 2]
-(# Macros can be defined as functions that take unprocessed syntax trees and return lua code #)
-(# "macro block %" is for defining macros that produce blocks of code, not values #)
+# Macros can be defined as functions that take unprocessed syntax trees and return lua code
+# "macro block %" is for defining macros that produce blocks of code, not values
macro block "unless %condition %body":
concat [..]
- (# "% as lua expr" and "% as lua block" are two useful helper functions here. #)
+ # "% as lua expr" and "% as lua block" are two useful helper functions here.
"if not (", %condition as lua expr, ") then"
- (# Extract the inner part of the code block's body and insert it: #)
+ # Extract the inner part of the code block's body and insert it:
"\n ", (lua expr "vars.body.value.value") as lua block
"\nend"
@@ -204,7 +206,7 @@ unless (1 > 10):
say "Macros work!"
say "It looks like a keyword, but there's no magic here!"
-(# and "macro %" is for defining macros that produce an expression #)
+# and "macro %" is for defining macros that produce an expression
macro "%value as a boolean":
concat ["(not not (", %value as lua expr, "))"]
macro "yep": "true"
diff --git a/nomsu.lua b/nomsu.lua
index c3c3f40..dfe4459 100644
--- a/nomsu.lua
+++ b/nomsu.lua
@@ -5,11 +5,6 @@ local INDENT = " "
lpeg.setmaxstack(10000)
local P, V, S, Cg, C, Cp, B, Cmt
P, V, S, Cg, C, Cp, B, Cmt = lpeg.P, lpeg.V, lpeg.S, lpeg.Cg, lpeg.C, lpeg.Cp, lpeg.B, lpeg.Cmt
-local wordchar = P(1) - S(' \t\n\r%:;,.{}[]()"')
-local comment = re.compile([[comment <- "(#" (comment / ((! "#)") .))* "#)"]])
-local whitespace = (S(" \t") + comment) ^ 1
-local nl = P("\n")
-local blank_line = whitespace ^ -1 * nl
local get_line_indentation
get_line_indentation = function(line)
local indent_amounts = {
@@ -18,7 +13,7 @@ get_line_indentation = function(line)
}
do
local sum = 0
- local leading_space = line:gsub("([\t ]*).*", "%1")
+ local leading_space = line:match("[\t ]*")
for c in leading_space:gmatch("[\t ]") do
sum = sum + indent_amounts[c]
end
@@ -64,13 +59,31 @@ make_parser = function(lingo, extra_definitions)
end
return end_pos
end
+ local wordchar = P(1) - S(' \t\n\r%#:;,.{}[]()"')
+ local nl = P("\n")
+ local whitespace = S(" \t") ^ 1
+ local blank_line = whitespace ^ -1 * nl
+ local line_comment = re.compile([=[ "#" [^%nl]* ]=], {
+ nl = nl
+ })
+ local block_comment = re.compile([=[ "#.." (!%nl .)* (%indent (!%dedent %nl [^%nl]*)*)
+ ]=], {
+ nl = nl,
+ whitespace = whitespace,
+ indent = #(nl * blank_line ^ 0 * Cmt(S(" \t") ^ 0, check_indent)),
+ dedent = #(nl * blank_line ^ 0 * Cmt(S(" \t") ^ 0, check_dedent)),
+ new_line = nl * blank_line ^ 0 * Cmt(S(" \t") ^ 0, check_nodent)
+ })
+ blank_line = ((Cmt(whitespace ^ -1, check_nodent) * (block_comment + line_comment)) ^ -1 + whitespace ^ -1) * nl
local defs = {
wordchar = wordchar,
nl = nl,
ws = whitespace,
- comment = comment,
+ blank_line = blank_line,
+ block_comment = block_comment,
+ line_comment = line_comment,
eol = #nl + (P("") - P(1)),
- word_boundary = whitespace + B(P("..")) + B(S("\";)]")) + #S("\":([") + #((whitespace + nl) ^ 0 * P("..")),
+ word_boundary = whitespace ^ -1 + B(P("..")) + B(S("\";)]")) + #S("\":([") + #((whitespace + nl) ^ 0 * P("..")),
indent = #(nl * blank_line ^ 0 * Cmt(whitespace ^ -1, check_indent)),
dedent = #(nl * blank_line ^ 0 * Cmt(whitespace ^ -1, check_dedent)),
new_line = nl * blank_line ^ 0 * Cmt(whitespace ^ -1, check_nodent),
@@ -244,7 +257,7 @@ do
if self.debug then
print("PARSING:\n" .. tostring(str))
end
- local lingo = [=[ file <- ({ {| %ws? %new_line? {:body: block :} %new_line? %ws? (errors)? |} }) -> File
+ local lingo = [=[ file <- ({ {| %blank_line* {:body: block :} %blank_line* (errors)? |} }) -> File
errors <- (({.+}) => error_handler)
block <- ({ {| statement (%new_line statement)* |} }) -> Block
statement <- ({ (functioncall / expression) }) -> Statement
@@ -260,37 +273,37 @@ do
functioncall <- ({ {| (expression %word_boundary fn_bits) / (word (%word_boundary fn_bits)?) |} }) -> FunctionCall
fn_bit <- (expression / word)
fn_bits <-
- ((".." %ws? (%indent %new_line indented_fn_bits %dedent) (%new_line ".." %ws? fn_bits)?)
+ ((".." %ws? %line_comment? (%indent %new_line indented_fn_bits %dedent) (%new_line ".." %ws? fn_bits)?)
/ (%new_line ".." fn_bit (%word_boundary fn_bits)?)
/ (fn_bit (%word_boundary fn_bits)?))
indented_fn_bits <-
fn_bit ((%new_line / %word_boundary) indented_fn_bits)?
thunk <-
- ({ ":" %ws?
+ ({ ":" %ws? %line_comment?
((%indent %new_line block ((%dedent (%new_line "..")?) / errors))
/ (one_liner (%ws? (%new_line? ".."))?)) }) -> Thunk
word <- ({ !number {%wordchar+} }) -> Word
expression <- ({ (longstring / string / number / variable / list / thunk / subexpression) }) -> Expression
- string <- ({ (!longstring) '"' {(("\" .) / [^"])*} '"' }) -> String
- longstring <- ({ '".."' %ws? %indent {(%new_line "|" [^%nl]*)+} ((%dedent (%new_line '..')?) / errors) }) -> Longstring
+ string <- ({ (!longstring) '"' {(("\" [^%nl]) / [^"%nl])*} '"' }) -> String
+ longstring <- ({ '".."' %ws? %line_comment? %indent {(%new_line "|" [^%nl]*)+} ((%dedent (%new_line '..')?) / errors) }) -> Longstring
number <- ({ {'-'? [0-9]+ ("." [0-9]+)?} }) -> Number
variable <- ({ ("%" {%wordchar+}) }) -> Var
subexpression <-
- (!%comment "(" %ws? (functioncall / expression) %ws? ")")
- / ("(..)" %ws? %indent %new_line ((({ {| indented_fn_bits |} }) -> FunctionCall) / expression) %dedent (%new_line "..")?)
+ ("(" %ws? (functioncall / expression) %ws? ")")
+ / ("(..)" %ws? %line_comment? %indent %new_line ((({ {| indented_fn_bits |} }) -> FunctionCall) / expression) %dedent (%new_line "..")?)
list <- ({ {|
- ("[..]" %ws? %indent %new_line indented_list ","? ((%dedent (%new_line "..")?) / errors))
+ ("[..]" %ws? %line_comment? %indent %new_line indented_list ","? ((%dedent (%new_line "..")?) / errors))
/ ("[" %ws? (list_items ","?)? %ws?"]")
|} }) -> List
list_items <- ((functioncall / expression) (list_sep list_items)?)
list_sep <- %ws? "," %ws?
indented_list <-
- (functioncall / expression) (((list_sep %new_line?) / %new_line) indented_list)?
+ (functioncall / expression) (((list_sep (%line_comment? %new_line)?) / (%line_comment? %new_line)) indented_list)?
]=]
lingo = make_parser(lingo)
local tree = lingo:match(str:gsub("\r", "") .. "\n")
diff --git a/nomsu.moon b/nomsu.moon
index bb98f1e..d0b9723 100755
--- a/nomsu.moon
+++ b/nomsu.moon
@@ -18,16 +18,10 @@ INDENT = " "
lpeg.setmaxstack 10000 -- whoa
{:P,:V,:S,:Cg,:C,:Cp,:B,:Cmt} = lpeg
-wordchar = P(1)-S(' \t\n\r%:;,.{}[]()"')
-comment = re.compile [[comment <- "(#" (comment / ((! "#)") .))* "#)"]]
-whitespace = (S(" \t") + comment)^1
-nl = P("\n")
-blank_line = whitespace^-1 * nl
-
get_line_indentation = (line)->
indent_amounts = {[" "]:1, ["\t"]:4}
with sum = 0
- leading_space = line\gsub("([\t ]*).*", "%1")
+ leading_space = line\match("[\t ]*")
for c in leading_space\gmatch "[\t ]"
sum += indent_amounts[c]
@@ -50,10 +44,22 @@ make_parser = (lingo, extra_definitions)->
if num_spaces != indent_stack[#indent_stack] then return nil
return end_pos
+ wordchar = P(1)-S(' \t\n\r%#:;,.{}[]()"')
+ nl = P("\n")
+ whitespace = S(" \t")^1
+ blank_line = whitespace^-1 * nl
+ line_comment = re.compile([=[ "#" [^%nl]* ]=], {:nl})
+ block_comment = re.compile([=[
+ "#.." (!%nl .)* (%indent (!%dedent %nl [^%nl]*)*)
+ ]=], {:nl, :whitespace,
+ indent:#(nl * blank_line^0 * Cmt(S(" \t")^0, check_indent)),
+ dedent:#(nl * blank_line^0 * Cmt(S(" \t")^0, check_dedent)),
+ new_line:nl * blank_line^0 * Cmt(S(" \t")^0, check_nodent)})
+ blank_line = ((Cmt(whitespace^-1, check_nodent) * (block_comment + line_comment))^-1 + whitespace^-1) * nl
defs =
- :wordchar, :nl, ws:whitespace, :comment
+ :wordchar, :nl, ws:whitespace, :blank_line, :block_comment, :line_comment
eol: #nl + (P("")-P(1))
- word_boundary: whitespace + B(P("..")) + B(S("\";)]")) + #S("\":([") + #((whitespace + nl)^0 * P(".."))
+ word_boundary: whitespace^-1 + B(P("..")) + B(S("\";)]")) + #S("\":([") + #((whitespace + nl)^0 * P(".."))
indent: #(nl * blank_line^0 * Cmt(whitespace^-1, check_indent))
dedent: #(nl * blank_line^0 * Cmt(whitespace^-1, check_dedent))
new_line: nl * blank_line^0 * Cmt(whitespace^-1, check_nodent)
@@ -162,7 +168,7 @@ class NomsuCompiler
if @debug
print("PARSING:\n#{str}")
lingo = [=[
- file <- ({ {| %ws? %new_line? {:body: block :} %new_line? %ws? (errors)? |} }) -> File
+ file <- ({ {| %blank_line* {:body: block :} %blank_line* (errors)? |} }) -> File
errors <- (({.+}) => error_handler)
block <- ({ {| statement (%new_line statement)* |} }) -> Block
statement <- ({ (functioncall / expression) }) -> Statement
@@ -178,37 +184,37 @@ class NomsuCompiler
functioncall <- ({ {| (expression %word_boundary fn_bits) / (word (%word_boundary fn_bits)?) |} }) -> FunctionCall
fn_bit <- (expression / word)
fn_bits <-
- ((".." %ws? (%indent %new_line indented_fn_bits %dedent) (%new_line ".." %ws? fn_bits)?)
+ ((".." %ws? %line_comment? (%indent %new_line indented_fn_bits %dedent) (%new_line ".." %ws? fn_bits)?)
/ (%new_line ".." fn_bit (%word_boundary fn_bits)?)
/ (fn_bit (%word_boundary fn_bits)?))
indented_fn_bits <-
fn_bit ((%new_line / %word_boundary) indented_fn_bits)?
thunk <-
- ({ ":" %ws?
+ ({ ":" %ws? %line_comment?
((%indent %new_line block ((%dedent (%new_line "..")?) / errors))
/ (one_liner (%ws? (%new_line? ".."))?)) }) -> Thunk
word <- ({ !number {%wordchar+} }) -> Word
expression <- ({ (longstring / string / number / variable / list / thunk / subexpression) }) -> Expression
- string <- ({ (!longstring) '"' {(("\" .) / [^"])*} '"' }) -> String
- longstring <- ({ '".."' %ws? %indent {(%new_line "|" [^%nl]*)+} ((%dedent (%new_line '..')?) / errors) }) -> Longstring
+ string <- ({ (!longstring) '"' {(("\" [^%nl]) / [^"%nl])*} '"' }) -> String
+ longstring <- ({ '".."' %ws? %line_comment? %indent {(%new_line "|" [^%nl]*)+} ((%dedent (%new_line '..')?) / errors) }) -> Longstring
number <- ({ {'-'? [0-9]+ ("." [0-9]+)?} }) -> Number
variable <- ({ ("%" {%wordchar+}) }) -> Var
subexpression <-
- (!%comment "(" %ws? (functioncall / expression) %ws? ")")
- / ("(..)" %ws? %indent %new_line ((({ {| indented_fn_bits |} }) -> FunctionCall) / expression) %dedent (%new_line "..")?)
+ ("(" %ws? (functioncall / expression) %ws? ")")
+ / ("(..)" %ws? %line_comment? %indent %new_line ((({ {| indented_fn_bits |} }) -> FunctionCall) / expression) %dedent (%new_line "..")?)
list <- ({ {|
- ("[..]" %ws? %indent %new_line indented_list ","? ((%dedent (%new_line "..")?) / errors))
+ ("[..]" %ws? %line_comment? %indent %new_line indented_list ","? ((%dedent (%new_line "..")?) / errors))
/ ("[" %ws? (list_items ","?)? %ws?"]")
|} }) -> List
list_items <- ((functioncall / expression) (list_sep list_items)?)
list_sep <- %ws? "," %ws?
indented_list <-
- (functioncall / expression) (((list_sep %new_line?) / %new_line) indented_list)?
+ (functioncall / expression) (((list_sep (%line_comment? %new_line)?) / (%line_comment? %new_line)) indented_list)?
]=]
lingo = make_parser lingo