Skip to content
Permalink
Browse files

CHANGE: propName: :wordString and #hashString now accept escaping and…

… a lot more, but [, {, ( no longer allowed without escaping
  • Loading branch information...
shanebdavis committed Aug 31, 2019
1 parent 32f049d commit fc260e37cde9c2646f1e376f814880b7b4cb38f3
@@ -1,14 +1,19 @@
import &ArtStandardLib

deescapeSpaces: (string) ->
### deescapeSpaces
IN: string
OUT: string
Input string with all "\ " and "\_" sequences converted into " ".

This is done safely so "\\ " and "\\_" becomes "\ " and "\_" respectively.
deescapeSpaces: deescapeSpaces = (string) ->
array str, i from string.split /((?:\\\\)+)/
if i %% 2 == 0
str.replace /\\ /g, ' '
str.replace /\\[_ ]/g, ' '
else
str
.join ''


escapeNewLines: (string) -> string.replace /\n/g, "\\n"

##
@@ -46,7 +51,11 @@ escapePropName: (rawPropName) ->
if legalUnquotedPropName.test rawPropName
rawPropName
else
escapeJavascriptString rawPropName
'"' +
deescapeSpaces rawPropName
.replace /["]/g, '\\"'
+ '"'


identifierRegexp:
///
@@ -11,7 +11,7 @@ import &StandardImport

comment:
{} pattern: "/##[^\n]*/ unparsedBlock*"
{} pattern: /\ *#([^\n$\w\u007f-\uffff]+[^\n]*|(?=\n|$))/
{} pattern: /// \ * \# ( [\ \t] [^\n]* | (?=\n|$) )

##
Statement-ends are:
@@ -113,33 +113,43 @@ import Extensions
stnFactory: "ObjectLiteralAccessorStn"

@rule
stringLiteralPropNameTail: [
"_ /:/ !unquotedString"
"/:/"
]
stringLiteralPropNameTail:
"" _ /:/ !unquotedString
/:/

@rule
thisPropName: "/@/ unquotedString?"
thisPropName: "/@/ propNameExtension*"
{}
stnFactory: :ThisStn
stnProps: ~> identifier: @unquotedString.toString()
stnProps: ~> identifier: @propNameExtension?.toString()

@rule
propName:
"!/then\\s/ str:thisPropName &_colon_"
"" !/then\\s/ thisPropName &_colon_
{}
stnFactory: "ObjectPropNameStn"
stnProps: ~>
isThisProp: true

@rule
propNameExtension:
"" /:*/ unquotedPropNameToken &/:/

@rule
propName:
"!regExpLiteral !/then\\s/ str:identifier &_colon_"
"!regExpLiteral !/then\\s/ str:unquotedString &/:/"
"quotedString:stringLiteral &stringLiteralPropNameTail"
"" !regExpLiteral !/then\\s/ propNameExtension+
{}
stnFactory: :ObjectPropNameStn
stnProps: ~>
value: @toString()
isThisProp: false

@rule
propName:
"" quotedString:stringLiteral &stringLiteralPropNameTail

{}
stnFactory: "ObjectPropNameStn"
stnFactory: :ObjectPropNameStn
stnProps: ~>
value: @str?.toString()
value: @toString()
isThisProp: false
@@ -1,6 +1,5 @@
import &StandardImport, &CaffeineEight, &StnRegistry, &Lib

wordStringChar = /// [^\n\s,)\]\}]
blockStringStartChar = /// (\ | \n | [^.\n\s,)\]\}] )

->
@@ -41,23 +40,60 @@ blockStringStartChar = /// (\ | \n | [^.\n\s,)\]\}] )
pattern: "" /"""|'''/
getStn: ~> StringStn parseTreeNode: @, value: ""

## word-strings
:unquoted strings
: is omitted
reserved: '::' for a future word-string-block
reserved: backslashes are currently excluded until I decide
if they should be escaped or
if we should support escapes
Could be interesting: :foo\sbar could == "foo bar"
## :wordString
Word-strings start with ':' and are followed by one or more characters
of any type EXCEPT:

close-brackets: ) } ]
comma: ,
white-space: \s \n \t

The starting ':' is omitted in the output string.

Escaping is supported.

EXCEPTION: '::' is reserved for future use

Examples:
:word
> "word"

# most non-whitespace characters are allowed
:https://www.home.com/foo.bar?erg=123
> "https://www.home.com/foo.bar?erg=123"

# escaping is allowed
:hi\nthere
> "hi\nthere"

# "::" is reserved for future features
::
> Syntax Error

{}
pattern: /// :(?!:) #{wordStringChar.source}+
pattern: "" /:(?!:)/ unquotedString2
getStn: ~> StringStn parseTreeNode: @, value: @toString().slice 1

## hashtag-strings
#hashtag and color (#fff) strings
The # is preserved
## #hashStrings (primary use: hashtag and colors)
Uses the same logic as wordStrings EXCEPT:

* The starting "#" is INCLUDED in the output string.
* "##" is a comment

Examples:
#tagThis
> "#tagThis"

#ff7700
> "#ff7700"

##hi << double-# followed by anything is a comment
> ;

The starting '#' is preserved.
reserved: '##' for comments
{}
pattern: /#[$\w\u007f-\uffff]+/
pattern: "" /\#(?!\#)/ unquotedString2
getStn: ~> StringStn parseTreeNode: @, value: @toString()

# number-with-unit strings
@@ -152,7 +152,58 @@
- should we allow escaping?
- should we allow #{} interpolation?

unquotedString: /[-~!@\#$%^&*_+=|\\<>?\/.$\w\u007f-\uffff]+/
unquotedString: /// [-~!@\#$%^&*_+=|\\<>?\/.$\w\u007f-\uffff]+

##
SBD Aug2019: I'm coming to these conclusions:
- all except: space, comma, [], (), {}, ;
- we could allow [ ( { in most places,
but for consistency sake, all brackets
must be excaped in unquoted strings.

USES:
:wordStrings # start with ':', which is ignored in the output string
#hashStrings # start with '#', which is included in the output string
propNames: 123 # end with ':', which is ignored in the output string

EXCEPTIONS:
- propNames: cannot START with a quote (' " `) or escape (\)

- No double start characters: the first two characters must be different
- ## is a comment, not the #hashString "##"
- :: is illegal (for now), not the :wordString ":"

- escaping: YES
- interpolation: YES (WIP)

unquotedString2:
///
(?:

[^;:\n\s,)\]\}]

|

: [^;\n\s,)\]\}]

)+

unquotedPropNameToken:
# /// (?: (?! [\s \x7f () [\] {} ; : , ]) [ \0x21-\uffff] )+
# /// [a-zA-Z0-9]
///

(?:

[^ \s \0-\x20 \x7f [ \] {} () ; : , ' " ` \\]

(?:
[^ \s \0-\x20 \x7f [ \] {} () ; : , \\]
|
\\ .
)*

)

unaryTailOperator: /// \?
unaryOperator_:
@@ -62,7 +62,7 @@ contexts:
# strings in YAML. When using single quoted strings, only single quotes
# need to be escaped: this is done by using two single quotes next to each
# other.
- match: '\b(((in|from)-)?(array|object)|super|await|delete|inject|as|with-key|extract|instanceof|return|break|into|returning|try|catch|promise|then|and|or|is|isnt|not|if|else|switch|unless|until|throw|new|while|class|extends|find|each|to|til|by|in|from|with|do|case|when|import)\b'
- match: '\b(((in|from)-)?(array|object)|super|await|delete|reduce|inject|as|with-key|extract|instanceof|return|break|into|returning|try|catch|promise|then|and|or|is|isnt|not|if|else|switch|unless|until|throw|new|while|class|extends|find|each|to|til|by|in|from|with|do|case|when|import)\b'
scope: keyword.caffeine

- match: '\b(false|true)\b'
@@ -2,16 +2,16 @@
let Caf = require("caffeine-script-runtime");
Caf.defMod(module, () => {
return Caf.importInvoke(
["escapeRegExp", "escapeJavascriptString"],
["escapeRegExp"],
[global, require("art-standard-lib")],
(escapeRegExp, escapeJavascriptString) => {
let legalUnquotedPropName;
escapeRegExp => {
let deescapeSpaces, legalUnquotedPropName;
return {
deescapeSpaces: function(string) {
deescapeSpaces: (deescapeSpaces = function(string) {
return Caf.array(string.split(/((?:\\\\)+)/), (str, i) =>
Caf.mod(i, 2) === 0 ? str.replace(/\\ /g, " ") : str
Caf.mod(i, 2) === 0 ? str.replace(/\\[_ ]/g, " ") : str
).join("");
},
}),
escapeNewLines: function(string) {
return string.replace(/\n/g, "\\n");
},
@@ -35,7 +35,7 @@ Caf.defMod(module, () => {
escapePropName: function(rawPropName) {
return legalUnquotedPropName.test(rawPropName)
? rawPropName
: escapeJavascriptString(rawPropName);
: '"' + deescapeSpaces(rawPropName).replace(/["]/g, '\\"') + '"';
},
identifierRegexp: /^(?!\d)((?!\s)[$\w\u007f-\uffff])+$/
};
@@ -10,7 +10,7 @@ Caf.defMod(module, () => {
_OrEnd: ["_", "end"],
comment: [
{ pattern: "/##[^\n]*/ unparsedBlock*" },
{ pattern: /\ *#([^\n$\w\u007f-\uffff]+[^\n]*|(?=\n|$))/ }
{ pattern: / *\#([ \t][^\n]*|(?=\n|$))/ }
],
_end: /( *(\n|; *|$))+|( *(?=[\)}]))/,
lineStartComment: ["comment _end", "_end"],
@@ -107,42 +107,50 @@ Caf.defMod(module, () => {
}
});
this.rule({
stringLiteralPropNameTail: ["_ /:/ !unquotedString", "/:/"]
stringLiteralPropNameTail: ["_ /:/ !unquotedString", /:/]
});
this.rule(
{ thisPropName: "/@/ unquotedString?" },
{ thisPropName: "/@/ propNameExtension*" },
{
stnFactory: "ThisStn",
stnProps: function() {
return { identifier: this.unquotedString.toString() };
let base;
return {
identifier:
Caf.exists((base = this.propNameExtension)) &&
base.toString()
};
}
}
);
this.rule(
{ propName: "!/then\\s/ str:thisPropName &_colon_" },
{ propName: "!/then\\s/ thisPropName &_colon_" },
{
stnFactory: "ObjectPropNameStn",
stnProps: function() {
return { isThisProp: true };
}
}
);
this.rule({ propNameExtension: "/:*/ unquotedPropNameToken &/:/" });
this.rule(
{ propName: "!regExpLiteral !/then\\s/ propNameExtension+" },
{
stnFactory: "ObjectPropNameStn",
stnProps: function() {
return { value: this.toString(), isThisProp: false };
}
}
);
return this.rule(
{
propName: [
"!regExpLiteral !/then\\s/ str:identifier &_colon_",
"!regExpLiteral !/then\\s/ str:unquotedString &/:/",
propName:
"quotedString:stringLiteral &stringLiteralPropNameTail"
]
},
{
stnFactory: "ObjectPropNameStn",
stnProps: function() {
let base;
return {
value: Caf.exists((base = this.str)) && base.toString(),
isThisProp: false
};
return { value: this.toString(), isThisProp: false };
}
}
);
@@ -11,8 +11,7 @@ Caf.defMod(module, () => {
require("../Lib")
],
(Extensions, StringStn, InterpolatedStringStn) => {
let wordStringChar, blockStringStartChar;
wordStringChar = /[^\n\s,)\]\}]/;
let blockStringStartChar;
blockStringStartChar = /( |\n|[^.\n\s,)\]\}])/;
return function() {
this.rule({
@@ -62,7 +61,7 @@ Caf.defMod(module, () => {
}
},
{
pattern: RegExp(`:(?!:)${Caf.toString(wordStringChar.source)}+`),
pattern: "/:(?!:)/ unquotedString2",
getStn: function() {
return StringStn({
parseTreeNode: this,
@@ -71,7 +70,7 @@ Caf.defMod(module, () => {
}
},
{
pattern: /#[$\w\u007f-\uffff]+/,
pattern: "/#(?!#)/ unquotedString2",
getStn: function() {
return StringStn({
parseTreeNode: this,
@@ -34,6 +34,8 @@ Caf.defMod(module, () => {
],
pathedRequire: /((?!\s)[-\/$\w\u007f-\uffff])+/,
unquotedString: /[-~!@\#$%^&*_+=|\\<>?\/.$\w\u007f-\uffff]+/,
unquotedString2: /(?:[^;:\n\s,)\]\}]|:[^;\n\s,)\]\}])+/,
unquotedPropNameToken: /(?:[^\s\0-\x20\x7f[\]{}();:,'"`\\](?:[^\s\0-\x20\x7f[\]{}();:,\\]|\\.)*)/,
unaryTailOperator: /\?/,
unaryOperator_: /([!~]|not\b|delete\b) *|-(?![-:])/,
binaryOperator: /&&|\|\||&(?=\s)|\||\^|\?|((and|or|in|is|isnt|instanceof)\b)|<<|>>>|>>|==|!=|<=|>=|<|>|\/\/|%%|\*\*|[-+*\/%]/,

0 comments on commit fc260e3

Please sign in to comment.
You can’t perform that action at this time.