Skip to content

Commit

Permalink
Added code-highlighting for the code examples
Browse files Browse the repository at this point in the history
Richard created a "simple" script that will tokenize the code and
returns a highlighted string. I've included this script outside the
webroot, for future usage.
  • Loading branch information
Berry Langerak committed Sep 18, 2012
1 parent 175597a commit 4f16a97
Show file tree
Hide file tree
Showing 6 changed files with 187 additions and 30 deletions.
2 changes: 2 additions & 0 deletions examples/1-hello-world.sf
@@ -0,0 +1,2 @@
use io;
io.print("Hello world");
6 changes: 6 additions & 0 deletions examples/2-using-variables.sf
@@ -0,0 +1,6 @@
use io;

$a = 1;
$a += 1;

io.print("The value of $a: ", $a , "\n");
18 changes: 18 additions & 0 deletions examples/3-simple-class.sf
@@ -0,0 +1,18 @@
use io;

class Foo {
const FOOBAR = "foobar";

protected property $a = 1;

public method ctor() {
// Constructor
}

public method foo() {
return $a;
}
}

$f = Foo();
io.print ("The value is: ", $f.foo());
91 changes: 91 additions & 0 deletions highlight.php
@@ -0,0 +1,91 @@
<?php
/**
* This is a script that can highlight Saffire-syntax, built by Richard van
* Velzen (https://github.com/rvanvelzen). Many thanks.
*/
$script = array_shift($argv);

if(count($argv) === 0) {
printf("Usage: php %s <input>\n", $script);
exit;
}

$input = array_shift( $argv );
if(!is_file($input) || !is_readable($input)) {
printf( "File \"%s\" is not readable. Usage: php %s <input>\n", $input, $script );
exit;
}

echo highlightSaffire(file_get_contents($input));

/**
* A function that can highlight a string that contains Saffire syntax.
*
* @param string $text
* @author Richard van Velzen https://github.com/rvanvelzen
*/
function highlightSaffire($text) {
$pointer = 0;
$length = strlen($text);
$output = array();

$ST_REGEX = 0;
$ST_DIV = 1;

$state = $ST_REGEX; // 0 is st_regex, 1 is st_div

while ($pointer < $length) {
if (!preg_match('~(?x)
(?P<comment> //.* | /\*([^*]|\*[^/])*\*/ )
| (?P<keyword> \b (?:
if | else | use | as | do | for | foreach | switch | class | extends
| implements | abstract | final | interface | const | static | public
| private | protected | method | readonly | property | catch | finally
| throw | return | break | breakelse | continue | try | default | goto
| case | self | parent | yield | in
) \b )
| (?P<operator> (?: [<>]{2} | [-+*/%&|^\~<>=!] ) = | [|&<>+-]{2} | [][+%<>(){}:;=,.?!*^|-]
' . ($state === $ST_DIV ? ' | / ' : '') . ')
| (?P<regex> ' . ($state === $ST_DIV ? '(?!)' : '
/[^/\\\\]*(?:\\\\.[^/\\\\]*)*/[a-z]*
' ) . ')
| (?P<identifier> ::\+ | [$a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]* | [a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]* [?!]? )
| (?P<string> "[^"]*" | \'[^\']*\' )
| (?P<whitespace> \s+ )
| (?P<number> \d+ )
| (?P<error> [\s\S] )
~u', $text, $match, null, $pointer)) {
break;
}

$lexeme = htmlspecialchars($match[0]);

$type = null;
foreach (array(
'comment' => array('comment', null),
'keyword' => array('keyword', $ST_REGEX),
'identifier' => array('identifier', $ST_DIV),
'string' => array('string', $ST_DIV),
'number' => array('number', $ST_DIV),
'operator' => array('operator', $ST_REGEX),
'regex' => array('regex', $ST_DIV),
'whitespace' => array(null, null)
) as $index => $class) {
if (isset($match[$index]) && strlen($match[$index])) {
list($class, $newState) = $class;
$type = $class;

if ($newState !== null) {
$state = $newState;
}

break;
}
}

$output[] = $type ? '<span class="' . $type . '">' . $lexeme . '</span>' : $lexeme;
$pointer += strlen($match[0]);
}

return '<pre class="source saffire">' . implode($output) . '</pre>';
}
45 changes: 23 additions & 22 deletions httpdocs/index.html
Expand Up @@ -88,39 +88,40 @@ <h2>Tutorial</h2>

<p><em>Example 1:</em> The mandatory hello world example:</p>

<pre class="code">
use io;
io.print("Hello world");</pre>
<pre class="source saffire"><span class="keyword">use</span> <span class="identifier">io</span><span class="operator">;</span>
<span class="identifier">io</span><span class="operator">.</span><span class="identifier">print</span><span class="operator">(</span><span class="string">&quot;Hello world&quot;</span><span class="operator">)</span><span class="operator">;</span>
</pre>

<p><em>Example 2:</em> Using variables:</p>
<pre class="code">
use io;

$a = 1;
$a += 1;
<pre class="source saffire"><span class="keyword">use</span> <span class="identifier">io</span><span class="operator">;</span>

io.print("The value of $a: ", $a , "\n");</pre>
<span class="identifier">$a</span> <span class="operator">=</span> <span class="number">1</span><span class="operator">;</span>
<span class="identifier">$a</span> <span class="operator">+=</span> <span class="number">1</span><span class="operator">;</span>

<span class="identifier">io</span><span class="operator">.</span><span class="identifier">print</span><span class="operator">(</span><span class="string">&quot;The value of $a: &quot;</span><span class="operator">,</span> <span class="identifier">$a</span> <span class="operator">,</span> <span class="string">&quot;\n&quot;</span><span class="operator">)</span><span class="operator">;</span>
</pre>

<p><em>Example 3:</em> A simple class in Saffire:</p>
<pre class="code">
use io;
<pre class="source saffire"><span class="keyword">use</span> <span class="identifier">io</span><span class="operator">;</span>

class Foo {
const FOOBAR = "foobar";
<span class="keyword">class</span> <span class="identifier">Foo</span> <span class="operator">{</span>
<span class="keyword">const</span> <span class="identifier">FOOBAR</span> <span class="operator">=</span> <span class="string">&quot;foobar&quot;</span><span class="operator">;</span>

protected property $a = 1;
<span class="keyword">protected</span> <span class="keyword">property</span> <span class="identifier">$a</span> <span class="operator">=</span> <span class="number">1</span><span class="operator">;</span>

public method ctor() {
// Constructor
}
<span class="keyword">public</span> <span class="keyword">method</span> <span class="identifier">ctor</span><span class="operator">(</span><span class="operator">)</span> <span class="operator">{</span>
<span class="comment">// Constructor</span>
<span class="operator">}</span>

public method foo() {
return $a;
}
}
<span class="keyword">public</span> <span class="keyword">method</span> <span class="identifier">foo</span><span class="operator">(</span><span class="operator">)</span> <span class="operator">{</span>
<span class="keyword">return</span> <span class="identifier">$a</span><span class="operator">;</span>
<span class="operator">}</span>
<span class="operator">}</span>

$f = Foo();
io.print ("The value is: ", $f.foo());</pre>
<span class="identifier">$f</span> <span class="operator">=</span> <span class="identifier">Foo</span><span class="operator">(</span><span class="operator">)</span><span class="operator">;</span>
<span class="identifier">io</span><span class="operator">.</span><span class="identifier">print</span> <span class="operator">(</span><span class="string">&quot;The value is: &quot;</span><span class="operator">,</span> <span class="identifier">$f</span><span class="operator">.</span><span class="identifier">foo</span><span class="operator">(</span><span class="operator">)</span><span class="operator">)</span><span class="operator">;</span>
</pre>
</div>
</section>

Expand Down
55 changes: 47 additions & 8 deletions httpdocs/style.css
Expand Up @@ -47,6 +47,19 @@ nav a, footer a {
text-decoration: none;
}

/**
* The fork-me banner on the right.
*/
#fork-me {
background: transparent url('images/fork-me.png') no-repeat;
position: fixed;
right: 0px;
height: 149px;
width: 149px;
z-index: 2;
}


/**
* Reusable styles for each section.
*/
Expand All @@ -72,7 +85,6 @@ a {
}

.code {
font-family: "Lucida Console", "Monaco", monospace;
color: #387abb;
}

Expand Down Expand Up @@ -137,11 +149,38 @@ footer {
background: #2f353b url('images/footer-bg.png') repeat-x;
}

#fork-me {
background: transparent url('images/fork-me.png') no-repeat;
position: fixed;
right: 0px;
height: 149px;
width: 149px;
z-index: 2;
/**
* The following is for syntax highlighting.
*/
.source.saffire {
font-family: "Lucida Console", "Monaco", monospace;
color: #000;
}

.source.saffire .comment {
color: #666;
}

.source.saffire .keyword {
color: #387ABB;
}

.source.saffire .identifier {
color: #38BC38;
}

.source.saffire .string {
color: #BC3838;
}

.source.saffire .number {
color: #BC38BC;
}

.source.saffire .operator {
color: #3838BC;
}

.source.saffire .regex {
color: #BC38BC;
}

0 comments on commit 4f16a97

Please sign in to comment.