Changed comments to use # and #.. instead of (# #), which is more
consistent with the language's attitude towards code blocks and indentation. No more long-range action closing parens.
This commit is contained in:
parent
6b5fbd436b
commit
0f228d2d25
8
core.nom
8
core.nom
@ -1,4 +1,3 @@
|
|||||||
(# Global import #)
|
|
||||||
lua block ".."
|
lua block ".."
|
||||||
|utils = require('utils')
|
|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 mod %b": concat ["(",%a as lua expr," mod ",%b as lua expr,")"]
|
||||||
macro "- %a": concat ["-(",%a as lua expr,")"]
|
macro "- %a": concat ["-(",%a as lua expr,")"]
|
||||||
macro "not %a": concat ["not (",%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":
|
rule "%a == %b":
|
||||||
lua expr "utils.equivalent(vars.a, vars.b)"
|
lua expr "((vars.a == vars.b) or utils.equivalent(vars.a, vars.b))"
|
||||||
macro "%a != %b": concat ["not (",%a as lua expr," == ",%b as lua expr,")"]
|
rule "%a != %b":
|
||||||
|
lua expr "((vars.a ~= vars.b) or not utils.equivalent(vars.a, vars.b))"
|
||||||
|
|
||||||
rule "say %str":
|
rule "say %str":
|
||||||
lua block ["print(utils.repr(", %str, "))"]
|
lua block ["print(utils.repr(", %str, "))"]
|
||||||
|
15
examples/sample_code.nom
Executable file → Normal file
15
examples/sample_code.nom
Executable file → Normal file
@ -1,18 +1,21 @@
|
|||||||
(# This is just a comment #)
|
# This is just a comment
|
||||||
(# Nested comments (# like this #) work fine #)
|
#.. Block comments
|
||||||
|
start with a #.. and
|
||||||
|
continue until dedent
|
||||||
|
|
||||||
run file "core.nom"
|
run file "core.nom"
|
||||||
|
|
||||||
say "foo"
|
say "foo"
|
||||||
|
|
||||||
say (4)
|
say (4)
|
||||||
|
|
||||||
(# "rule" is just a function that takes a function call spec and a block of code to run,
|
#.. "rule" is just a function that takes a function call spec and a block of code to run,
|
||||||
and stores the function definition #)
|
and stores the function definition
|
||||||
rule "fart": say "poot"
|
rule "fart": say "poot"
|
||||||
|
|
||||||
fart
|
fart
|
||||||
|
|
||||||
(# multi-line strings: #)
|
# multi-line strings:
|
||||||
say ".."
|
say ".."
|
||||||
| Once upon a time
|
| Once upon a time
|
||||||
|there was a very
|
|there was a very
|
||||||
@ -30,7 +33,7 @@ say ".."
|
|||||||
|(done)
|
|(done)
|
||||||
|
|
|
|
||||||
|
|
||||||
rule "doublefart": (# this farts twice #)
|
rule "doublefart": # this farts twice
|
||||||
say "poot"
|
say "poot"
|
||||||
say "poot"
|
say "poot"
|
||||||
|
|
||||||
|
@ -31,13 +31,13 @@ rule "you":
|
|||||||
lua expr "(you or 'Anonymous')"
|
lua expr "(you or 'Anonymous')"
|
||||||
|
|
||||||
rule ["make %person %action", "make %person do %action"]:
|
rule ["make %person %action", "make %person do %action"]:
|
||||||
lua block [..]
|
lua block ".."
|
||||||
"do"
|
|do
|
||||||
"\n local old_you = you"
|
| local old_you = you
|
||||||
"\n you = vars.person"
|
| you = vars.person
|
||||||
"\n ret = compiler:call('do %', vars.action)"
|
| ret = compiler:call('do %', vars.action)
|
||||||
"\n you = old_you"
|
| you = old_you
|
||||||
"\nend"
|
|end
|
||||||
|
|
||||||
say "===================================================="
|
say "===================================================="
|
||||||
say " NEW GAME"
|
say " NEW GAME"
|
||||||
|
@ -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"
|
run file "core.nom"
|
||||||
|
|
||||||
(# Numbers: #)
|
# Numbers:
|
||||||
23
|
23
|
||||||
4.5
|
4.5
|
||||||
(# Since this language cross-compiles to lua, integers and floating point numbers are
|
#.. Since this language cross-compiles to lua, integers and floating point numbers are
|
||||||
both represented using the same primitive. #)
|
both represented using the same primitive.
|
||||||
|
|
||||||
(# Strings: #)
|
# Strings:
|
||||||
"asdf"
|
"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 "|"
|
|that starts with ".." and includes each indented line that starts with a "|"
|
||||||
|until the indentation ends
|
|until the indentation ends
|
||||||
|
|
||||||
(# Lists: #)
|
# Lists:
|
||||||
[1,2,3]
|
[1,2,3]
|
||||||
[..]
|
[..]
|
||||||
"like multi-line strings, lists have an indented form", "that can use commas too"
|
"like multi-line strings, lists have an indented form", "that can use commas too"
|
||||||
@ -24,73 +26,73 @@ run file "core.nom"
|
|||||||
5
|
5
|
||||||
6,7,8
|
6,7,8
|
||||||
|
|
||||||
(# Function calls: #)
|
# Function calls:
|
||||||
say "Hello world!"
|
say "Hello world!"
|
||||||
|
|
||||||
(# Function definition: #)
|
# Function definition:
|
||||||
rule "say both %first and also %second":
|
rule "say both %first and also %second":
|
||||||
(# Variables use the "%" sign: #)
|
# Variables use the "%" sign:
|
||||||
say %first
|
say %first
|
||||||
say %second
|
say %second
|
||||||
|
|
||||||
(# Function calls can have parts of the function's name spread throughout.
|
#.. 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 #)
|
Everything that's not a literal value is treated as part of the function's name
|
||||||
say both "Hello" and also "again!"
|
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":
|
rule "%what-she-said is what she said":
|
||||||
say %what-she-said
|
say %what-she-said
|
||||||
say "-- she said"
|
say "-- she said"
|
||||||
"Howdy pardner" is what she said
|
"Howdy pardner" is what she said
|
||||||
|
|
||||||
(# The language only reserves []{}().,:;% as special characters, so functions and variables
|
#.. The language only reserves []{}().,:;% as special characters, so functions and variables
|
||||||
can have really funky names! #)
|
can have really funky names!
|
||||||
rule ">> %foo-bar###^ --> %@@& _~-^-~_~-^ %1 !":
|
rule ">> %foo-bar$$$^ --> %@@& _~-^-~_~-^ %1 !":
|
||||||
say %foo-bar###^
|
say %foo-bar$$$^
|
||||||
say %@@&
|
say %@@&
|
||||||
say %1
|
say %1
|
||||||
>> "wow" --> "so flexible!" _~-^-~_~-^ "even numbers can be variables!" !
|
>> "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)
|
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)
|
rule "%a ++ %b": 2 * (%a + %b)
|
||||||
say (2 ++ 3)
|
say (2 ++ 3)
|
||||||
|
|
||||||
|
|
||||||
(# Code blocks start with ":" and either continue until the end of the line
|
#.. Code blocks start with ":" and either continue until the end of the line
|
||||||
or are indented blocks #)
|
or are indented blocks
|
||||||
|
|
||||||
(# One liner: #)
|
# One liner:
|
||||||
: say "hi"
|
: say "hi"
|
||||||
|
|
||||||
(# Block version: #)
|
# Block version:
|
||||||
:
|
:
|
||||||
say "one"
|
say "one"
|
||||||
say "two"
|
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 % %"
|
"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..
|
say..
|
||||||
both "Tom" and
|
both "Tom" and
|
||||||
also
|
also
|
||||||
"Sawyer"
|
"Sawyer"
|
||||||
|
|
||||||
(# Or by starting the next line with ".." #)
|
# Or by starting the next line with ".."
|
||||||
say both "Bruce"
|
say both "Bruce"
|
||||||
..and also "Lee"
|
..and also "Lee"
|
||||||
|
|
||||||
(# This can be mixed and matched: #)
|
# This can be mixed and matched:
|
||||||
say both..
|
say both..
|
||||||
"Rick"
|
"Rick"
|
||||||
..and also..
|
..and also..
|
||||||
"Moranis"
|
"Moranis"
|
||||||
|
|
||||||
(# And combined with the block forms of literals: #)
|
# And combined with the block forms of literals:
|
||||||
say both ".."
|
say both ".."
|
||||||
|Four score and seven years ago our fathers brought forth, upon this continent,
|
|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
|
|a new nation, conceived in liberty, and dedicated to the proposition that
|
||||||
@ -99,31 +101,31 @@ say both ".."
|
|||||||
"-- Abraham Lincoln"
|
"-- Abraham Lincoln"
|
||||||
|
|
||||||
rule "my favorite number": return 23
|
rule "my favorite number": return 23
|
||||||
(# Subexpressions are wrapped in parentheses: #)
|
# Subexpressions are wrapped in parentheses:
|
||||||
(# printf takes a list of bits that are converted to strings and concatenated together, and printed #)
|
# printf takes a list of bits that are converted to strings and concatenated together, and printed
|
||||||
printf ["My favorite number is ", my favorite number]
|
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 [..]
|
printf [..]
|
||||||
"My favorite number is still ", (..)
|
"My favorite number is still ", (..)
|
||||||
my favorite
|
my favorite
|
||||||
number
|
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.
|
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):
|
if (1 < 10):
|
||||||
say "One is less than ten"
|
say "One is less than ten"
|
||||||
..else:
|
..else:
|
||||||
say "One is not less than ten"
|
say "One is not less than ten"
|
||||||
|
|
||||||
(# Breakdown of the above: #)
|
#.. Breakdown of the above:
|
||||||
(# Function call (actually a macro) to "if % % else %" #)
|
Function call (actually a macro) to "if % % else %"
|
||||||
(# First argument is a subexpression that is a function call (also a macro) to "% < %"
|
First argument is a subexpression that is a function call (also a macro) to "% < %"
|
||||||
that performs a comparison on its arguments, 1 and 10 #)
|
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 #)
|
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 #)
|
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):
|
if (1 > 10):
|
||||||
say "First condition"
|
say "First condition"
|
||||||
..else: if (1 > 5):
|
..else: if (1 > 5):
|
||||||
@ -131,7 +133,7 @@ if (1 > 10):
|
|||||||
..else:
|
..else:
|
||||||
say "Last condition"
|
say "Last condition"
|
||||||
|
|
||||||
(# ^that's the same as: #)
|
# ^that's the same as:
|
||||||
if (1 > 10):
|
if (1 > 10):
|
||||||
say "First condition"
|
say "First condition"
|
||||||
..else:
|
..else:
|
||||||
@ -140,10 +142,10 @@ if (1 > 10):
|
|||||||
..else:
|
..else:
|
||||||
say "Last condition"
|
say "Last condition"
|
||||||
|
|
||||||
(# Variables are modified with a macro, "let % = %" #)
|
# Variables are modified with a macro, "let % = %"
|
||||||
let "numbers" = [5,6,7]
|
let "numbers" = [5,6,7]
|
||||||
|
|
||||||
(# Looping: #)
|
# Looping:
|
||||||
printf ["Looping over: ",%numbers,"!"]
|
printf ["Looping over: ",%numbers,"!"]
|
||||||
for "number" in %numbers:
|
for "number" in %numbers:
|
||||||
say (%number + 100)
|
say (%number + 100)
|
||||||
@ -158,45 +160,45 @@ rule "sing %starting-bottles bottles of beer":
|
|||||||
|
|
||||||
sing 9 bottles of beer
|
sing 9 bottles of beer
|
||||||
|
|
||||||
|
#.. Note that because math and logic operations are just macros, they require a lot
|
||||||
(# Note that because math and logic operations are just macros, they require a lot
|
of parentheses to disambiguate. There's no PEMDAS.
|
||||||
of parentheses to disambiguate. There's no PEMDAS. #)
|
|
||||||
say (5 + (4 * (- (1 + (6 + 2)))))
|
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 * 2 * 3 * 4
|
1 * 2 * 3 * 4
|
||||||
1 and 2 and 3 and 4
|
1 and 2 and 3 and 4
|
||||||
1 or 2 or 3 or 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]
|
sum of [1,2,3,4,5,6,7]
|
||||||
product 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]
|
all of [1,1,1,1,0,1,1]
|
||||||
any of [0,0,0,0,1,0,0]
|
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
|
1 < 2 <= 3
|
||||||
|
|
||||||
|
|
||||||
(# Macros: #)
|
# Macros:
|
||||||
(# The "lua block %" and "lua expr %" macros can be used to write raw lua code: #)
|
# The "lua block %" and "lua expr %" macros can be used to write raw lua code:
|
||||||
rule "say the time":
|
rule "say the time":
|
||||||
lua block ".."
|
lua block ".."
|
||||||
|io.write("The OS time is: ")
|
|io.write("The OS time is: ")
|
||||||
|io.write(tostring(os.time()).."\n")
|
|io.write(tostring(os.time()).."\n")
|
||||||
say the time
|
say the time
|
||||||
printf ["Math expression result is: ", lua expr "(1 + 2*3 + 3*4)^2"]
|
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":
|
rule "square root of %n":
|
||||||
return (lua expr "math.sqrt(vars.n)")
|
return (lua expr "math.sqrt(vars.n)")
|
||||||
printf ["the square root of 2 is ", square root of 2]
|
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 #)
|
# 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 %" is for defining macros that produce blocks of code, not values
|
||||||
macro block "unless %condition %body":
|
macro block "unless %condition %body":
|
||||||
concat [..]
|
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"
|
"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
|
"\n ", (lua expr "vars.body.value.value") as lua block
|
||||||
"\nend"
|
"\nend"
|
||||||
|
|
||||||
@ -204,7 +206,7 @@ unless (1 > 10):
|
|||||||
say "Macros work!"
|
say "Macros work!"
|
||||||
say "It looks like a keyword, but there's no magic here!"
|
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":
|
macro "%value as a boolean":
|
||||||
concat ["(not not (", %value as lua expr, "))"]
|
concat ["(not not (", %value as lua expr, "))"]
|
||||||
macro "yep": "true"
|
macro "yep": "true"
|
||||||
|
47
nomsu.lua
47
nomsu.lua
@ -5,11 +5,6 @@ local INDENT = " "
|
|||||||
lpeg.setmaxstack(10000)
|
lpeg.setmaxstack(10000)
|
||||||
local P, V, S, Cg, C, Cp, B, Cmt
|
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
|
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
|
local get_line_indentation
|
||||||
get_line_indentation = function(line)
|
get_line_indentation = function(line)
|
||||||
local indent_amounts = {
|
local indent_amounts = {
|
||||||
@ -18,7 +13,7 @@ get_line_indentation = function(line)
|
|||||||
}
|
}
|
||||||
do
|
do
|
||||||
local sum = 0
|
local sum = 0
|
||||||
local leading_space = line:gsub("([\t ]*).*", "%1")
|
local leading_space = line:match("[\t ]*")
|
||||||
for c in leading_space:gmatch("[\t ]") do
|
for c in leading_space:gmatch("[\t ]") do
|
||||||
sum = sum + indent_amounts[c]
|
sum = sum + indent_amounts[c]
|
||||||
end
|
end
|
||||||
@ -64,13 +59,31 @@ make_parser = function(lingo, extra_definitions)
|
|||||||
end
|
end
|
||||||
return end_pos
|
return end_pos
|
||||||
end
|
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 = {
|
local defs = {
|
||||||
wordchar = wordchar,
|
wordchar = wordchar,
|
||||||
nl = nl,
|
nl = nl,
|
||||||
ws = whitespace,
|
ws = whitespace,
|
||||||
comment = comment,
|
blank_line = blank_line,
|
||||||
|
block_comment = block_comment,
|
||||||
|
line_comment = line_comment,
|
||||||
eol = #nl + (P("") - P(1)),
|
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)),
|
indent = #(nl * blank_line ^ 0 * Cmt(whitespace ^ -1, check_indent)),
|
||||||
dedent = #(nl * blank_line ^ 0 * Cmt(whitespace ^ -1, check_dedent)),
|
dedent = #(nl * blank_line ^ 0 * Cmt(whitespace ^ -1, check_dedent)),
|
||||||
new_line = nl * blank_line ^ 0 * Cmt(whitespace ^ -1, check_nodent),
|
new_line = nl * blank_line ^ 0 * Cmt(whitespace ^ -1, check_nodent),
|
||||||
@ -244,7 +257,7 @@ do
|
|||||||
if self.debug then
|
if self.debug then
|
||||||
print("PARSING:\n" .. tostring(str))
|
print("PARSING:\n" .. tostring(str))
|
||||||
end
|
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)
|
errors <- (({.+}) => error_handler)
|
||||||
block <- ({ {| statement (%new_line statement)* |} }) -> Block
|
block <- ({ {| statement (%new_line statement)* |} }) -> Block
|
||||||
statement <- ({ (functioncall / expression) }) -> Statement
|
statement <- ({ (functioncall / expression) }) -> Statement
|
||||||
@ -260,37 +273,37 @@ do
|
|||||||
functioncall <- ({ {| (expression %word_boundary fn_bits) / (word (%word_boundary fn_bits)?) |} }) -> FunctionCall
|
functioncall <- ({ {| (expression %word_boundary fn_bits) / (word (%word_boundary fn_bits)?) |} }) -> FunctionCall
|
||||||
fn_bit <- (expression / word)
|
fn_bit <- (expression / word)
|
||||||
fn_bits <-
|
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)?)
|
/ (%new_line ".." fn_bit (%word_boundary fn_bits)?)
|
||||||
/ (fn_bit (%word_boundary fn_bits)?))
|
/ (fn_bit (%word_boundary fn_bits)?))
|
||||||
indented_fn_bits <-
|
indented_fn_bits <-
|
||||||
fn_bit ((%new_line / %word_boundary) indented_fn_bits)?
|
fn_bit ((%new_line / %word_boundary) indented_fn_bits)?
|
||||||
|
|
||||||
thunk <-
|
thunk <-
|
||||||
({ ":" %ws?
|
({ ":" %ws? %line_comment?
|
||||||
((%indent %new_line block ((%dedent (%new_line "..")?) / errors))
|
((%indent %new_line block ((%dedent (%new_line "..")?) / errors))
|
||||||
/ (one_liner (%ws? (%new_line? ".."))?)) }) -> Thunk
|
/ (one_liner (%ws? (%new_line? ".."))?)) }) -> Thunk
|
||||||
|
|
||||||
word <- ({ !number {%wordchar+} }) -> Word
|
word <- ({ !number {%wordchar+} }) -> Word
|
||||||
expression <- ({ (longstring / string / number / variable / list / thunk / subexpression) }) -> Expression
|
expression <- ({ (longstring / string / number / variable / list / thunk / subexpression) }) -> Expression
|
||||||
|
|
||||||
string <- ({ (!longstring) '"' {(("\" .) / [^"])*} '"' }) -> String
|
string <- ({ (!longstring) '"' {(("\" [^%nl]) / [^"%nl])*} '"' }) -> String
|
||||||
longstring <- ({ '".."' %ws? %indent {(%new_line "|" [^%nl]*)+} ((%dedent (%new_line '..')?) / errors) }) -> Longstring
|
longstring <- ({ '".."' %ws? %line_comment? %indent {(%new_line "|" [^%nl]*)+} ((%dedent (%new_line '..')?) / errors) }) -> Longstring
|
||||||
number <- ({ {'-'? [0-9]+ ("." [0-9]+)?} }) -> Number
|
number <- ({ {'-'? [0-9]+ ("." [0-9]+)?} }) -> Number
|
||||||
variable <- ({ ("%" {%wordchar+}) }) -> Var
|
variable <- ({ ("%" {%wordchar+}) }) -> Var
|
||||||
|
|
||||||
subexpression <-
|
subexpression <-
|
||||||
(!%comment "(" %ws? (functioncall / expression) %ws? ")")
|
("(" %ws? (functioncall / expression) %ws? ")")
|
||||||
/ ("(..)" %ws? %indent %new_line ((({ {| indented_fn_bits |} }) -> FunctionCall) / expression) %dedent (%new_line "..")?)
|
/ ("(..)" %ws? %line_comment? %indent %new_line ((({ {| indented_fn_bits |} }) -> FunctionCall) / expression) %dedent (%new_line "..")?)
|
||||||
|
|
||||||
list <- ({ {|
|
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?"]")
|
/ ("[" %ws? (list_items ","?)? %ws?"]")
|
||||||
|} }) -> List
|
|} }) -> List
|
||||||
list_items <- ((functioncall / expression) (list_sep list_items)?)
|
list_items <- ((functioncall / expression) (list_sep list_items)?)
|
||||||
list_sep <- %ws? "," %ws?
|
list_sep <- %ws? "," %ws?
|
||||||
indented_list <-
|
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)
|
lingo = make_parser(lingo)
|
||||||
local tree = lingo:match(str:gsub("\r", "") .. "\n")
|
local tree = lingo:match(str:gsub("\r", "") .. "\n")
|
||||||
|
42
nomsu.moon
42
nomsu.moon
@ -18,16 +18,10 @@ INDENT = " "
|
|||||||
lpeg.setmaxstack 10000 -- whoa
|
lpeg.setmaxstack 10000 -- whoa
|
||||||
{:P,:V,:S,:Cg,:C,:Cp,:B,:Cmt} = lpeg
|
{: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)->
|
get_line_indentation = (line)->
|
||||||
indent_amounts = {[" "]:1, ["\t"]:4}
|
indent_amounts = {[" "]:1, ["\t"]:4}
|
||||||
with sum = 0
|
with sum = 0
|
||||||
leading_space = line\gsub("([\t ]*).*", "%1")
|
leading_space = line\match("[\t ]*")
|
||||||
for c in leading_space\gmatch "[\t ]"
|
for c in leading_space\gmatch "[\t ]"
|
||||||
sum += indent_amounts[c]
|
sum += indent_amounts[c]
|
||||||
|
|
||||||
@ -50,10 +44,22 @@ make_parser = (lingo, extra_definitions)->
|
|||||||
if num_spaces != indent_stack[#indent_stack] then return nil
|
if num_spaces != indent_stack[#indent_stack] then return nil
|
||||||
return end_pos
|
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 =
|
defs =
|
||||||
:wordchar, :nl, ws:whitespace, :comment
|
:wordchar, :nl, ws:whitespace, :blank_line, :block_comment, :line_comment
|
||||||
eol: #nl + (P("")-P(1))
|
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))
|
indent: #(nl * blank_line^0 * Cmt(whitespace^-1, check_indent))
|
||||||
dedent: #(nl * blank_line^0 * Cmt(whitespace^-1, check_dedent))
|
dedent: #(nl * blank_line^0 * Cmt(whitespace^-1, check_dedent))
|
||||||
new_line: nl * blank_line^0 * Cmt(whitespace^-1, check_nodent)
|
new_line: nl * blank_line^0 * Cmt(whitespace^-1, check_nodent)
|
||||||
@ -162,7 +168,7 @@ class NomsuCompiler
|
|||||||
if @debug
|
if @debug
|
||||||
print("PARSING:\n#{str}")
|
print("PARSING:\n#{str}")
|
||||||
lingo = [=[
|
lingo = [=[
|
||||||
file <- ({ {| %ws? %new_line? {:body: block :} %new_line? %ws? (errors)? |} }) -> File
|
file <- ({ {| %blank_line* {:body: block :} %blank_line* (errors)? |} }) -> File
|
||||||
errors <- (({.+}) => error_handler)
|
errors <- (({.+}) => error_handler)
|
||||||
block <- ({ {| statement (%new_line statement)* |} }) -> Block
|
block <- ({ {| statement (%new_line statement)* |} }) -> Block
|
||||||
statement <- ({ (functioncall / expression) }) -> Statement
|
statement <- ({ (functioncall / expression) }) -> Statement
|
||||||
@ -178,37 +184,37 @@ class NomsuCompiler
|
|||||||
functioncall <- ({ {| (expression %word_boundary fn_bits) / (word (%word_boundary fn_bits)?) |} }) -> FunctionCall
|
functioncall <- ({ {| (expression %word_boundary fn_bits) / (word (%word_boundary fn_bits)?) |} }) -> FunctionCall
|
||||||
fn_bit <- (expression / word)
|
fn_bit <- (expression / word)
|
||||||
fn_bits <-
|
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)?)
|
/ (%new_line ".." fn_bit (%word_boundary fn_bits)?)
|
||||||
/ (fn_bit (%word_boundary fn_bits)?))
|
/ (fn_bit (%word_boundary fn_bits)?))
|
||||||
indented_fn_bits <-
|
indented_fn_bits <-
|
||||||
fn_bit ((%new_line / %word_boundary) indented_fn_bits)?
|
fn_bit ((%new_line / %word_boundary) indented_fn_bits)?
|
||||||
|
|
||||||
thunk <-
|
thunk <-
|
||||||
({ ":" %ws?
|
({ ":" %ws? %line_comment?
|
||||||
((%indent %new_line block ((%dedent (%new_line "..")?) / errors))
|
((%indent %new_line block ((%dedent (%new_line "..")?) / errors))
|
||||||
/ (one_liner (%ws? (%new_line? ".."))?)) }) -> Thunk
|
/ (one_liner (%ws? (%new_line? ".."))?)) }) -> Thunk
|
||||||
|
|
||||||
word <- ({ !number {%wordchar+} }) -> Word
|
word <- ({ !number {%wordchar+} }) -> Word
|
||||||
expression <- ({ (longstring / string / number / variable / list / thunk / subexpression) }) -> Expression
|
expression <- ({ (longstring / string / number / variable / list / thunk / subexpression) }) -> Expression
|
||||||
|
|
||||||
string <- ({ (!longstring) '"' {(("\" .) / [^"])*} '"' }) -> String
|
string <- ({ (!longstring) '"' {(("\" [^%nl]) / [^"%nl])*} '"' }) -> String
|
||||||
longstring <- ({ '".."' %ws? %indent {(%new_line "|" [^%nl]*)+} ((%dedent (%new_line '..')?) / errors) }) -> Longstring
|
longstring <- ({ '".."' %ws? %line_comment? %indent {(%new_line "|" [^%nl]*)+} ((%dedent (%new_line '..')?) / errors) }) -> Longstring
|
||||||
number <- ({ {'-'? [0-9]+ ("." [0-9]+)?} }) -> Number
|
number <- ({ {'-'? [0-9]+ ("." [0-9]+)?} }) -> Number
|
||||||
variable <- ({ ("%" {%wordchar+}) }) -> Var
|
variable <- ({ ("%" {%wordchar+}) }) -> Var
|
||||||
|
|
||||||
subexpression <-
|
subexpression <-
|
||||||
(!%comment "(" %ws? (functioncall / expression) %ws? ")")
|
("(" %ws? (functioncall / expression) %ws? ")")
|
||||||
/ ("(..)" %ws? %indent %new_line ((({ {| indented_fn_bits |} }) -> FunctionCall) / expression) %dedent (%new_line "..")?)
|
/ ("(..)" %ws? %line_comment? %indent %new_line ((({ {| indented_fn_bits |} }) -> FunctionCall) / expression) %dedent (%new_line "..")?)
|
||||||
|
|
||||||
list <- ({ {|
|
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?"]")
|
/ ("[" %ws? (list_items ","?)? %ws?"]")
|
||||||
|} }) -> List
|
|} }) -> List
|
||||||
list_items <- ((functioncall / expression) (list_sep list_items)?)
|
list_items <- ((functioncall / expression) (list_sep list_items)?)
|
||||||
list_sep <- %ws? "," %ws?
|
list_sep <- %ws? "," %ws?
|
||||||
indented_list <-
|
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
|
lingo = make_parser lingo
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user