2015-07-15 21:26:01 +00:00
|
|
|
<!DOCTYPE html>
|
|
|
|
<html lang="en">
|
|
|
|
<head>
|
|
|
|
<title>PEG Playground</title>
|
|
|
|
<style>
|
|
|
|
* {
|
|
|
|
box-sizing: border-box;
|
|
|
|
margin: 0;
|
|
|
|
padding: 0;
|
|
|
|
text-decoration: none;
|
|
|
|
list-style: none;
|
|
|
|
}
|
|
|
|
body {
|
|
|
|
display: flex;
|
2015-07-17 00:18:46 +00:00
|
|
|
display: -webkit-flex;
|
2015-07-15 21:26:01 +00:00
|
|
|
flex-direction: column;
|
2015-07-17 00:18:46 +00:00
|
|
|
-webkit-flex-direction: column;
|
2015-07-15 21:26:01 +00:00
|
|
|
height: 100vh;
|
|
|
|
}
|
|
|
|
#main {
|
|
|
|
flex: 1;
|
2015-07-17 00:18:46 +00:00
|
|
|
-webkit-flex: 1;
|
2015-07-15 21:26:01 +00:00
|
|
|
display: none;
|
|
|
|
}
|
|
|
|
.editor-container {
|
|
|
|
flex: 1;
|
2015-07-17 00:18:46 +00:00
|
|
|
-webkit-flex: 1;
|
2015-07-15 21:26:01 +00:00
|
|
|
width: 100%;
|
|
|
|
display: flex;
|
2015-07-17 00:18:46 +00:00
|
|
|
display: -webkit-flex;
|
2015-07-15 21:26:01 +00:00
|
|
|
flex-direction: column;
|
2015-07-17 00:18:46 +00:00
|
|
|
-webkit-flex-direction: column;
|
2015-07-15 21:26:01 +00:00
|
|
|
margin: 8px;
|
|
|
|
}
|
|
|
|
.editor-container:first-child {
|
|
|
|
margin-right: 0;
|
|
|
|
}
|
|
|
|
.editor-header {
|
|
|
|
display: flex;
|
2015-07-17 00:18:46 +00:00
|
|
|
display: -webkit-flex;
|
2015-07-15 21:26:01 +00:00
|
|
|
height: 48px;
|
|
|
|
padding: 4px 8px;
|
|
|
|
}
|
|
|
|
.editor-header > li:last-child {
|
|
|
|
margin-left: auto;
|
|
|
|
}
|
|
|
|
.editor-header > li > span {
|
|
|
|
height: 38px;
|
|
|
|
line-height: 38px;
|
|
|
|
}
|
|
|
|
.editor-header > li > a {
|
|
|
|
height: 38px;
|
|
|
|
line-height: 38px;
|
|
|
|
padding: .3em .5em;
|
|
|
|
border: 1px solid red;
|
|
|
|
}
|
|
|
|
.editor-validation {
|
|
|
|
height: 38px;
|
|
|
|
line-height: 38px;
|
|
|
|
padding: .4em .6em;
|
|
|
|
color: green;
|
|
|
|
background-color: lightgreen;
|
|
|
|
border-radius: 5px;
|
|
|
|
}
|
|
|
|
.editor-validation-invalid {
|
|
|
|
color: red;
|
|
|
|
background-color: pink;
|
|
|
|
}
|
|
|
|
.editor-area {
|
|
|
|
flex: 1;
|
2015-07-17 00:18:46 +00:00
|
|
|
-webkit-flex: 1;
|
2015-07-15 21:26:01 +00:00
|
|
|
border: 1px solid lightgray;
|
|
|
|
}
|
|
|
|
.editor-info {
|
|
|
|
margin-top: 6px;
|
|
|
|
height: 160px;
|
|
|
|
border: 1px solid lightgray;
|
|
|
|
padding: 8px;
|
|
|
|
}
|
|
|
|
.editor-info li {
|
|
|
|
cursor: pointer;
|
|
|
|
}
|
|
|
|
</style>
|
|
|
|
</head>
|
|
|
|
<body>
|
|
|
|
|
|
|
|
<div id="main">
|
|
|
|
<div class="editor-container">
|
|
|
|
<ul class="editor-header">
|
|
|
|
<li><span>Grammar:</span></li>
|
|
|
|
<li><span id="grammar-validation" class="editor-validation">Valid</span></li>
|
|
|
|
</ul>
|
|
|
|
<pre id="grammar-editor" class="editor-area">
|
|
|
|
EXPRESSION <- _ TERM (TERM_OPERATOR TERM)*
|
|
|
|
TERM <- FACTOR (FACTOR_OPERATOR FACTOR)*
|
|
|
|
FACTOR <- NUMBER / '(' _ EXPRESSION ')' _
|
|
|
|
TERM_OPERATOR <- < [-+] > _
|
|
|
|
FACTOR_OPERATOR <- < [/*] > _
|
|
|
|
NUMBER <- < [0-9]+ > _
|
|
|
|
~_ <- [ \t\r\n]*</pre>
|
|
|
|
<div id="grammar-info" class="editor-info"></div>
|
|
|
|
</div>
|
|
|
|
<div class="editor-container">
|
|
|
|
<ul class="editor-header">
|
|
|
|
<li><span>Code:</span></li>
|
|
|
|
<li><span id="code-validation" class="editor-validation">Valid</span></li>
|
|
|
|
</ul>
|
|
|
|
<pre id="code-editor" class="editor-area">2 * (3 + 4)</pre>
|
|
|
|
<div id="code-info" class="editor-info"></div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.1.9/ace.js"></script>
|
|
|
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
|
|
|
|
<script>
|
|
|
|
// Setup editros
|
|
|
|
var grammar = ace.edit("grammar-editor");
|
|
|
|
grammar.setShowPrintMargin(false);
|
|
|
|
|
|
|
|
var code = ace.edit("code-editor");
|
|
|
|
code.setShowPrintMargin(false);
|
|
|
|
|
|
|
|
var generateErrorListHTML = function (errors) {
|
|
|
|
var html = '<ul>';
|
|
|
|
|
|
|
|
html += $.map(errors, function (x) {
|
|
|
|
return '<li data-ln="' + x.ln + '" data-col="' + x.col + '"><span>' + x.ln + ':' + x.col + '</span> <span>' + x.msg + '</span></li>';
|
|
|
|
}).join('');
|
|
|
|
|
|
|
|
html += '<ul>';
|
|
|
|
|
|
|
|
return html;
|
|
|
|
};
|
|
|
|
|
|
|
|
var parse = function () {
|
|
|
|
var $grammarValidation = $('#grammar-validation');
|
|
|
|
var $grammarInfo = $('#grammar-info');
|
|
|
|
var grammarText = grammar.getValue();
|
|
|
|
|
|
|
|
var $codeValidation = $('#code-validation');
|
|
|
|
var $codeInfo = $('#code-info');
|
|
|
|
var codeText = code.getValue();
|
|
|
|
|
|
|
|
$.post("/parse", {
|
|
|
|
grammar: grammarText,
|
|
|
|
code: codeText
|
|
|
|
}).done(function (data) {
|
|
|
|
var isValid = data.grammar.length === 0;
|
|
|
|
if (isValid) {
|
|
|
|
$grammarInfo.html('');
|
|
|
|
$grammarValidation.removeClass('editor-validation-invalid').text('Valid');
|
|
|
|
|
|
|
|
var isValid = data.code.length === 0;
|
|
|
|
if (isValid) {
|
|
|
|
$codeInfo.html('');
|
|
|
|
$codeValidation.removeClass('editor-validation-invalid').text('Valid');
|
|
|
|
} else {
|
|
|
|
var html = generateErrorListHTML(data.code);
|
|
|
|
$codeInfo.html(html);
|
|
|
|
$codeValidation.addClass('editor-validation-invalid').text('Invalid');
|
|
|
|
}
|
|
|
|
$codeValidation.show();
|
|
|
|
} else {
|
|
|
|
var html = generateErrorListHTML(data.grammar);
|
|
|
|
$grammarInfo.html(html);
|
|
|
|
$grammarValidation.addClass('editor-validation-invalid').text('Invalid');
|
|
|
|
|
|
|
|
$codeValidation.hide();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
// Event handing for text editiing
|
|
|
|
var timer;
|
|
|
|
var setupTimer = function () {
|
|
|
|
clearTimeout(timer);
|
|
|
|
timer = setTimeout(parse, 750);
|
|
|
|
};
|
|
|
|
grammar.getSession().on('change', setupTimer);
|
|
|
|
code.getSession().on('change', setupTimer);
|
|
|
|
|
|
|
|
// Event handing in the info area
|
|
|
|
var makeOnClickInInfo = function (editor) {
|
|
|
|
return function () {
|
|
|
|
var el = $(this);
|
|
|
|
editor.navigateTo(el.data('ln') - 1, el.data('col') - 1);
|
|
|
|
editor.focus();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
$('#grammar-info').on('click', 'li', makeOnClickInInfo(grammar));
|
|
|
|
$('#code-info').on('click', 'li', makeOnClickInInfo(code));
|
|
|
|
|
|
|
|
// Show page
|
2015-07-17 00:18:46 +00:00
|
|
|
$('#main').css({
|
|
|
|
'display': 'flex',
|
|
|
|
'display': '-webkit-flex'
|
|
|
|
});
|
2015-07-15 21:26:01 +00:00
|
|
|
|
|
|
|
// Initial parse
|
|
|
|
parse();
|
|
|
|
</script>
|
|
|
|
</body>
|
|
|
|
</html>
|
|
|
|
|