From e336007fcf82c065e4651a28a8dc67a31be591e7 Mon Sep 17 00:00:00 2001 From: Golmote Date: Wed, 9 Sep 2015 21:06:24 +0200 Subject: [PATCH] Add support for Bison --- components.js | 5 + components/prism-bison.js | 39 +++++++ components/prism-bison.min.js | 1 + examples/prism-bison.html | 110 ++++++++++++++++++++ tests/languages/bison/c_feature.test | 56 ++++++++++ tests/languages/bison/comment_feature.test | 25 +++++ tests/languages/bison/keyword_feature.test | 22 ++++ tests/languages/bison/number_feature.test | 15 +++ tests/languages/bison/property_feature.test | 21 ++++ tests/languages/bison/string_feature.test | 21 ++++ 10 files changed, 315 insertions(+) create mode 100644 components/prism-bison.js create mode 100644 components/prism-bison.min.js create mode 100644 examples/prism-bison.html create mode 100644 tests/languages/bison/c_feature.test create mode 100644 tests/languages/bison/comment_feature.test create mode 100644 tests/languages/bison/keyword_feature.test create mode 100644 tests/languages/bison/number_feature.test create mode 100644 tests/languages/bison/property_feature.test create mode 100644 tests/languages/bison/string_feature.test diff --git a/components.js b/components.js index 3746a5d098..69d2967312 100644 --- a/components.js +++ b/components.js @@ -93,6 +93,11 @@ var components = { "title": "BASIC", "owner": "Golmote" }, + "bison": { + "title": "Bison", + "require": "c", + "owner": "Golmote" + }, "brainfuck": { "title": "Brainfuck", "owner": "Golmote" diff --git a/components/prism-bison.js b/components/prism-bison.js new file mode 100644 index 0000000000..9a65a537d1 --- /dev/null +++ b/components/prism-bison.js @@ -0,0 +1,39 @@ +Prism.languages.bison = Prism.languages.extend('c', {}); + +Prism.languages.insertBefore('bison', 'comment', { + 'bison': { + // This should match all the beginning of the file + // including the prologue(s), the bison declarations and + // the grammar rules. + pattern: /^[\s\S]*?%%[\s\S]*?%%/, + inside: { + 'c': { + // Allow for one level of nested braces + pattern: /%\{[\s\S]*?%\}|\{(?:\{[^}]*\}|[^{}])*\}/, + inside: { + 'delimiter': { + pattern: /^%?\{|%?\}$/, + alias: 'punctuation' + }, + 'bison-variable': { + pattern: /[$@](?:<[^\s>]+>)?[\w$]+/, + alias: 'variable', + inside: { + 'punctuation': /<|>/ + } + }, + rest: Prism.languages.c + } + }, + 'comment': Prism.languages.c.comment, + 'string': Prism.languages.c.string, + 'property': /\S+(?=:)/, + 'keyword': /%\w+/, + 'number': { + pattern: /(^|[^@])\b(?:0x[\da-f]+|\d+)/i, + lookbehind: true + }, + 'punctuation': /%[%?]|[|:;\[\]<>]/ + } + } +}); \ No newline at end of file diff --git a/components/prism-bison.min.js b/components/prism-bison.min.js new file mode 100644 index 0000000000..c26f331756 --- /dev/null +++ b/components/prism-bison.min.js @@ -0,0 +1 @@ +Prism.languages.bison=Prism.languages.extend("c",{}),Prism.languages.insertBefore("bison","comment",{bison:{pattern:/^[\s\S]*?%%[\s\S]*?%%/,inside:{c:{pattern:/%\{[\s\S]*?%\}|\{(?:\{[^}]*\}|[^{}])*\}/,inside:{delimiter:{pattern:/^%?\{|%?\}$/,alias:"punctuation"},"bison-variable":{pattern:/[$@](?:<[^\s>]+>)?[\w$]+/,alias:"variable",inside:{punctuation:/<|>/}},rest:Prism.languages.c}},comment:Prism.languages.c.comment,string:Prism.languages.c.string,property:/\S+(?=:)/,keyword:/%\w+/,number:{pattern:/(^|[^@])\b(?:0x[\da-f]+|\d+)/i,lookbehind:!0},punctuation:/%[%?]|[|:;\[\]<>]/}}}); \ No newline at end of file diff --git a/examples/prism-bison.html b/examples/prism-bison.html new file mode 100644 index 0000000000..d76d81c838 --- /dev/null +++ b/examples/prism-bison.html @@ -0,0 +1,110 @@ +

Bison

+

To use this language, use the class "language-bison".

+ +

Comments

+
// Single-line comment
+/* Multi-line
+comment */
+ +

C prologue and Bison declarations

+
%{
+  #include <stdio.h>
+  #include <math.h>
+  int yylex (void);
+  void yyerror (char const *);
+%}
+
+%define api.value.type {double}
+%token NUM
+%union { char *string; }
+%%
+%%
+ +

Grammar rules

+
%%
+exp:
+  NUM           { $$ = $1;           }
+| exp exp '+'   { $$ = $1 + $2;      }
+| exp exp '-'   { $$ = $1 - $2;      }
+| exp exp '*'   { $$ = $1 * $2;      }
+| exp exp '/'   { $$ = $1 / $2;      }
+| exp exp '^'   { $$ = pow($1, $2);  }  /* Exponentiation */
+| exp 'n'       { $$ = -$1;          }  /* Unary minus    */
+;
+
+$@1: %empty { a(); };
+$@2: %empty { c(); };
+$@3: %empty { d(); };
+exp: $@1 "b" $@2 $@3 "e" { f(); };
+%%
+ +

Full example

+
/* Mini Calculator */
+/* calc.y */
+
+%{
+#include "heading.h"
+int yyerror(char *s);
+int yylex(void);
+%}
+
+%union{
+  int		int_val;
+  string*	op_val;
+}
+
+%start	input 
+
+%token	<int_val>	INTEGER_LITERAL
+%type	<int_val>	exp
+%left	PLUS
+%left	MULT
+
+%%
+
+input:		/* empty */
+		| exp	{ cout << "Result: " << $1 << endl; }
+		;
+
+exp:		INTEGER_LITERAL	{ $$ = $1; }
+		| exp PLUS exp	{ $$ = $1 + $3; }
+		| exp MULT exp	{ $$ = $1 * $3; }
+		;
+
+%%
+
+int yyerror(string s)
+{
+  extern int yylineno;	// defined and maintained in lex.c
+  extern char *yytext;	// defined and maintained in lex.c
+  
+  cerr << "ERROR: " << s << " at symbol \"" << yytext;
+  cerr << "\" on line " << yylineno << endl;
+  exit(1);
+}
+
+int yyerror(char *s)
+{
+  return yyerror(string(s));
+}
+ +

Known failures

+

There are certain edge cases where Prism will fail. + There are always such cases in every regex-based syntax highlighter. + However, Prism dares to be open and honest about them. + If a failure is listed here, it doesn’t mean it will never be fixed. This is more of a “known bugs” list, just with a certain type of bug. +

+ +

Comment-like substring

+
"This string is // broken"
+ +

Two levels of nesting inside C section

+
{
+	if($1) {
+		if($2) {
+
+		}
+	}
+} // <- Broken
+%%
+%%
\ No newline at end of file diff --git a/tests/languages/bison/c_feature.test b/tests/languages/bison/c_feature.test new file mode 100644 index 0000000000..a131ec3d84 --- /dev/null +++ b/tests/languages/bison/c_feature.test @@ -0,0 +1,56 @@ +%{ + #include +%} +%code { + if(foo) { + + } +} +%% +exp: + NUM { + $$ = f($3, $4); + @$.first_column = @1.first_column; + $result = $left + $1; + } +%% + +---------------------------------------------------- + +[ + ["bison", [ + ["c", [ + ["delimiter", "%{"], + ["macro", ["#include ", ["string", ""]]], + ["delimiter", "%}"] + ]], + ["keyword", "%code"], + ["c", [ + ["delimiter", "{"], + ["keyword", "if"], ["punctuation", "("], "foo", ["punctuation", ")"], + ["punctuation", "{"], ["punctuation", "}"], + ["delimiter", "}"] + ]], + ["punctuation", "%%"], + ["property", "exp"], ["punctuation", ":"], + "\r\n\tNUM ", + ["c", [ + ["delimiter", "{"], + ["bison-variable", ["$$"]], ["operator", "="], + ["function", "f"], ["punctuation", "("], + ["bison-variable", ["$3"]], ["punctuation", ","], + ["bison-variable", ["$4"]], ["punctuation", ")"], ["punctuation", ";"], + ["bison-variable", ["@$"]], ["punctuation", "."], "first_column ", ["operator", "="], + ["bison-variable", ["@1"]], ["punctuation", "."], "first_column", ["punctuation", ";"], + ["bison-variable", ["$result"]], ["operator", "="], + ["bison-variable", ["$left"]], ["operator", "+"], + ["bison-variable", ["$", ["punctuation", "<"], "itype", ["punctuation", ">"], "1"]], ["punctuation", ";"], + ["delimiter", "}"] + ]], + ["punctuation", "%%"] + ]] +] + +---------------------------------------------------- + +Checks for C inside Bison, along with special Bison variables. \ No newline at end of file diff --git a/tests/languages/bison/comment_feature.test b/tests/languages/bison/comment_feature.test new file mode 100644 index 0000000000..15ed152e15 --- /dev/null +++ b/tests/languages/bison/comment_feature.test @@ -0,0 +1,25 @@ +// Foobar +/* Foo +bar */ +%% +// Foobar +/* Foo +bar */ +%% + +---------------------------------------------------- + +[ + ["bison", [ + ["comment", "// Foobar"], + ["comment", "/* Foo\r\nbar */"], + ["punctuation", "%%"], + ["comment", "// Foobar"], + ["comment", "/* Foo\r\nbar */"], + ["punctuation", "%%"] + ]] +] + +---------------------------------------------------- + +Checks for comments. \ No newline at end of file diff --git a/tests/languages/bison/keyword_feature.test b/tests/languages/bison/keyword_feature.test new file mode 100644 index 0000000000..49fb373317 --- /dev/null +++ b/tests/languages/bison/keyword_feature.test @@ -0,0 +1,22 @@ +%union +%token +%% +exp: %empty +%% + +---------------------------------------------------- + +[ + ["bison", [ + ["keyword", "%union"], + ["keyword", "%token"], + ["punctuation", "%%"], + ["property", "exp"], ["punctuation", ":"], + ["keyword", "%empty"], + ["punctuation", "%%"] + ]] +] + +---------------------------------------------------- + +Checks for keywords. \ No newline at end of file diff --git a/tests/languages/bison/number_feature.test b/tests/languages/bison/number_feature.test new file mode 100644 index 0000000000..ddbacff94b --- /dev/null +++ b/tests/languages/bison/number_feature.test @@ -0,0 +1,15 @@ +42 +0 +0xBadFace + +---------------------------------------------------- + +[ + ["number", "42"], + ["number", "0"], + ["number", "0xBadFace"] +] + +---------------------------------------------------- + +Checks for numbers. \ No newline at end of file diff --git a/tests/languages/bison/property_feature.test b/tests/languages/bison/property_feature.test new file mode 100644 index 0000000000..c1b6cb2405 --- /dev/null +++ b/tests/languages/bison/property_feature.test @@ -0,0 +1,21 @@ +%% +foo: +bar_42: +$@1: +%% + +---------------------------------------------------- + +[ + ["bison", [ + ["punctuation", "%%"], + ["property", "foo"], ["punctuation", ":"], + ["property", "bar_42"], ["punctuation", ":"], + ["property", "$@1"], ["punctuation", ":"], + ["punctuation", "%%"] + ]] +] + +---------------------------------------------------- + +Checks for properties. \ No newline at end of file diff --git a/tests/languages/bison/string_feature.test b/tests/languages/bison/string_feature.test new file mode 100644 index 0000000000..3f3f6c0d58 --- /dev/null +++ b/tests/languages/bison/string_feature.test @@ -0,0 +1,21 @@ +%% +foo: 'foo' "foo"; +bar: '\'' "\""; +%% + +---------------------------------------------------- + +[ + ["bison", [ + ["punctuation", "%%"], + ["property", "foo"], ["punctuation", ":"], + ["string", "'foo'"], ["string", "\"foo\""], ["punctuation", ";"], + ["property", "bar"], ["punctuation", ":"], + ["string", "'\\''"], ["string", "\"\\\"\""], ["punctuation", ";"], + ["punctuation", "%%"] + ]] +] + +---------------------------------------------------- + +Checks for strings. \ No newline at end of file