Repository: tweag/nickel (rust)

Issue:
Allow dashes in identifiers
**Is your feature request related to a problem? Please describe.**
 Dashes are common in option names. Currently one has to escape record fields with dashes inside because it is interpreted as a minus:

```nickel
{
  "foo-bar"."bar-baz" = null,
}
```

**Describe the solution you'd like**
As decided during the [standardization meeting](https://github.com/tweag/nickel/blob/master/notes/standardization-meeting-07.12.21.md), alow the dash character "-" as part of an identifier, as in Nix.

```nickel
{
  foo-bar.bar-baz = null,
}
```

This means that `a-b` is not parsed as subtraction anymore. Subtraction now requires spaces. But we expect this to be a minor inconvenience (or even good practice) in a configuration language, versus the field escaping annoyance.

Pull request description:
Allow dash in identifiers
Close #492.

Patch:
diff --git a/examples/fibonacci/fibonacci.ncl b/examples/fibonacci/fibonacci.ncl
index 2cd9c89b..82cbb7a3 100644
--- a/examples/fibonacci/fibonacci.ncl
+++ b/examples/fibonacci/fibonacci.ncl
@@ -10,6 +10,6 @@ let fibonacci = {
   else if n == 1 then
     1
   else 
-    f (n-1) + f (n-2)
+    f (n - 1) + f (n - 2)
 }.f in
 fibonacci 10
diff --git a/src/parser/lexer.rs b/src/parser/lexer.rs
index 92d98e6d..7f043564 100644
--- a/src/parser/lexer.rs
+++ b/src/parser/lexer.rs
@@ -40,7 +40,7 @@ pub enum NormalToken<'input> {
     #[error]
     Error,
 
-    #[regex("_?[a-zA-Z][_a-zA-Z0-9]*")]
+    #[regex("_?[a-zA-Z][_a-zA-Z0-9-]*")]
     Identifier(&'input str),
     #[regex("[0-9]*\\.?[0-9]+", |lex| lex.slice().parse())]
     NumLiteral(f64),
diff --git a/src/repl/mod.rs b/src/repl/mod.rs
index 2ebb77b9..ff085b1c 100644
--- a/src/repl/mod.rs
+++ b/src/repl/mod.rs
@@ -14,7 +14,6 @@ use crate::term::{RichTerm, Term};
 use crate::types::Types;
 use crate::{eval, transformations, typecheck};
 use codespan::FileId;
-use md5::digest::generic_array::functional::FunctionalSequence;
 use simple_counter::*;
 use std::ffi::{OsStr, OsString};
 use std::io::Write;


Test patch:
diff --git a/tests/contracts_fail.rs b/tests/contracts_fail.rs
index 87c59c26..f3314921 100644
--- a/tests/contracts_fail.rs
+++ b/tests/contracts_fail.rs
@@ -99,12 +99,12 @@ fn records_contracts_poly() {
     // but this is not yet the case.
     // eval_string(&format!("{} {{foo = 2}}", extd)).unwrap_err();
 
-    let remv = "let f | forall a. {foo: Num | a} -> { | a} = fun x => x-$\"foo\" in f";
+    let remv = "let f | forall a. {foo: Num | a} -> { | a} = fun x => x -$ \"foo\" in f";
     assert_raise_blame!(&format!("{} {{}}", remv));
 
     let bad_cst = "let f | forall a. { | a} -> { | a} = fun x => {a=1} in f";
     let bad_acc = "let f | forall a. { | a} -> { | a} = fun x => %seq% x.a x in f";
-    let bad_extd = "let f | forall a. { | a} -> {foo: Num | a} = fun x => x-$\"foo\" in f";
+    let bad_extd = "let f | forall a. { | a} -> {foo: Num | a} = fun x => x -$ \"foo\" in f";
     let bad_rmv = "let f | forall a. {foo: Num | a} -> { | a} = fun x => x$[\"foo\"=1] in f";
 
     assert_raise_blame!(&format!("{} {{}}", bad_cst));
diff --git a/tests/pass/record-defs.ncl b/tests/pass/record-defs.ncl
index a71d6c1c..b32be944 100644
--- a/tests/pass/record-defs.ncl
+++ b/tests/pass/record-defs.ncl
@@ -24,6 +24,7 @@ let Assert = fun l x => x || %blame% l in
   {"#{x}-bar" = "foo"}."foo-bar" == "foo" | #Assert) &&
 
 ({"foo-bar"."baz+baz" = false}."foo-bar"."baz+baz" == false | #Assert) &&
+({foo-bar.baz-baz = false}.foo-bar.baz-baz == false | #Assert) &&
 
 // recursive_paths
 ({foo.bar.baz = 1, bar.baz.foo = foo.bar.baz + 1}