aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBruce Hill <bitbucket@bruce-hill.com>2017-10-13 19:41:58 -0700
committerBruce Hill <bitbucket@bruce-hill.com>2017-10-13 19:41:58 -0700
commitbccfe9d8e12ba024c745cd533f73987439c76499 (patch)
treec2df6f49a9a6ddae962140848da02fd446b50d4b
parent56f014a4884d7df387ff2ffa34fa95f1cc8b1f16 (diff)
Changed tokenizing to treat symbols as their own things.
-rw-r--r--examples/how_do_i.nom37
-rw-r--r--examples/sample_game.nom12
-rw-r--r--lib/collections.nom43
-rw-r--r--lib/control_flow.nom62
-rw-r--r--lib/operators.nom4
-rw-r--r--lib/permissions.nom24
-rw-r--r--lib/plurals.nom4
-rw-r--r--nomsu.lua18
-rwxr-xr-xnomsu.moon19
9 files changed, 132 insertions, 91 deletions
diff --git a/examples/how_do_i.nom b/examples/how_do_i.nom
index 486ea19..2365627 100644
--- a/examples/how_do_i.nom
+++ b/examples/how_do_i.nom
@@ -49,7 +49,7 @@ say "Hello world!"
# Use a list?
%my_list = ["first item", "second item", "third item"]
# Lists are 1-indexed because they're implemented as Lua tables, so this prints "first item"
-say (%my_list -> 1)
+say (%my_list->1)
# These do the same thing:
say (%my_list's 1)
say (1 in %my_list)
@@ -58,7 +58,12 @@ say (1 in %my_list)
say (size of %my_list)
# Define a dictionary/hash map?
-# Dicts are created by passing a list of key-value pairs to the function "dict"
+%my_dict = (dict {x = 99; y = 101})
+%my_dict = (..)
+ dict:
+ x = 101
+ "99 bottles" = 99
+ 653 = 292
%my_dict = (dict [["x", 99], ["y", 101]])
# Use a dict?
@@ -175,11 +180,11 @@ say (first fibonacci above 10)
# Functions can have aliases, which may or may not have the arguments in different order
rule [..]
- I hate %worse-things more than %better-things
- I think %worse-things are worse than %better-things
- I like %better-things more than %worse-things
+ I hate %worse_things more than %better_things
+ I think %worse_things are worse than %better_things
+ I like %better_things more than %worse_things
..=:
- say "\(%better-things capitalized) rule and \(%worse-things) drool!"
+ say "\(%better_things capitalized) rule and \(%worse_things) drool!"
I like "dogs" more than "cats"
I think "chihuahuas" are worse than "corgis"
@@ -190,20 +195,26 @@ I think "chihuahuas" are worse than "corgis"
say both "Hello" and also "again!"
# Functions can even have their name at the end:
-rule [%what-she-said is what she said] =:
- say %what-she-said
+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
+#.. The language only reserves []{}().,:;% as special characters, so functions
can have really funky names!
-rule [>> %foo-bar$$$^ --> %@@& _~-^-~_~-^ %1 !] =:
- say %foo-bar$$$^
- say %@@&
+rule [>> %foo_bar $$$^ --> %@ @& _~-^-~_~-^ %1 !] =:
+ say %foo_bar
+ say %@
say %1
->> "wow" --> "so flexible!" _~-^-~_~-^ "even numbers can be variables!" !
+>> "wow" $$$^ --> "so flexible!" @& _~-^-~_~-^ "even numbers can be variables!" !
+
+#.. The all of the following are characters won't "stick" to their neighbors, so the
+ compiler treats them as solitary single-character tokens: '~`!@$^&*-+=|<>?/
+ which means you can jam things together:
+rule [%x++%y] =: 2*(%x+%y)
+(5++2) == ( 5 ++ 2 )
# Math and logic operations are just treated the same as function calls in the syntax
say (2 + 3)
diff --git a/examples/sample_game.nom b/examples/sample_game.nom
index 3698fb4..a6a792d 100644
--- a/examples/sample_game.nom
+++ b/examples/sample_game.nom
@@ -30,7 +30,7 @@ with secrets:
| return t;
|end});
- rule [inventory] =: dict:
+ rule [inventory] =: dict (..)
[%inv's "key", dict (%entry for %entry in (entries in (%inv's "value")))]
..for %inv in (entries in (secret %inventory))
@@ -207,16 +207,16 @@ propose:
rule [vote for %candidate] =:
for %c in (secret %candidates):
if (%c == %candidate):
- go to %candidate-is-legit
+ go to %candidate_is_legit
error ".."
|Invalid candidate: \(%candidate)
- -> %candidate-is-legit
+ -> %candidate_is_legit
(secret %votes)->(you) =: %candidate
- %vote-percent = ((number of (votes for %candidate)) / (number of (everyone)))
+ %vote_percent = ((number of (votes for %candidate)) / (number of (everyone)))
say ".."
- |Vote cast. \(%candidate) now has \(100 * %vote-percent)% of the votes.
- if (%vote-percent > 0.5):
+ |Vote cast. \(%candidate) now has \(100 * %vote_percent)% of the votes.
+ if (%vote_percent > 0.5):
secret %winner = %candidate
after winning a fair election do (secret %action)
close the election
diff --git a/lib/collections.nom b/lib/collections.nom
index 022c1dc..5958bb9 100644
--- a/lib/collections.nom
+++ b/lib/collections.nom
@@ -19,7 +19,7 @@ parse [first in %list, first %list] as: 1 st in %list
parse [last in %list, last %list] as: 1 st to last in %list
# Dict iteration convenience function. This could also be accomplished with: for all (entries in %dict): ...
-compile [for %key -> %value in %dict %body] to code: ".."
+compile [for %key = %value in %dict %body] to code: ".."
|do;
| for k, v in pairs(\(%dict as lua)) do;
| \(%key as lua), \(%value as lua) = k, v;
@@ -29,7 +29,7 @@ compile [for %key -> %value in %dict %body] to code: ".."
# Membership testing
rule [%item is in %list, %list contains %item, %list has %item] =:
- for %key -> %value in %list:
+ for %key = %value in %list:
if (%key == %item): return (yes)
return (no)
@@ -38,7 +38,7 @@ rule [..]
%list doesn't contain %item, %list does not contain %item
%list doesn't have %item, %list does not have %item
..=:
- for %key -> %value in %list:
+ for %key = %value in %list:
if (%key == %item): return (no)
return (yes)
@@ -87,26 +87,53 @@ rule [flatten %lists] =:
add %item to %flat
%flat
-rule [dict %items] =:
+rule [dict from entries %items] =:
%dict = []
for %pair in %items:
%dict -> (%pair -> 1) = (%pair -> 2)
%dict
+compile [dict %items] to:
+ if ((%items's "type") == "Thunk"):
+ %item_codes = []
+ for %func_call in (%items's "value"):
+ assert ((%func_call's "type") == "FunctionCall") ".."
+ |Invalid format for 'dict' expression. Only literals are allowed.
+ %tokens = (%func_call's "value")
+ %equals = (%tokens -> 2)
+ assert (lua expr "#\(%tokens) == 3 and \(%equals) and \(%equals).type == 'Word' and \(%equals).value == '='") ".."
+ |Invalid format for 'dict' expression. Lines must only have the "% = %" format, not \(%func_call's "src")
+ %key = (%tokens -> 1)
+ lua code ".."
+ |if \(%key).type == "Word" and \(%key).value:match("^[a-zA-Z_][a-zA-Z0-9_]*$") then
+ | \(%key_code) = \(%key).value;
+ |elseif \(%key).type == "Word" then
+ | \(%key_code) = "["..nomsu:repr(\(%key).value).."]";
+ |else
+ | \(\{%key_code = "[\((%key as lua))]"} as lua statements)
+ |end
+ add "\(%key_code) = \((%tokens -> 3) as lua)" to %item_codes
+ return "{\(join %item_codes with glue ",\n")}"
+ ..else:
+ return (..)
+ (..)
+ nomsu "replaced_vars" [\(dict from entries %items), lua expr "vars"]
+ ..as lua
+
rule [entries in %dict] =:
%entries = []
- for %k -> %v in %dict:
- add (dict [["key",%k],["value",%v]]) to %entries
+ for %k = %v in %dict:
+ add (dict {key = %k; value = %v}) to %entries
%entries
rule [keys in %dict] =:
%keys = []
- for %k -> %v in %dict: add %k to %keys
+ for %k = %v in %dict: add %k to %keys
%keys
rule [values in %dict] =:
%values = []
- for %k -> %v in %dict: add %v to %values
+ for %k = %v in %dict: add %v to %values
%values
# List Comprehension
diff --git a/lib/control_flow.nom b/lib/control_flow.nom
index 2c51c50..84aca6c 100644
--- a/lib/control_flow.nom
+++ b/lib/control_flow.nom
@@ -21,7 +21,7 @@ compile [if %condition %if_body else %else_body, unless %condition %else_body el
# Return
compile [return] to code: "do; return; end;"
-compile [return %return-value] to code: "do; return \(%return-value as lua); end;"
+compile [return %return_value] to code: "do; return \(%return_value as lua); end;"
# GOTOs
compile [-> %label] to code: ".."
@@ -44,11 +44,11 @@ rule [tree %tree has function call %call] =:
compile [do next repeat-loop] to code: "goto continue_repeat;"
compile [stop repeat-loop] to code: "goto stop_repeat;"
compile [repeat while %condition %body] to code:
- %continue-labels = (..)
+ %continue_labels = (..)
"\n::continue_repeat::;" if (tree %body has function call \(do next repeat-loop)) else ""
%code = ".."
|while \(%condition as lua) do;
- |\(%body as lua statements)\(%continue-labels)
+ |\(%body as lua statements)\(%continue_labels)
|end;--while-loop
if (tree %body has function call \(stop repeat-loop)):
return ".."
@@ -73,25 +73,25 @@ compile [..]
for %var from %start to %stop by %step %body
for %var from %start to %stop via %step %body
..to code:
- %continue-labels = ""
+ %continue_labels = ""
if (tree %body has function call \(do next for-loop)):
- %continue-labels join= "\n::continue_for::;"
+ %continue_labels join= "\n::continue_for::;"
if (tree %body has function call (nomsu "replaced_vars" [\(do next %), lua expr "{['']=\(%var)}"])):
- %continue-labels join= "\n::continue_\(nomsu "var_to_lua_identifier" [%var])::;"
+ %continue_labels join= "\n::continue_\(nomsu "var_to_lua_identifier" [%var])::;"
%code = ".."
|for i=\(%start as lua),\(%stop as lua),\(%step as lua) do;
# This trashes the loop variables, just like in Python.
|\(%var as lua) = i;
- |\(%body as lua statements)\(%continue-labels)
+ |\(%body as lua statements)\(%continue_labels)
|end;--numeric for-loop
- %stop-labels = ""
+ %stop_labels = ""
if (tree %body has function call \(stop for-loop)):
- %stop-labels join= "\n::stop_for::;"
+ %stop_labels join= "\n::stop_for::;"
if (tree %body has function call (nomsu "replaced_vars" [\(stop %), lua expr "{['']=\(%var)}"])):
- %stop-labels join= "\n::stop_\(nomsu "var_to_lua_identifier" [%var])::;"
- if (%stop-labels != ""): ".."
+ %stop_labels join= "\n::stop_\(nomsu "var_to_lua_identifier" [%var])::;"
+ if (%stop_labels != ""): ".."
|do;--for-loop label scope
- |\(%code)\(%stop-labels)
+ |\(%code)\(%stop_labels)
|end;--for-loop label scope
..else: %code
parse [for %var from %start to %stop %body] as: for %var from %start to %stop via 1 %body
@@ -102,25 +102,25 @@ parse [..]
parse [for all %start to %stop %body] as: for all %start to %stop via 1 %body
compile [for %var in %iterable %body] to code:
- %continue-labels = ""
+ %continue_labels = ""
if (tree %body has function call \(do next for-loop)):
- %continue-labels join= "\n::continue_for::;"
+ %continue_labels join= "\n::continue_for::;"
if (tree %body has function call (nomsu "replaced_vars" [\(do next %), lua expr "{['']=\(%var)}"])):
- %continue-labels join= "\n::continue_\(nomsu "var_to_lua_identifier" [%var])::;"
+ %continue_labels join= "\n::continue_\(nomsu "var_to_lua_identifier" [%var])::;"
%code = ".."
|for i,value in ipairs(\(%iterable as lua)) do;
# This trashes the loop variables, just like in Python.
|\(%var as lua) = value;
- |\(%body as lua statements)\(%continue-labels)
+ |\(%body as lua statements)\(%continue_labels)
|end;--foreach-loop
- %stop-labels = ""
+ %stop_labels = ""
if (tree %body has function call \(stop for-loop)):
- %stop-labels join= "\n::stop_for::;"
+ %stop_labels join= "\n::stop_for::;"
if (tree %body has function call (nomsu "replaced_vars" [\(stop %), lua expr "{['']=\(%var)}"])):
- %stop-labels join= "\n::stop_\(nomsu "var_to_lua_identifier" [%var])::;"
- if (%stop-labels != ""): ".."
+ %stop_labels join= "\n::stop_\(nomsu "var_to_lua_identifier" [%var])::;"
+ if (%stop_labels != ""): ".."
|do;--for-loop label scope
- |\(%code)\(%stop-labels)
+ |\(%code)\(%stop_labels)
|end;--for-loop label scope
..else: %code
parse [for all %iterable %body] as: for % in %iterable %body
@@ -131,10 +131,10 @@ compile [when %body] to code:
%result = ""
%fallthroughs = []
%first = (yes)
- for %func-call in (%body's "value"):
- assert ((%func-call's "type") == "FunctionCall") ".."
+ for %func_call in (%body's "value"):
+ assert ((%func_call's "type") == "FunctionCall") ".."
|Invalid format for 'when' statement. Only '*' blocks are allowed.
- %tokens = (%func-call's "value")
+ %tokens = (%func_call's "value")
%star = (%tokens -> 1)
assert (lua expr "vars.star and vars.star.type == 'Word' and vars.star.value == '*'") ".."
|Invalid format for 'when' statement. Lines must begin with '*'
@@ -146,7 +146,7 @@ compile [when %body] to code:
%action = (%tokens -> 3)
if (%action == (nil)):
lua block "table.insert(vars.fallthroughs, vars.condition)"
- do next %func-call
+ do next %func_call
if (lua expr "vars.condition.type == 'Word' and vars.condition.value == 'else'"):
%result join= ".."
@@ -171,14 +171,14 @@ compile [when %body] to code:
%result
# Switch statement
-compile [when %branch-value == ? %body] to code:
+compile [when %branch_value == ? %body] to code:
%result = ""
%fallthroughs = []
%first = (yes)
- for %func-call in (%body's "value"):
- assert ((%func-call's "type") == "FunctionCall") ".."
+ for %func_call in (%body's "value"):
+ assert ((%func_call's "type") == "FunctionCall") ".."
|Invalid format for 'when' statement. Only '*' blocks are allowed.
- %tokens = (%func-call's "value")
+ %tokens = (%func_call's "value")
%star = (%tokens -> 1)
assert (lua expr "vars.star and vars.star.type == 'Word' and vars.star.value == '*'") ".."
|Invalid format for 'when' statement. Lines must begin with '*'
@@ -190,7 +190,7 @@ compile [when %branch-value == ? %body] to code:
%action = (%tokens -> 3)
if (%action == (nil)):
lua block "table.insert(vars.fallthroughs, vars.condition)"
- do next %func-call
+ do next %func_call
if (lua expr "vars.condition.type == 'Word' and vars.condition.value == 'else'"):
%result join= ".."
@@ -213,7 +213,7 @@ compile [when %branch-value == ? %body] to code:
if (%result != ""):
%result = ".."
|do;--when == ?
- |local branch_value = \(%branch-value as lua);\(%result)
+ |local branch_value = \(%branch_value as lua);\(%result)
|end;
|end;--when == ?
%result
diff --git a/lib/operators.nom b/lib/operators.nom
index 13e6ce4..09bdbcd 100644
--- a/lib/operators.nom
+++ b/lib/operators.nom
@@ -29,7 +29,7 @@ compile [..]
|end)(nomsu, vars)
# Indexing:
-compile [%obj's %key, %obj -> %key] to: "(\(%obj as lua))[\(%key as lua)]"
+compile [%obj'%key, %obj's %key, %obj -> %key] to: "(\(%obj as lua))[\(%key as lua)]"
# Variable assignment operator, and += type versions
compile [%var = %val] to code: "\(%var as lua) = \(%val as lua);"
@@ -90,7 +90,7 @@ lua block ".."
# Chained compairsions (e.g. x < y <= z) are defined up to 3 operands
lua block ".."
|local max_operands = 3;
- |for _,chainers in ipairs({{"<","<="},{">",">="}}) do;
+ |for _,chainers in ipairs({{"<","< ="},{">","> ="}}) do;
| local function recurse(chainers, chain)
# The 1-op versions are already more efficiently defined, and a 0-op version doesnt make sense
| if #chain >= 2 then;
diff --git a/lib/permissions.nom b/lib/permissions.nom
index 1725683..3231b25 100644
--- a/lib/permissions.nom
+++ b/lib/permissions.nom
@@ -15,33 +15,33 @@ rule [standardize rules %rules] =:
keys in %set
-rule [restrict %rules to within %elite-rules] =:
+rule [restrict %rules to within %elite_rules] =:
%rules = (standardize rules %rules)
- %elite-rules = (standardize rules %elite-rules)
- for all (flatten [%elite-rules, %rules]):
+ %elite_rules = (standardize rules %elite_rules)
+ for all (flatten [%elite_rules, %rules]):
assert ((nomsu's "defs") has key %) "Undefined function: \(%)"
for %rule in %rules:
assert (nomsu "check_permission" [%]) ".."
|You do not have permission to restrict permissions for function: \(%)
((nomsu) ->* ["defs",%rule,"whiteset"]) = (..)
- dict ([%, yes] for all %elite-rules)
+ dict ([%, yes] for all %elite_rules)
-rule [allow %elite-rules to use %rules] =:
+rule [allow %elite_rules to use %rules] =:
%rules = (standardize rules %rules)
- %elite-rules = (standardize rules %elite-rules)
- for all (flatten [%elite-rules, %rules]):
+ %elite_rules = (standardize rules %elite_rules)
+ for all (flatten [%elite_rules, %rules]):
assert ((nomsu's "defs") has key %) "Undefined function: \(%)"
for %rule in %rules:
assert (nomsu "check_permission" [%rule]) ".."
|You do not have permission to grant permissions for function: \(%rule)
%whiteset = ((nomsu) ->* ["defs",%rule,"whiteset"])
if (not %whiteset): go to next %rule
- for all %elite-rules: %whiteset -> % = (yes)
+ for all %elite_rules: %whiteset -> % = (yes)
-rule [forbid %pleb-rules to use %rules] =:
+rule [forbid %pleb_rules to use %rules] =:
%rules = (standardize rules %rules)
- %pleb-rules = (standardize rules %pleb-rules)
- for all (flatten [%pleb-rules, %used]):
+ %pleb_rules = (standardize rules %pleb_rules)
+ for all (flatten [%pleb_rules, %used]):
assert ((nomsu's "defs") has key %) "Undefined function: \(%)"
for all %rules:
assert (nomsu "check_permission" [%]) ".."
@@ -50,4 +50,4 @@ rule [forbid %pleb-rules to use %rules] =:
assert %whiteset ".."
|Cannot individually restrict permissions for \(%) because it is currently
|available to everyone. Perhaps you meant to use "restrict % to within %" instead?
- for all %pleb-rules: %whiteset's % = (nil)
+ for all %pleb_rules: %whiteset's % = (nil)
diff --git a/lib/plurals.nom b/lib/plurals.nom
index 347c2e7..da0fa4d 100644
--- a/lib/plurals.nom
+++ b/lib/plurals.nom
@@ -29,7 +29,7 @@ with secrets:
rule [plural %singular] =:
%singular in (secret %plurals)
- rule [canonicalize %item-name] =:
- %item-name in (secret %canonicals)
+ rule [canonicalize %item_name] =:
+ %item_name in (secret %canonicals)
rule [rules that change plurals] =: ["the plural of % is %"]
diff --git a/nomsu.lua b/nomsu.lua
index 28bb36d..cbcbf9e 100644
--- a/nomsu.lua
+++ b/nomsu.lua
@@ -70,7 +70,7 @@ local nomsu = [=[ file <- ({{| shebang?
noeol_statement <- noeol_functioncall / noeol_expression
inline_statement <- inline_functioncall / inline_expression
- inline_thunk <- ({ {| "{" inline_statements "}" |} }) -> Thunk
+ inline_thunk <- ({ {| "{" %ws? inline_statements %ws? "}" |} }) -> Thunk
eol_thunk <- ({ {| ":" %ws? noeol_statements eol |} }) -> Thunk
indented_thunk <- ({ {| (":" / "{..}") indent
statements (nodent statements)*
@@ -82,7 +82,7 @@ local nomsu = [=[ file <- ({{| shebang?
indented_nomsu <- ({("\" expression) }) -> Nomsu
inline_expression <- number / variable / inline_string / inline_list / inline_nomsu
- / inline_thunk / ("(" inline_statement ")")
+ / inline_thunk / ("(" %ws? inline_statement %ws? ")")
noeol_expression <- indented_string / indented_nomsu / indented_list / indented_thunk
/ ("(..)" indent
statement
@@ -101,7 +101,7 @@ local nomsu = [=[ file <- ({{| shebang?
(expression (dotdot / tok_gap))* word ((dotdot / tok_gap) (expression / word))*
|} }) -> FunctionCall
- word <- ({ !number {%wordchar (!"'" %wordchar)*} }) -> Word
+ word <- ({ { %wordbreaker / (!number %wordchar+) } }) -> Word
inline_string <- ({ '"' {|
({~ (("\\" -> "\") / ('\"' -> '"') / ("\n" -> "
@@ -119,7 +119,7 @@ local nomsu = [=[ file <- ({{| shebang?
-- Variables can be nameless (i.e. just %) and can't contain apostrophes
-- which is a hack to allow %foo's to parse as "%foo" and "'s" separately
- variable <- ({ ("%" { (!"'" %wordchar)* }) }) -> Var
+ variable <- ({ ("%" { (%wordbreaker / (%wordchar+))? }) }) -> Var
inline_list <- ({ {|
("[" %ws? ((inline_list_item comma)* inline_list_item comma?)? %ws? "]")
@@ -140,22 +140,24 @@ local nomsu = [=[ file <- ({{| shebang?
indent <- eol (%nl ignored_line)* %nl %indented ((block_comment/line_comment) (%nl ignored_line)* nodent)?
nodent <- eol (%nl ignored_line)* %nl %nodented
dedent <- eol (%nl ignored_line)* (((!.) &%dedented) / (&(%nl %dedented)))
- tok_gap <- %ws / %prev_edge / &("[" / "\" / [.,:;{("#%'])
+ tok_gap <- %ws / %prev_edge / &("[" / "\" / [.,:;{("#%] / &%wordbreaker)
comma <- %ws? "," %ws?
semicolon <- %ws? ";" %ws?
dotdot <- nodent ".." %ws?
]=]
local CURRENT_FILE = nil
local whitespace = S(" \t") ^ 1
+local wordbreaker = ("'~`!@$^&*-+=|<>?/")
local defs = {
ws = whitespace,
nl = P("\n"),
tonumber = tonumber,
- wordchar = P(1) - S(' \t\n\r%#:;,.{}[]()"\\'),
+ wordbreaker = S(wordbreaker),
+ wordchar = P(1) - S(' \t\n\r%#:;,.{}[]()"\\' .. wordbreaker),
indented = Cmt(S(" \t") ^ 0 * (#(P(1) - S(" \t\n") + (-P(1)))), check_indent),
nodented = Cmt(S(" \t") ^ 0 * (#(P(1) - S(" \t\n") + (-P(1)))), check_nodent),
dedented = Cmt(S(" \t") ^ 0 * (#(P(1) - S(" \t\n") + (-P(1)))), check_dedent),
- prev_edge = B(S(" \t\n.,:;}])\"\\")),
+ prev_edge = B(S(" \t\n.,:;}])\"\\" .. wordbreaker)),
line_no = function(src, pos)
local line_no = 1
for _ in src:sub(1, pos):gmatch("\n") do
@@ -704,7 +706,7 @@ end)]]):format(concat(lua_bits, "\n"))
self:error("Nothing to get stub from")
end
if type(x) == 'string' then
- local stub = x:gsub("'", " '"):gsub("%%%S+", "%%"):gsub("%s+", " ")
+ local stub = x:gsub("([" .. tostring(wordbreaker) .. "])", " %1 "):gsub("%%%S+", "%%"):gsub("%s+", " "):gsub("%s*$", "")
local arg_names
do
local _accum_0 = { }
diff --git a/nomsu.moon b/nomsu.moon
index cd80510..82867ed 100755
--- a/nomsu.moon
+++ b/nomsu.moon
@@ -71,7 +71,7 @@ nomsu = [=[
noeol_statement <- noeol_functioncall / noeol_expression
inline_statement <- inline_functioncall / inline_expression
- inline_thunk <- ({ {| "{" inline_statements "}" |} }) -> Thunk
+ inline_thunk <- ({ {| "{" %ws? inline_statements %ws? "}" |} }) -> Thunk
eol_thunk <- ({ {| ":" %ws? noeol_statements eol |} }) -> Thunk
indented_thunk <- ({ {| (":" / "{..}") indent
statements (nodent statements)*
@@ -83,7 +83,7 @@ nomsu = [=[
indented_nomsu <- ({("\" expression) }) -> Nomsu
inline_expression <- number / variable / inline_string / inline_list / inline_nomsu
- / inline_thunk / ("(" inline_statement ")")
+ / inline_thunk / ("(" %ws? inline_statement %ws? ")")
noeol_expression <- indented_string / indented_nomsu / indented_list / indented_thunk
/ ("(..)" indent
statement
@@ -102,7 +102,7 @@ nomsu = [=[
(expression (dotdot / tok_gap))* word ((dotdot / tok_gap) (expression / word))*
|} }) -> FunctionCall
- word <- ({ !number {%wordchar (!"'" %wordchar)*} }) -> Word
+ word <- ({ { %wordbreaker / (!number %wordchar+) } }) -> Word
inline_string <- ({ '"' {|
({~ (("\\" -> "\") / ('\"' -> '"') / ("\n" -> "
@@ -120,7 +120,7 @@ nomsu = [=[
-- Variables can be nameless (i.e. just %) and can't contain apostrophes
-- which is a hack to allow %foo's to parse as "%foo" and "'s" separately
- variable <- ({ ("%" { (!"'" %wordchar)* }) }) -> Var
+ variable <- ({ ("%" { (%wordbreaker / (%wordchar+))? }) }) -> Var
inline_list <- ({ {|
("[" %ws? ((inline_list_item comma)* inline_list_item comma?)? %ws? "]")
@@ -141,7 +141,7 @@ nomsu = [=[
indent <- eol (%nl ignored_line)* %nl %indented ((block_comment/line_comment) (%nl ignored_line)* nodent)?
nodent <- eol (%nl ignored_line)* %nl %nodented
dedent <- eol (%nl ignored_line)* (((!.) &%dedented) / (&(%nl %dedented)))
- tok_gap <- %ws / %prev_edge / &("[" / "\" / [.,:;{("#%'])
+ tok_gap <- %ws / %prev_edge / &("[" / "\" / [.,:;{("#%] / &%wordbreaker)
comma <- %ws? "," %ws?
semicolon <- %ws? ";" %ws?
dotdot <- nodent ".." %ws?
@@ -149,13 +149,14 @@ nomsu = [=[
CURRENT_FILE = nil
whitespace = S(" \t")^1
+wordbreaker = ("'~`!@$^&*-+=|<>?/")
defs =
- ws:whitespace, nl: P("\n"), :tonumber
- wordchar: P(1)-S(' \t\n\r%#:;,.{}[]()"\\')
+ ws:whitespace, nl: P("\n"), :tonumber, wordbreaker:S(wordbreaker)
+ wordchar: P(1)-S(' \t\n\r%#:;,.{}[]()"\\'..wordbreaker)
indented: Cmt(S(" \t")^0 * (#(P(1)-S(" \t\n") + (-P(1)))), check_indent)
nodented: Cmt(S(" \t")^0 * (#(P(1)-S(" \t\n") + (-P(1)))), check_nodent)
dedented: Cmt(S(" \t")^0 * (#(P(1)-S(" \t\n") + (-P(1)))), check_dedent)
- prev_edge: B(S(" \t\n.,:;}])\"\\"))
+ prev_edge: B(S(" \t\n.,:;}])\"\\"..wordbreaker))
line_no: (src, pos)->
line_no = 1
for _ in src\sub(1,pos)\gmatch("\n") do line_no += 1
@@ -541,7 +542,7 @@ end)]])\format(concat(lua_bits, "\n"))
-- Returns a single stub ("say %"), and list of arg names ({"msg"}) from a single rule def
-- (e.g. "say %msg") or function call (e.g. FunctionCall({Word("say"), Var("msg")))
if type(x) == 'string'
- stub = x\gsub("'"," '")\gsub("%%%S+","%%")\gsub("%s+"," ")
+ stub = x\gsub("([#{wordbreaker}])"," %1 ")\gsub("%%%S+","%%")\gsub("%s+"," ")\gsub("%s*$","")
arg_names = [arg for arg in x\gmatch("%%([^%s']*)")]
return stub, arg_names
switch x.type