/ ~hypervariety /

Text (12572 bytes)
Saved 2 months ago
parsers
Push esc to read the page. Hold Ctrl/Alt/Opt to edit elements on the page.
Or drag a box to create new ones.
Sign in and out   Your home page ~ / Your files

Parsers

In Hypervariety the <field> tag has nice properties. The most colorful is the ability to automatically format its contents according to parsing rules. Parsers don't freeze the browser even if they're written badly.

1. Example

You can edit the text in this field. It will automatically color certain words as you type them. ♪ Red, orange, yellow, green, blue, purple, that's the way the colors go. ♪ Here is the parser for that field. # the first rule applies to the whole field and declares it to be tokens. mainRule = token* # a token is either a color or the next single character token = color / character character = . # We referred to a rule called Color with seven possible outcomes: color = "red" [red] / "orange" [orange] / "yellow" [yellow] color = "green" [green] / "blue" [blue] / "purple" [purple] / "brown" [brown]

2. Rules

The internal rules that define parsers are interesting. # Comments start with a # mark. They take up the rest of the line. rule = "Hello" [red] -> "Test output" [yellow] # You can add additional versions of a rule and they'll also be tried, in that order rule = "Hi" [blue] rule = "Yo" [green] rule = ("Dude" / "Friend" / "Pal") [gray] # Put rules together to concatenate, and use a question mark to be optional rule = ("Mrs" / "Mr" / "Dr") "."? " Pepper"? [orange] rule = ("..."+ [purple]) "Ideas" "!"* [yellow] # The same rule can be repeated at least once, or any number of times loop = "This rule needs at least one of this text"+ loop = "This rule can consume this phrase forever, and doesn't even have to do that"* optional = "This string, or not? it's optional."? # But you can't "loop" a rule if it *might* not eat anything. test = ( "The question mark makes the inside optional"? )* #the above line would ruin the parser's chance of finishing, every time
Hello, here's a place to type in. -> Here's a place to see what the parser produced.

3. Formal Grammar

Look, here's the parsing rules of parsers as a parser. standard_grammar = o:outer_inner<linePrefix,comment/ruleDeclaration> -> " [ " o " null ]" alpha = ."abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_" numeric = ."0123456789" literal = alpha (alpha/numeric)* [literal] spaces = ." \t"* -> "" linePrefix = ." \n\r\t;"* -> "\n" doublequote = "\"" singlequote = "\'" quoted = doublequote q:(-doublequote -"\n" -"\r" quotedChar)* doublequote? [quoted] -> q quoted = singlequote q:(-singlequote -"\n" -"\r" quotedChar)* singlequote? [quoted] -> q quotedChar = c:."\"\'" -> "/" c / "\\"? . comment = "#" c:(-."\n\r" .)* [comment] -> "//" c style = "[" s:literal "]" -> s ruleDeclaration = n:literal g:genericLabels? spaces r:ruleDefinition? -> "[ '" n "', " g ", [" r "] ]," ruleDefinition = "=" spaces r:ruleBody -> r ruleBody = outer_inner<ruleChoice, spaces "/" spaces -> "],["> ruleChoice = b:concatBody spaces e:ruleEmitter? -> b e ruleEmitter = "->" spaces b:emitterBody -> b genericLabels = "<" o:outer_inner<l:literal [label] -> "'" l "'", spaces "," spaces -> ","> ">" -> "[" o "]" # each rule choice has a body concatBody = outer_inner<concatElementWithPrefix, spaces -> ","> concatElement = q:quoted -> "{type:'terminal',string:\"" q "\"}" concatElement = s:style -> "{style:\"" s "\"}" concatElement = "(" spaces b:ruleBody spaces ")" -> "{type:'choice', rules: [ [" b "] ]}" concatElement = "." a:(q:quoted -> ",allowed:\"" q "\"")? -> "{type:'any'" a "}" concatElement = l:(literal [label]) "<" b:outer_inner<ruleBody, spaces "," spaces -> "] ],[ ["> ">" -> "{ type: 'generic', name: '" l "', parameters: [ [ [" b "] ] ] }" concatElement = l:(literal [label]) -> "'" l "'" concatElementWithPrefix = "--" e:concatElement -> "{ type: 'guard', rule: { type: 'guard', rule: " e " } }" concatElementWithPrefix = "-" e:concatElement -> "{ type: 'guard', rule: " e " }" concatElementWithPrefix = l:(literal [label]) ":" e:concatElementWithSuffix -> "{ label: '" l "', rule: " e " }" concatElementWithPrefix = concatElementWithSuffix concatElementWithSuffix = e:concatElement "*" -> "{ type: 'repeat', rule: " e " }" concatElementWithSuffix = e:concatElement "+" -> "{ type: 'repeat', minimum: 1, rule: " e " }" concatElementWithSuffix = e:concatElement "?" -> "{ type: 'choice', rules: [ [" e "],[{ type: 'terminal', string: '' }] ] }" concatElementWithSuffix = concatElement # and a rule choice has an optional emitter emitterBody = b:outer_inner<emitterElement,spaces -> ","> -> ",{ emitter: [" b "] }" emitterElement = l:(literal [label]) -> "'" l "'" emitterElement = q:quoted -> "{text:\"" q "\"}" emitterElement = s:style -> "{style:\"" s "\"}" emitterElement = j:."[]{}"+ [quoted] -> "{text:\"" j "\"}" # a generic is helpful, it's kind of the idea of a rule outer_inner<outer,inner> = outer (inner outer)*

4. Properties

The float can be left or right, which makes other text on the page wrap around the field. The style can be shadow, rectangle, or transparent, and you can set the background to a color. The lock can be true to keep the user from editing. If you have tags around the field (like <B>...</B>), it will be styled. This field floats on the right side.
That's okay...it likes that.
This is on the left side.
You can edit it too.
Another field on the right. This one's
full of red.
This text in this field is lengthy, so it wraps around the floating fields on the left and on the right. This text in this field is lengthy, so it wraps around the floating fields on the left and on the right. This text in this field is lengthy, so it wraps around the floating fields on the left and on the right. This text in this field is lengthy, so it wraps around the floating fields on the left and on the right. This text in this field is lengthy, so it wraps around the floating fields on the left and on the right. This text in this field is lengthy, so it wraps around the floating fields on the left and on the right. This text in this field is lengthy, so it wraps around the floating fields on the left and on the right. This text in this field is lengthy, so it wraps around the floating fields on the left and on the right. This text in this field is lengthy, so it wraps around the floating fields on the left and on the right. This text in this field is lengthy, so This text in this field is lengthy, so it wraps around the floating fields on the left and on the right. This text in this field is lengthy, so it wraps around the floating fields on the left and on the right. hey all of a sudden here...
Bee!!
which is
still being styled. This text in this field is lengthy, so it wraps around the floating fields on the left and on the right. This text in this field is lengthy, so it wraps around the floating fields on the left and on the right. This text in this field is lengthy, so it wraps around the floating fields on the left and on the right. This text in this field is lengthy, so it wraps around the floating fields on the left and on the right. This text in this field is lengthy, so it wraps around the floating fields on the left and on the right. This text in this field is lengthy, so it wraps around the floating fields on the left and on the right. This text in this field is lengthy, so it wraps around the floating fields on the left and on the right.



5. Limitations

The fields were written to depend on a tag called <div contenteditable>, which I feel may have been a dumb decision. The tag has got some quirks. Internet Explorer is weird about drawing images and other things, and modern browsers are both too clumsy at the old stuff (like Undo-ing your changes) and too free at the new stuff (you can paste a huge JPEG into the text even if it's not wanted).

I also need to update some of the text coloring routines to be more power efficient. The previous problem and this problem happen to have a common solution, and I will be working on them when I can.

Editing is enabled
Learn about instructions Hide the box