Skip to content

Commit

Permalink
new user interface, app state is saved to localStorage
Browse files Browse the repository at this point in the history
  • Loading branch information
Ondrej Zdych committed May 16, 2014
1 parent d8c0d59 commit dd6dde9
Show file tree
Hide file tree
Showing 13 changed files with 219 additions and 48 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
node_modules
dist
.sublime-gulp.cache
30 changes: 29 additions & 1 deletion app/Parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ export default class Parser {
// scope chain for identifier lookup
this._scopeChain = []; // of scopes

// list of accumulated warnings
this._warnings = [];

// create global scope
this.pushScope(ScopeType.Function, this._globals);
}
Expand Down Expand Up @@ -111,6 +114,22 @@ export default class Parser {
return this._state;
}

/**
* Returns list of warnings.
*/
get warnings () {
return this._warnings;
}

/**
* Adds and formats warning message.
*/
addWarning (message) {
message = this._formatMessage(message);

this._warnings.push(message);
}

/**
* Registers prefix operator expression parser.
*/
Expand Down Expand Up @@ -173,6 +192,7 @@ export default class Parser {
this.throw(`Unexpected token '${token.value}'`);
}

// get prexix parser
var left = prefixParser.parse(this);

while (precedence < this.getPrecedence()) {
Expand All @@ -182,7 +202,9 @@ export default class Parser {
break;
}

// get infix parser
let infixParser = this.getInfixExpressionParser(token);

left = infixParser.parse(this, left);
}

Expand Down Expand Up @@ -426,9 +448,15 @@ export default class Parser {
* Throws error with line and column information.
*/
throw (message, _Error = SyntaxError) {
message = this._formatMessage(message);

throw new _Error(message);
}

_formatMessage (message) {
var { line, column } = this._lexer.lineAndColumn;

throw new _Error(`ln: ${line}, col: ${column} - ${message}.`);
return `ln: ${line}, col: ${column} - ${message}.`;
}

/**
Expand Down
2 changes: 1 addition & 1 deletion app/Transformer.js
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ export default class Transformer {
}

if (declarators.length) {
return new DeclarationStatement(declarators, Keyword.Var);
return new DeclarationStatement(declarators, Keyword.Var);
}

return null;
Expand Down
13 changes: 13 additions & 0 deletions app/code.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
export default code =

`let a, b=a+5*9;
// function defaults parameters
function fn(bb=b+1,b='ahoj') {
let c = 28,d;
// binary numbers
c+=0b11101;
return a+1-2.e-10*0xabcd;
}
fn(b, null);`;
2 changes: 1 addition & 1 deletion app/expressions/parsers/IdentifierExpressionParser.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export default class IdentifierExpressionParser extends PrefixExpressionParser {
var id = token.value;

if (!withoutDefinitionCheck && !parser.scope.isVariableDefined(id)) {
parser.throw(`'${id}' is not defined`, ReferenceError);
parser.addWarning(`'${id}' is not defined`);
}

return new IdentifierExpression(id);
Expand Down
112 changes: 88 additions & 24 deletions app/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,51 +2,115 @@ import { Lexer } from './Lexer';
import MyParser from './MyParser';
import Transformer from './Transformer';

// import some code for textarea
import defaultCode from './code';

var sourceInput = document.getElementById('source');
var btnDo = document.getElementById('do');
var preTokens = document.getElementById('tokens');
var preAST = document.getElementById('ast');
var preOutput = document.getElementById('output');
var tokensArea = document.getElementById('tokens-area');
var astArea = document.getElementById('ast-area');
var outputArea = document.getElementById('output-area');
var $tabs = $('#tabs');

var warns = document.getElementById('warns');
var errors = document.getElementById('errors');

var LOCAL_STORAGE_KEY_CODE = 'lang_parser_code';
var LOCAL_STORAGE_KEY_SEL_TAB = 'lang_parser_sel_tab';

var lexer = new Lexer();
var parser = new MyParser(lexer);
var transformer = new Transformer();

sourceInput.value =
`let a, b=a+5*9;
function loadCode () {
var fromStorage = localStorage.getItem(LOCAL_STORAGE_KEY_CODE);

// function defaults parameters
function fn(bb=b+1,b='ahoj') {
let c = 28,d;
if (fromStorage) {
sourceInput.value = fromStorage;
}
else {
sourceInput.value = defaultCode;
}
}

// binary numbers
c+=0b11101;
function loadSelectedTab () {
var tab = localStorage.getItem(LOCAL_STORAGE_KEY_SEL_TAB);

return a+1-2.e-10*0xabcd;
}
fn(b, null);`;
if (!tab) {
tab = '#ast';
}

var oldSource = '';
$tabs.find('a[href="' + tab + '"]').tab('show');
}

function _do () {
function process () {
lexer.source = sourceInput.value;
oldSource = sourceInput.value;

try {
let tokens = lexer.dump();
let ast = parser.parseProgram();
$(preAST).JSONView(JSON.stringify(ast));
preOutput.innerHTML = transformer.visitProgram(ast);

// show warnings
showWarnings(parser.warnings);

$(astArea).JSONView(JSON.stringify(ast));
$(tokensArea).JSONView(tokens);
outputArea.innerHTML = transformer.visitProgram(ast);

// hide error
showError(false);
}
catch (ex) {
preAST.innerHTML = ex.message;
preOutput.innerHTML = '';
// show error
showError(ex.message);

astArea.innerHTML = '';
tokensArea.innerHTML = '';
outputArea.innerHTML = '';
console.log(ex);
}
}

(function _t () {
if (oldSource != sourceInput.value) {
_do();
function showError (err) {
errors.style.display = 'none';

if (err) {
errors.style.display = 'block';
errors.innerHTML = err;
}
}

function showWarnings (warnings) {
warns.style.display = 'none';

if (warnings && warnings.length) {
warns.style.display = 'block';
warns.innerHTML = warnings;
}
setTimeout(_t, 150);
}

var oldSource = '';

// set editor data
loadCode();

(function update () {
var code = sourceInput.value;

if (oldSource != code) {
process();

localStorage.setItem(LOCAL_STORAGE_KEY_CODE, code);
}
setTimeout(update, 150);
})();

$(function () {
loadSelectedTab();

$tabs.on('click', 'a', function (e) {
localStorage.setItem(LOCAL_STORAGE_KEY_SEL_TAB, e.target.getAttribute('href'));

console.log(localStorage.getItem(LOCAL_STORAGE_KEY_SEL_TAB));
})
});
5 changes: 2 additions & 3 deletions app/statements/parsers/FunctionDeclarationStatementParser.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,12 @@ export default class FunctionDeclarationStatementParser extends StatementParser
// inject arguments
arguments: Keyword.Var
};
var params = [];
var body = null;

// defined variable in current scope
parser.scope.define(id.name, Keyword.Var);

var params = [];
var body = null;

parser.consume(Punctuator.OpenParen);

if (!parser.match(Punctuator.CloseParen)) {
Expand Down
32 changes: 32 additions & 0 deletions css/app.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
body {
padding: 0 30px;
}

pre {
font-size: 1.1em;
}

#code {
float: left;
}

#code textarea {
font-family: monospace;
font-size: 1.1em;
height:800px;
width:600px;
}

#tabs-container {
padding-left: 50px;
float: left;
width: 1000px;
}

#tabs-container .tab-pane {
padding-top: 20px;
}

#warns, #errors {
display: none;
}
7 changes: 7 additions & 0 deletions css/bootstrap.min.css

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion css/jquery.jsonview.css
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
@charset "UTF-8";
.jsonview {
font-family: monospace;
font-size: 1.1em;
font-size: 1.0em;
white-space: pre-wrap; }
.jsonview .prop {
font-weight: bold; }
Expand Down
5 changes: 2 additions & 3 deletions gulpfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,12 +55,11 @@ gulp.task('serve', function() {
});

gulp.task('clean', function() {
return gulp.src(distFolder, {force: true})
.pipe(clean());
return gulp.src(distFolder, { force: true }).pipe(clean());
});

gulp.task('watch', function() {
return gulp.watch(srcFolder + '/**/*.js', ['scripts']);
return gulp.watch([ srcFolder + '/**/*.js', '*.js' ], ['scripts']);
});

gulp.task('default', ['scripts', 'serve', 'watch']);
50 changes: 36 additions & 14 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,31 +2,53 @@
<html>
<head>
<title>Lang Parser</title>
<link rel="stylesheet" href="css/jquery.jsonview.css" />
<link rel="stylesheet" href="css/bootstrap.min.css">
<link rel="stylesheet" href="css/jquery.jsonview.css"/>
<link rel="stylesheet" href="css/app.css"/>

<script src="lib/jquery-1.11.1.min.js"></script>
<script src="lib/bootstrap.min.js"></script>
<script src="lib/jquery.jsonview.js"></script>
<script src="lib/traceur-runtime.min.js"></script>
<script src="lib/es6-module-loader.min.js"></script>
<script src="lib/system.js"></script>
</head>
<body>

<div>
<div style="float:left">
<h3>Code</h3>
<textarea id="source" style="height:800px;width:600px;"></textarea>
<div id="code">
<h3>Input</h3>
<textarea id="source"></textarea>
</div>

<div style="float:left;padding-left:20px;">
<h3>AST</h3>
<pre id="ast" ></pre>
</div>
<div id="tabs-container">
<h3>Output</h3>

<div id="warns" class="alert alert-warning"></div>
<div id="errors" class="alert alert-danger"></div>

<ul id="tabs" class="nav nav-tabs">
<li>
<a href="#ast" data-toggle="tab">AST</a>
</li>
<li>
<a href="#tokens" data-toggle="tab">Tokens</a>
</li>
<li>
<a href="#compiled-code" data-toggle="tab">Compiled code</a>
</li>
</ul>

<div style="float:left;padding-left:20px;">
<h3>Compiled</h3>
<pre id="output" ></pre>
<div class="tab-content">
<div class="tab-pane" id="ast">
<div id="ast-area"></div>
</div>
<div class="tab-pane" id="tokens">
<div id="tokens-area"></div>
</div>
<div class="tab-pane" id="compiled-code">
<pre id="output-area"></pre>
</div>
</div>
</div>
</div>

<script>
(function (prodMode) {
Expand Down
6 changes: 6 additions & 0 deletions lib/bootstrap.min.js

Large diffs are not rendered by default.

0 comments on commit dd6dde9

Please sign in to comment.