From 56bf4878236f5464ba19d27b4342fa2a3a99eac6 Mon Sep 17 00:00:00 2001 From: Lizzy Hunt Date: Thu, 16 Nov 2023 19:06:35 -0700 Subject: [PATCH] add compiler --- godel/css/styles.css | 11 + godel/grammar.peg | 29 +- godel/index.html | 73 +++-- godel/js-beautify/js-beautify.js | 1 + godel/js/compiler.js | 163 ++++++++++ godel/js/main.js | 120 +++++++- godel/{ => js}/parser.js | 493 +++++++++++++++++++------------ 7 files changed, 666 insertions(+), 224 deletions(-) create mode 100644 godel/js-beautify/js-beautify.js create mode 100644 godel/js/compiler.js rename godel/{ => js}/parser.js (67%) diff --git a/godel/css/styles.css b/godel/css/styles.css index 8820b40..b9c5c10 100644 --- a/godel/css/styles.css +++ b/godel/css/styles.css @@ -39,10 +39,21 @@ body { border: 2px solid white; border-radius: 0.25rem; padding: 1rem; + flex: 1; +} + +.source-container { + display: flex; + flex-direction: row; + gap: 1rem; + height: 100%; } textarea { border-radius: 0.25rem; +} + +.CodeMirror { height: 50vh; } diff --git a/godel/grammar.peg b/godel/grammar.peg index 1096b00..73ba08e 100644 --- a/godel/grammar.peg +++ b/godel/grammar.peg @@ -1,8 +1,8 @@ -Program = instructions: Line* { - return { instructions: instructions }; +Program = lines: (Line / (_/[\n]))* { + return { instructions: lines.filter((line) => typeof line !== "string" || line.trim() != "") }; } -Line = instruction: (LabeledInstruction / Instruction) _ { +Line = _? instruction: (LabeledInstruction / Instruction) _? [\n]? { return instruction; } @@ -16,9 +16,14 @@ Label = "[" _? label:LABEL_V _? "]" { Instruction = conditional: Conditional { return { conditional }; } / assignment: Assignment { return { assignment }; } + / goto: Goto { return { goto }; } -Conditional = "IF" _ variable: VAR _ "!=" _ "0" _ "GOTO" _ label: Label { - return { variable, label }; +Goto = GOTO _ label: LABEL_V { + return { label }; +} + +Conditional = "IF" _ variable: VAR _? "!=" _? "0" _ goto: Goto { + return { variable, goto }; } Assignment = variable: VAR _ "<-" _ expr: Expression { @@ -30,19 +35,25 @@ Assignment = variable: VAR _ "<-" _ expr: Expression { Expression = left: VAR _ opr: OPERATION _ "1" { return { left, opr }; +} / left: VAR { + return { left }; } VAR = symbol:"Y" { return symbol } / symbol:("X" / "Z") ind:Integer+ { return symbol + ind; } +GOTO = "GOTO" + OPERATION = "+" / "-" -LABEL_V = symbol:[A-E] ind:Integer+ { +LABEL_V = symbol:END_LABEL { return symbol } / symbol:[A-E] ind:Integer+ { return symbol + ind; } -Integer "integer" - = _ [0-9]+ { return parseInt(text(), 10); } +END_LABEL = "E" -_ "whitespace" = [ \t\n\r]* { } +Integer "integer" + = [0-9]+ { return parseInt(text(), 10); } + +_ "whitespace" = [ \t]+ { } diff --git a/godel/index.html b/godel/index.html index 84cde8f..055f13d 100644 --- a/godel/index.html +++ b/godel/index.html @@ -1,35 +1,46 @@ - + - - L-Program Compiler - - - - -
-

L-Program Compiler

-

Developed for Kulyukin's CS5000

-
-
- -
- -
-
- + + Liz's L-Program Compiler + + + + +
+

Liz's L-Program Compiler

+

Developed for Kulyukin's CS5000

+
+
+
+

L Source

+ +
+ +
+
+
+

Compiled JS

+ +
+ +
+
-
- - - - - + + + + + + + + diff --git a/godel/js-beautify/js-beautify.js b/godel/js-beautify/js-beautify.js new file mode 100644 index 0000000..342352d --- /dev/null +++ b/godel/js-beautify/js-beautify.js @@ -0,0 +1 @@ +!function(){!function(){"use strict";var n=[function(t,e,i){var n=i(1).Beautifier,u=i(5).Options;t.exports=function(t,e){return new n(t,e).beautify()},t.exports.defaultOptions=function(){return new u}},function(t,e,i){var n=i(2).Output,u=i(3).Token,o=i(4),_=i(5).Options,s=i(7).Tokenizer,r=i(7).line_starters,h=i(7).positionable_operators,p=i(7).TOKEN;function l(t,e){return-1!==e.indexOf(t)}function a(t,e){return t&&t.type===p.RESERVED&&t.text===e}function f(t,e){return t&&t.type===p.RESERVED&&l(t.text,e)}var c=["case","return","do","if","throw","else","await","break","continue","async"],d=function(t){for(var e={},i=0;ii&&(i=t.line_indent_level)),{mode:e,parent:t,last_token:t?t.last_token:new u(p.START_BLOCK,""),last_word:t?t.last_word:"",declaration_statement:!1,declaration_assignment:!1,multiline_frame:!1,inline_frame:!1,if_block:!1,else_block:!1,class_start_block:!1,do_block:!1,do_while:!1,import_block:!1,in_case_statement:!1,in_case:!1,case_body:!1,case_block:!1,indentation_level:i,alignment:0,line_indent_level:t?t.line_indent_level:i,start_line_index:this._output.get_line_number(),ternary_depth:0}},T.prototype._reset=function(t){var e=t.match(/^[\t ]*/)[0],e=(this._last_last_text="",this._output=new n(this._options,e),this._output.raw=this._options.test_output_raw,this._flag_store=[],this.set_mode(g),new s(t,this._options));return this._tokens=e.tokenize(),t},T.prototype.beautify=function(){if(this._options.disabled)return this._source_text;for(var t=this._reset(this._source_text),e=this._options.eol,i=("auto"===this._options.eol&&(e="\n",t&&o.lineBreak.test(t||"")&&(e=t.match(o.lineBreak)[0])),this._tokens.next());i;)this.handle_token(i),this._last_last_text=this._flags.last_token.text,this._flags.last_token=i,i=this._tokens.next();return this._output.get_code(e)},T.prototype.handle_token=function(t,e){t.type===p.START_EXPR?this.handle_start_expr(t):t.type===p.END_EXPR?this.handle_end_expr(t):t.type===p.START_BLOCK?this.handle_start_block(t):t.type===p.END_BLOCK?this.handle_end_block(t):t.type===p.WORD||t.type===p.RESERVED?this.handle_word(t):t.type===p.SEMICOLON?this.handle_semicolon(t):t.type===p.STRING?this.handle_string(t):t.type===p.EQUALS?this.handle_equals(t):t.type===p.OPERATOR?this.handle_operator(t):t.type===p.COMMA?this.handle_comma(t):t.type===p.BLOCK_COMMENT?this.handle_block_comment(t,e):t.type===p.COMMENT?this.handle_comment(t,e):t.type===p.DOT?this.handle_dot(t):t.type===p.EOF?this.handle_eof(t):(t.type,p.UNKNOWN,this.handle_unknown(t,e))},T.prototype.handle_whitespace_and_comments=function(t,e){var i=t.newlines,n=this._options.keep_array_indentation&&R(this._flags.mode);if(t.comments_before)for(var u=t.comments_before.next();u;)this.handle_whitespace_and_comments(u,e),this.handle_token(u,e),u=t.comments_before.next();if(n)for(var _=0;_this._options.max_preserve_newlines&&(i=this._options.max_preserve_newlines),this._options.preserve_newlines&&1this._flags.parent.indentation_level)&&(--this._flags.indentation_level,this._output.set_indent(this._flags.indentation_level,this._flags.alignment))},T.prototype.set_mode=function(t){this._flags?(this._flag_store.push(this._flags),this._previous_flags=this._flags):this._previous_flags=this.create_flags(null,t),this._flags=this.create_flags(this._previous_flags,t),this._output.set_indent(this._flags.indentation_level,this._flags.alignment)},T.prototype.restore_mode=function(){0"!==this._flags.last_token.text)&&(l(this._flags.last_token.type,[p.EQUALS,p.START_EXPR,p.COMMA,p.OPERATOR])||f(this._flags.last_token,["return","throw","import","default"]))?this.set_mode(m):this.set_mode(g),this._flags.last_token&&f(this._flags.last_token.previous,["class","extends"])&&(this._flags.class_start_block=!0),!e.comments_before&&"}"===e.text),e=i&&"function"===this._flags.last_word&&this._flags.last_token.type===p.END_EXPR;if(this._options.brace_preserve_inline){var n=0,u=null;this._flags.inline_frame=!0;do{if((u=this._tokens.peek((n+=1)-1)).newlines){this._flags.inline_frame=!1;break}}while(u.type!==p.EOF&&(u.type!==p.END_BLOCK||u.opened!==t))}("expand"===this._options.brace_style||"none"===this._options.brace_style&&t.newlines)&&!this._flags.inline_frame?this._flags.last_token.type!==p.OPERATOR&&(e||this._flags.last_token.type===p.EQUALS||f(this._flags.last_token,c)&&"else"!==this._flags.last_token.text)?this._output.space_before_token=!0:this.print_newline(!1,!0):(!R(this._previous_flags.mode)||this._flags.last_token.type!==p.START_EXPR&&this._flags.last_token.type!==p.COMMA||(this._flags.last_token.type!==p.COMMA&&!this._options.space_in_paren||(this._output.space_before_token=!0),(this._flags.last_token.type===p.COMMA||this._flags.last_token.type===p.START_EXPR&&this._flags.inline_frame)&&(this.allow_wrap_or_preserved_newline(t),this._previous_flags.multiline_frame=this._previous_flags.multiline_frame||this._flags.multiline_frame,this._flags.multiline_frame=!1)),this._flags.last_token.type!==p.OPERATOR&&this._flags.last_token.type!==p.START_EXPR&&(l(this._flags.last_token.type,[p.START_BLOCK,p.SEMICOLON])&&!this._flags.inline_frame?this.print_newline():this._output.space_before_token=!0)),this.print_token(t),this.indent(),i||this._options.brace_preserve_inline&&this._flags.inline_frame||this.print_newline()},T.prototype.handle_end_block=function(t){for(this.handle_whitespace_and_comments(t);this._flags.mode===k;)this.restore_mode();var e=this._flags.last_token.type===p.START_BLOCK;this._flags.inline_frame&&!e?this._output.space_before_token=!0:"expand"===this._options.brace_style?e||this.print_newline():e||(R(this._flags.mode)&&this._options.keep_array_indentation?(this._options.keep_array_indentation=!1,this.print_newline(),this._options.keep_array_indentation=!0):this.print_newline()),this.restore_mode(),this.print_token(t)},T.prototype.handle_word=function(t){if(t.type===p.RESERVED&&(l(t.text,["set","get"])&&this._flags.mode!==m||"import"===t.text&&l(this._tokens.peek().text,["(","."])||l(t.text,["as","from"])&&!this._flags.import_block||this._flags.mode===m&&":"===this._tokens.peek().text)&&(t.type=p.WORD),this.start_of_statement(t)?f(this._flags.last_token,["var","let","const"])&&t.type===p.WORD&&(this._flags.declaration_statement=!0):!t.newlines||O(this._flags.mode)||this._flags.last_token.type===p.OPERATOR&&"--"!==this._flags.last_token.text&&"++"!==this._flags.last_token.text||this._flags.last_token.type===p.EQUALS||!this._options.preserve_newlines&&f(this._flags.last_token,["var","let","const","set","get"])?this.handle_whitespace_and_comments(t):(this.handle_whitespace_and_comments(t),this.print_newline()),this._flags.do_block&&!this._flags.do_while){if(a(t,"while"))return this._output.space_before_token=!0,this.print_token(t),this._output.space_before_token=!0,void(this._flags.do_while=!0);this.print_newline(),this._flags.do_block=!1}if(this._flags.if_block)if(!this._flags.else_block&&a(t,"else"))this._flags.else_block=!0;else{for(;this._flags.mode===k;)this.restore_mode();this._flags.if_block=!1,this._flags.else_block=!1}if(this._flags.in_case_statement&&f(t,["case","default"]))return this.print_newline(),this._flags.case_block||!this._flags.case_body&&!this._options.jslint_happy||this.deindent(),this._flags.case_body=!1,this.print_token(t),void(this._flags.in_case=!0);if(this._flags.last_token.type!==p.COMMA&&this._flags.last_token.type!==p.START_EXPR&&this._flags.last_token.type!==p.EQUALS&&this._flags.last_token.type!==p.OPERATOR||this.start_of_object_property()||l(this._flags.last_token.text,["+","-"])&&":"===this._last_last_text&&this._flags.parent.mode===m||this.allow_wrap_or_preserved_newline(t),a(t,"function"))return!(l(this._flags.last_token.text,["}",";"])||this._output.just_added_newline()&&!l(this._flags.last_token.text,["(","[","{",":","=",","])&&this._flags.last_token.type!==p.OPERATOR)||this._output.just_added_blankline()||t.comments_before||(this.print_newline(),this.print_newline(!0)),this._flags.last_token.type===p.RESERVED||this._flags.last_token.type===p.WORD?f(this._flags.last_token,["get","set","new","export"])||f(this._flags.last_token,A)||a(this._flags.last_token,"default")&&"export"===this._last_last_text||"declare"===this._flags.last_token.text?this._output.space_before_token=!0:this.print_newline():this._flags.last_token.type===p.OPERATOR||"="===this._flags.last_token.text?this._output.space_before_token=!0:!this._flags.multiline_frame&&(O(this._flags.mode)||R(this._flags.mode))||this.print_newline(),this.print_token(t),void(this._flags.last_word=t.text);var e="NONE";this._flags.last_token.type===p.END_BLOCK?this._previous_flags.inline_frame?e="SPACE":!f(t,["else","catch","finally","from"])||"expand"===this._options.brace_style||"end-expand"===this._options.brace_style||"none"===this._options.brace_style&&t.newlines?e="NEWLINE":(e="SPACE",this._output.space_before_token=!0):this._flags.last_token.type===p.SEMICOLON&&this._flags.mode===g?e="NEWLINE":this._flags.last_token.type===p.SEMICOLON&&O(this._flags.mode)?e="SPACE":this._flags.last_token.type===p.STRING?e="NEWLINE":this._flags.last_token.type===p.RESERVED||this._flags.last_token.type===p.WORD||"*"===this._flags.last_token.text&&(l(this._last_last_text,["function","yield"])||this._flags.mode===m&&l(this._last_last_text,["{",","]))?e="SPACE":this._flags.last_token.type===p.START_BLOCK?e=this._flags.inline_frame?"SPACE":"NEWLINE":this._flags.last_token.type===p.END_EXPR&&(this._output.space_before_token=!0,e="NEWLINE"),f(t,r)&&")"!==this._flags.last_token.text&&(e=this._flags.inline_frame||"else"===this._flags.last_token.text||"export"===this._flags.last_token.text?"SPACE":"NEWLINE"),f(t,["else","catch","finally"])?(this._flags.last_token.type!==p.END_BLOCK||this._previous_flags.mode!==g||"expand"===this._options.brace_style||"end-expand"===this._options.brace_style||"none"===this._options.brace_style&&t.newlines)&&!this._flags.inline_frame?this.print_newline():(this._output.trim(!0),"}"!==this._output.current_line.last()&&this.print_newline(),this._output.space_before_token=!0):"NEWLINE"===e?f(this._flags.last_token,c)||"declare"===this._flags.last_token.text&&f(t,["var","let","const"])?this._output.space_before_token=!0:this._flags.last_token.type!==p.END_EXPR?this._flags.last_token.type===p.START_EXPR&&f(t,["var","let","const"])||":"===this._flags.last_token.text||(a(t,"if")&&a(t.previous,"else")?this._output.space_before_token=!0:this.print_newline()):f(t,r)&&")"!==this._flags.last_token.text&&this.print_newline():this._flags.multiline_frame&&R(this._flags.mode)&&","===this._flags.last_token.text&&"}"===this._last_last_text?this.print_newline():"SPACE"===e&&(this._output.space_before_token=!0),!t.previous||t.previous.type!==p.WORD&&t.previous.type!==p.RESERVED||(this._output.space_before_token=!0),this.print_token(t),this._flags.last_word=t.text,t.type===p.RESERVED&&("do"===t.text?this._flags.do_block=!0:"if"===t.text?this._flags.if_block=!0:"import"===t.text?this._flags.import_block=!0:this._flags.import_block&&a(t,"from")&&(this._flags.import_block=!1))},T.prototype.handle_semicolon=function(t){this.start_of_statement(t)?this._output.space_before_token=!1:this.handle_whitespace_and_comments(t);for(var e=this._tokens.peek();!(this._flags.mode!==k||this._flags.if_block&&a(e,"else")||this._flags.do_block);)this.restore_mode();this._flags.import_block&&(this._flags.import_block=!1),this.print_token(t)},T.prototype.handle_string=function(t){t.text.startsWith("`")&&0===t.newlines&&""===t.whitespace_before&&(")"===t.previous.text||this._flags.last_token.type===p.WORD)||(this.start_of_statement(t)?this._output.space_before_token=!0:(this.handle_whitespace_and_comments(t),this._flags.last_token.type===p.RESERVED||this._flags.last_token.type===p.WORD||this._flags.inline_frame?this._output.space_before_token=!0:this._flags.last_token.type===p.COMMA||this._flags.last_token.type===p.START_EXPR||this._flags.last_token.type===p.EQUALS||this._flags.last_token.type===p.OPERATOR?this.start_of_object_property()||this.allow_wrap_or_preserved_newline(t):!t.text.startsWith("`")||this._flags.last_token.type!==p.END_EXPR||"]"!==t.previous.text&&")"!==t.previous.text||0!==t.newlines?this.print_newline():this._output.space_before_token=!0)),this.print_token(t)},T.prototype.handle_equals=function(t){this.start_of_statement(t)||this.handle_whitespace_and_comments(t),this._flags.declaration_statement&&(this._flags.declaration_assignment=!0),this._output.space_before_token=!0,this.print_token(t),this._output.space_before_token=!0},T.prototype.handle_comma=function(t){this.handle_whitespace_and_comments(t,!0),this.print_token(t),this._output.space_before_token=!0,this._flags.declaration_statement?(O(this._flags.parent.mode)&&(this._flags.declaration_assignment=!1),this._flags.declaration_assignment?(this._flags.declaration_assignment=!1,this.print_newline(!1,!0)):this._options.comma_first&&this.allow_wrap_or_preserved_newline(t)):this._flags.mode===m||this._flags.mode===k&&this._flags.parent.mode===m?(this._flags.mode===k&&this.restore_mode(),this._flags.inline_frame||this.print_newline()):this._options.comma_first&&this.allow_wrap_or_preserved_newline(t)},T.prototype.handle_operator=function(t){var e="*"===t.text&&(f(this._flags.last_token,["function","yield"])||l(this._flags.last_token.type,[p.START_BLOCK,p.COMMA,p.END_BLOCK,p.SEMICOLON])),i=l(t.text,["-","+"])&&(l(this._flags.last_token.type,[p.START_BLOCK,p.START_EXPR,p.EQUALS,p.OPERATOR])||l(this._flags.last_token.text,r)||","===this._flags.last_token.text);if(this.start_of_statement(t)||this.handle_whitespace_and_comments(t,!e),"*"===t.text&&this._flags.last_token.type===p.DOT)this.print_token(t);else if("::"===t.text)this.print_token(t);else if(l(t.text,["-","+"])&&this.start_of_object_property())this.print_token(t);else{if(this._flags.last_token.type===p.OPERATOR&&l(this._options.operator_position,b)&&this.allow_wrap_or_preserved_newline(t),":"===t.text&&this._flags.in_case)return this.print_token(t),this._flags.in_case=!1,this._flags.case_body=!0,void(this._tokens.peek().type!==p.START_BLOCK?(this.indent(),this.print_newline(),this._flags.case_block=!1):(this._flags.case_block=!0,this._output.space_before_token=!0));var n=!0,u=!0,_=!1;if(":"===t.text?0===this._flags.ternary_depth?n=!1:(--this._flags.ternary_depth,_=!0):"?"===t.text&&(this._flags.ternary_depth+=1),!i&&!e&&this._options.preserve_newlines&&l(t.text,h)){var s=":"===t.text,a=s&&_,o=s&&!_;switch(this._options.operator_position){case d.before_newline:return this._output.space_before_token=!o,this.print_token(t),s&&!a||this.allow_wrap_or_preserved_newline(t),void(this._output.space_before_token=!0);case d.after_newline:return this._output.space_before_token=!0,!s||a?this._tokens.peek().newlines?this.print_newline(!1,!0):this.allow_wrap_or_preserved_newline(t):this._output.space_before_token=!1,this.print_token(t),void(this._output.space_before_token=!0);case d.preserve_newline:return o||this.allow_wrap_or_preserved_newline(t),n=!(this._output.just_added_newline()||o),this._output.space_before_token=n,this.print_token(t),void(this._output.space_before_token=!0)}}e?(this.allow_wrap_or_preserved_newline(t),n=!1,u=(_=this._tokens.peek())&&l(_.type,[p.WORD,p.RESERVED])):"..."===t.text?(this.allow_wrap_or_preserved_newline(t),n=this._flags.last_token.type===p.START_BLOCK,u=!1):(l(t.text,["--","++","!","~"])||i)&&(this._flags.last_token.type!==p.COMMA&&this._flags.last_token.type!==p.START_EXPR||this.allow_wrap_or_preserved_newline(t),u=n=!1,!t.newlines||"--"!==t.text&&"++"!==t.text&&"~"!==t.text||((e=f(this._flags.last_token,c)&&t.newlines)&&(this._previous_flags.if_block||this._previous_flags.else_block)&&this.restore_mode(),this.print_newline(e,!0)),";"===this._flags.last_token.text&&O(this._flags.mode)&&(n=!0),this._flags.last_token.type===p.RESERVED?n=!0:this._flags.last_token.type===p.END_EXPR?n=!("]"===this._flags.last_token.text&&("--"===t.text||"++"===t.text)):this._flags.last_token.type===p.OPERATOR&&(n=l(t.text,["--","-","++","+"])&&l(this._flags.last_token.text,["--","-","++","+"]),l(t.text,["+","-"])&&l(this._flags.last_token.text,["--","++"])&&(u=!0)),(this._flags.mode!==g||this._flags.inline_frame)&&this._flags.mode!==k||"{"!==this._flags.last_token.text&&";"!==this._flags.last_token.text||this.print_newline()),this._output.space_before_token=this._output.space_before_token||n,this.print_token(t),this._output.space_before_token=u}},T.prototype.handle_block_comment=function(t,e){return this._output.raw?(this._output.add_raw_token(t),void(t.directives&&"end"===t.directives.preserve&&(this._output.raw=this._options.test_output_raw))):t.directives?(this.print_newline(!1,e),this.print_token(t),"start"===t.directives.preserve&&(this._output.raw=!0),void this.print_newline(!1,!0)):void(o.newline.test(t.text)||t.newlines?this.print_block_commment(t,e):(this._output.space_before_token=!0,this.print_token(t),this._output.space_before_token=!0))},T.prototype.print_block_commment=function(t,e){var i,n,u,_=function(t){for(var e=[],i=(t=t.replace(o.allLineBreaks,"\n")).indexOf("\n");-1!==i;)e.push(t.substring(0,i)),i=(t=t.substring(i+1)).indexOf("\n");return t.length&&e.push(t),e}(t.text),s=t.whitespace_before,a=s.length;if(this.print_newline(!1,e),this.print_token_line_indentation(t),this._output.add_token(_[0]),this.print_newline(!1,e),1<_.length){for(n=function(t,e){for(var i=0;ithis.__parent.wrap_line_length&&this.__wrap_point_character_count>this.__parent.next_line.__character_count},u.prototype._allow_wrap=function(){var t;return!!this._should_wrap()&&(this.__parent.add_new_line(),(t=this.__parent.current_line).set_indent(this.__wrap_point_indent_count,this.__wrap_point_alignment_count),t.__items=this.__items.slice(this.__wrap_point_index),this.__items=this.__items.slice(0,this.__wrap_point_index),t.__character_count+=this.__character_count-this.__wrap_point_character_count,this.__character_count=this.__wrap_point_character_count," "===t.__items[0]&&(t.__items.splice(0,1),--t.__character_count),!0)},u.prototype.is_empty=function(){return 0===this.__items.length},u.prototype.last=function(){return this.is_empty()?null:this.__items[this.__items.length-1]},u.prototype.push=function(t){this.__items.push(t);var e=t.lastIndexOf("\n");-1!==e?this.__character_count=t.length-e:this.__character_count+=t.length},u.prototype.pop=function(){var t=null;return this.is_empty()||(t=this.__items.pop(),this.__character_count-=t.length),t},u.prototype._remove_indent=function(){0=this.__cache.length;)this.__add_column()},i.prototype.__add_column=function(){var t,e=this.__cache.length,i="";this.__indent_size&&e>=this.__indent_size&&(e-=(t=Math.floor(e/this.__indent_size))*this.__indent_size,i=new Array(t+1).join(this.__indent_string)),e&&(i+=new Array(e+1).join(" ")),this.__cache.push(i)},e.prototype.__add_outputline=function(){this.previous_line=this.current_line,this.current_line=this.next_line.clone_empty(),this.__lines.push(this.current_line)},e.prototype.get_line_number=function(){return this.__lines.length},e.prototype.get_indent_string=function(t,e){return this.__indent_cache.get_indent_string(t,e)},e.prototype.get_indent_size=function(t,e){return this.__indent_cache.get_indent_size(t,e)},e.prototype.is_empty=function(){return!this.previous_line&&this.current_line.is_empty()},e.prototype.add_new_line=function(t){return!(this.is_empty()||!t&&this.just_added_newline())&&(this.raw||this.__add_outputline(),!0)},e.prototype.get_code=function(t){this.trim(!0);var e=this.current_line.pop(),e=(e&&("\n"===e[e.length-1]&&(e=e.replace(/\n+$/g,"")),this.current_line.push(e)),this._end_with_newline&&this.__add_outputline(),this.__lines.join("\n"));return e="\n"!==t?e.replace(/[\n]/g,t):e},e.prototype.set_wrap_point=function(){this.current_line._set_wrap_point()},e.prototype.set_indent=function(t,e){return this.next_line.set_indent(t=t||0,e=e||0),1/),include:t.starting_with(/#include/).until_after(r.lineBreak),shebang:t.starting_with(/#!/).until_after(r.lineBreak),xml:t.matching(/[\s\S]*?<(\/?)([-a-zA-Z:0-9_.]+|{[^}]+?}|!\[CDATA\[[^\]]*?\]\]|)(\s*{[^}]+?}|\s+[-a-zA-Z:0-9_.]+|\s+[-a-zA-Z:0-9_.]+\s*=\s*('[^']*'|"[^"]*"|{([^{}]|{[^}]+?})+?}))*\s*(\/?)\s*>/),single_quote:e.until(/['\\\n\r\u2028\u2029]/),double_quote:e.until(/["\\\n\r\u2028\u2029]/),template_text:e.until(/[`\\$]/),template_expression:e.until(/[`}\\]/)}}var l,f={START_EXPR:"TK_START_EXPR",END_EXPR:"TK_END_EXPR",START_BLOCK:"TK_START_BLOCK",END_BLOCK:"TK_END_BLOCK",WORD:"TK_WORD",RESERVED:"TK_RESERVED",SEMICOLON:"TK_SEMICOLON",STRING:"TK_STRING",EQUALS:"TK_EQUALS",OPERATOR:"TK_OPERATOR",COMMA:"TK_COMMA",BLOCK_COMMENT:"TK_BLOCK_COMMENT",COMMENT:"TK_COMMENT",DOT:"TK_DOT",UNKNOWN:"TK_UNKNOWN",START:u.START,RAW:u.RAW,EOF:u.EOF},c=new s(/\/\*/,/\*\//),d=/0[xX][0123456789abcdefABCDEF_]*n?|0[oO][01234567_]*n?|0[bB][01_]*n?|\d[\d_]*n|(?:\.\d[\d_]*|\d[\d_]*\.?[\d_]*)(?:[eE][+-]?[\d_]+)?/,b=/[0-9]/,g=/[^\d\.]/,i=">>> === !== &&= ??= ||= << && >= ** != == <= >> || ?? |> < / - + > : & % ? ^ | *".split(" "),u=">>>= ... >>= <<= === >>> !== **= &&= ??= ||= => ^= :: /= << <= == && -= >= >> != -- += ** || ?? ++ %= &= *= |= |> = ! ? > < : / ^ - + * & % ~ |",k=(u=(u="\\?\\.(?!\\d) "+(u=u.replace(/[-[\]{}()*+?.,\\^$|#]/g,"\\$&"))).replace(/ /g,"|"),new RegExp(u)),s="continue,try,throw,return,var,let,const,if,switch,case,default,for,while,break,function,import,export".split(","),u=s.concat(["do","in","of","else","get","set","new","catch","finally","typeof","yield","async","await","from","as","class","extends"]),m=new RegExp("^(?:"+u.join("|")+")$");(p.prototype=new n)._is_comment=function(t){return t.type===f.COMMENT||t.type===f.BLOCK_COMMENT||t.type===f.UNKNOWN},p.prototype._is_opening=function(t){return t.type===f.START_BLOCK||t.type===f.START_EXPR},p.prototype._is_closing=function(t,e){return(t.type===f.END_BLOCK||t.type===f.END_EXPR)&&e&&("]"===t.text&&"["===e.text||")"===t.text&&"("===e.text||"}"===t.text&&"{"===e.text)},p.prototype._reset=function(){l=!1},p.prototype._get_next_token=function(t,e){this._readWhitespace();var i=this._input.peek();return null===i?this._create_token(f.EOF,""):this._read_non_javascript(i)||this._read_string(i)||this._read_pair(i,this._input.peek(1))||this._read_word(t)||this._read_singles(i)||this._read_comment(i)||this._read_regexp(i,t)||this._read_xml(i,t)||this._read_punctuation()||this._create_token(f.UNKNOWN,this._input.next())},p.prototype._read_word=function(t){var e=this.__patterns.identifier.read();return""!==e?(e=e.replace(r.allLineBreaks,"\n"),t.type!==f.DOT&&(t.type!==f.RESERVED||"set"!==t.text&&"get"!==t.text)&&m.test(e)?"in"!==e&&"of"!==e||t.type!==f.WORD&&t.type!==f.STRING?this._create_token(f.RESERVED,e):this._create_token(f.OPERATOR,e):this._create_token(f.WORD,e)):""!==(e=this.__patterns.number.read())?this._create_token(f.WORD,e):void 0},p.prototype._read_singles=function(t){var e=null;return"("===t||"["===t?e=this._create_token(f.START_EXPR,t):")"===t||"]"===t?e=this._create_token(f.END_EXPR,t):"{"===t?e=this._create_token(f.START_BLOCK,t):"}"===t?e=this._create_token(f.END_BLOCK,t):";"===t?e=this._create_token(f.SEMICOLON,t):"."===t&&g.test(this._input.peek(1))?e=this._create_token(f.DOT,t):","===t&&(e=this._create_token(f.COMMA,t)),e&&this._input.next(),e},p.prototype._read_pair=function(t,e){var i=null;return(i="#"===t&&"{"===e?this._create_token(f.START_BLOCK,t+e):i)&&(this._input.next(),this._input.next()),i},p.prototype._read_punctuation=function(){var t=this.__patterns.punct.read();if(""!==t)return"="===t?this._create_token(f.EQUALS,t):"?."===t?this._create_token(f.DOT,t):this._create_token(f.OPERATOR,t)},p.prototype._read_non_javascript=function(t){var e="";if("#"===t){if(this._is_first_token()&&(e=this.__patterns.shebang.read()))return this._create_token(f.UNKNOWN,e.trim()+"\n");if(e=this.__patterns.include.read())return this._create_token(f.UNKNOWN,e.trim()+"\n");t=this._input.next();var i="#";if(this._input.hasNext()&&this._input.testChar(b)){for(;i+=t=this._input.next(),this._input.hasNext()&&"#"!==t&&"="!==t;);return"#"!==t&&("["===this._input.peek()&&"]"===this._input.peek(1)?(i+="[]",this._input.next(),this._input.next()):"{"===this._input.peek()&&"}"===this._input.peek(1)&&(i+="{}",this._input.next(),this._input.next())),this._create_token(f.WORD,i)}this._input.back()}else if("<"===t&&this._is_first_token()){if(e=this.__patterns.html_comment_start.read()){for(;this._input.hasNext()&&!this._input.testChar(r.newline);)e+=this._input.next();return l=!0,this._create_token(f.COMMENT,e)}}else if(l&&"-"===t&&(e=this.__patterns.html_comment_end.read()))return l=!1,this._create_token(f.COMMENT,e);return null},p.prototype._read_comment=function(t){var e,i=null;return"/"===t&&(t="","*"===this._input.peek(1)?(t=this.__patterns.block_comment.read(),(e=c.get_directives(t))&&"start"===e.ignore&&(t+=c.readIgnored(this._input)),t=t.replace(r.allLineBreaks,"\n"),(i=this._create_token(f.BLOCK_COMMENT,t)).directives=e):"/"===this._input.peek(1)&&(t=this.__patterns.comment.read(),i=this._create_token(f.COMMENT,t))),i},p.prototype._read_string=function(t){var e;return"`"===t||"'"===t||'"'===t?(e=this._input.next(),this.has_char_escapes=!1,e+="`"===t?this._read_string_recursive("`",!0,"${"):this._read_string_recursive(t),this.has_char_escapes&&this._options.unescape_strings&&(e=function(t){var e="",i=0,n=new _(t),u=null;for(;n.hasNext();)if((u=n.match(/([\s]|[^\\]|\\\\)+/g))&&(e+=u[0]),"\\"===n.peek()){if(n.next(),"x"===n.peek())u=n.match(/x([0-9A-Fa-f]{2})/g);else{if("u"!==n.peek()){e+="\\",n.hasNext()&&(e+=n.next());continue}u=(u=n.match(/u([0-9A-Fa-f]{4})/g))||n.match(/u\{([0-9A-Fa-f]+)\}/g)}if(!u)return t;if(126<(i=parseInt(u[1],16))&&i<=255&&0===u[0].indexOf("x"))return t;e+=0<=i&&i<32||1114111=t.length&&this.__input.substring(e-t.length,e).toLowerCase()===t},t.exports.InputScanner=e},function(t,e,i){function n(t,e){this._input=new u(t),this._options=e||{},this.__tokens=null,this._patterns={},this._patterns.whitespace=new a(this._input)}var u=i(8).InputScanner,_=i(3).Token,s=i(10).TokenStream,a=i(11).WhitespacePattern,o={START:"TK_START",RAW:"TK_RAW",EOF:"TK_EOF"};n.prototype.tokenize=function(){this._input.restart(),this.__tokens=new s,this._reset();for(var t,e=new _(o.START,""),i=null,n=[],u=new s;e.type!==o.EOF;){for(t=this._get_next_token(e,i);this._is_comment(t);)u.add(t),t=this._get_next_token(e,i);u.isEmpty()||(t.comments_before=u,u=new s),t.parent=i,this._is_opening(t)?(n.push(i),i=t):i&&this._is_closing(t,i)&&((t.opened=i).closed=t,i=n.pop(),t.parent=i),(t.previous=e).next=t,this.__tokens.add(t),e=t}return this.__tokens},n.prototype._is_first_token=function(){return this.__tokens.isEmpty()},n.prototype._reset=function(){},n.prototype._get_next_token=function(t,e){this._readWhitespace();var i=this._input.read(/.+/g);return i?this._create_token(o.RAW,i):this._create_token(o.EOF,"")},n.prototype._is_comment=function(t){return!1},n.prototype._is_opening=function(t){return!1},n.prototype._is_closing=function(t,e){return!1},n.prototype._create_token=function(t,e){return new _(t,e,this._patterns.whitespace.newline_count,this._patterns.whitespace.whitespace_before_token)},n.prototype._readWhitespace=function(){return this._patterns.whitespace.read()},t.exports.Tokenizer=n,t.exports.TOKEN=o},function(t){function e(t){this.__tokens=[],this.__tokens_length=this.__tokens.length,this.__position=0,this.__parent_token=t}e.prototype.restart=function(){this.__position=0},e.prototype.isEmpty=function(){return 0===this.__tokens_length},e.prototype.hasNext=function(){return this.__position/),erb:e.starting_with(/<%[^%]/).until_after(/[^%]%>/),django:e.starting_with(/{%/).until_after(/%}/),django_value:e.starting_with(/{{/).until_after(/}}/),django_comment:e.starting_with(/{#/).until_after(/#}/),smarty:e.starting_with(/{(?=[^}{\s\n])/).until_after(/[^\s\n]}/),smarty_comment:e.starting_with(/{\*/).until_after(/\*}/),smarty_literal:e.starting_with(/{literal}/).until_after(/{\/literal}/)}}(_.prototype=new n)._create=function(){return new _(this._input,this)},_.prototype._update=function(){this.__set_templated_pattern()},_.prototype.disable=function(t){var e=this._create();return e._disabled[t]=!0,e._update(),e},_.prototype.read_options=function(t){var e,i=this._create();for(e in u)i._disabled[e]=-1===t.templating.indexOf(e);return i._update(),i},_.prototype.exclude=function(t){var e=this._create();return e._excluded[t]=!0,e._update(),e},_.prototype.read=function(){for(var t="",t=this._match_pattern?this._input.read(this._starting_pattern):this._input.read(this._starting_pattern,this.__template_pattern),e=this._read_template();e;)this._match_pattern?e+=this._input.read(this._match_pattern):e+=this._input.readUntil(this.__template_pattern),t+=e,e=this._read_template();return this._until_after&&(t+=this._input.readUntilAfter(this._until_pattern)),t},_.prototype.__set_templated_pattern=function(){var t=[];this._disabled.php||t.push(this.__patterns.php._starting_pattern.source),this._disabled.handlebars||t.push(this.__patterns.handlebars._starting_pattern.source),this._disabled.erb||t.push(this.__patterns.erb._starting_pattern.source),this._disabled.django||(t.push(this.__patterns.django._starting_pattern.source),t.push(this.__patterns.django_value._starting_pattern.source),t.push(this.__patterns.django_comment._starting_pattern.source)),this._disabled.smarty||t.push(this.__patterns.smarty._starting_pattern.source),this._until_pattern&&t.push(this._until_pattern.source),this.__template_pattern=this._input.get_regexp("(?:"+t.join("|")+")")},_.prototype._read_template=function(){var t,e="",i=this._input.peek();return"<"===i?(t=this._input.peek(1),this._disabled.php||this._excluded.php||"?"!==t||(e=e||this.__patterns.php.read()),this._disabled.erb||this._excluded.erb||"%"!==t||(e=e||this.__patterns.erb.read())):"{"===i&&(this._disabled.handlebars||this._excluded.handlebars||(e=(e=(e=e||this.__patterns.handlebars_comment.read())||this.__patterns.handlebars_unescaped.read())||this.__patterns.handlebars.read()),this._disabled.django||(this._excluded.django||this._excluded.handlebars||(e=e||this.__patterns.django_value.read()),this._excluded.django||(e=(e=e||this.__patterns.django_comment.read())||this.__patterns.django.read())),this._disabled.smarty||this._disabled.django&&this._disabled.handlebars&&(e=(e=(e=e||this.__patterns.smarty_comment.read())||this.__patterns.smarty_literal.read())||this.__patterns.smarty.read())),e},t.exports.TemplatablePattern=_}],u={};var t=function t(e){var i=u[e];if(void 0!==i)return i.exports;i=u[e]={exports:{}};return n[e](i,i.exports,t),i.exports}(0);e=t}();var e,t=e;"function"==typeof define&&define.amd?define([],function(){return{js_beautify:t}}):"undefined"!=typeof exports?exports.js_beautify=t:"undefined"!=typeof window?window.js_beautify=t:"undefined"!=typeof global&&(global.js_beautify=t)}(); diff --git a/godel/js/compiler.js b/godel/js/compiler.js new file mode 100644 index 0000000..65ebbcd --- /dev/null +++ b/godel/js/compiler.js @@ -0,0 +1,163 @@ +class StringBuilder { + constructor() { + this.stringPieces = []; + } + add(s) { + this.stringPieces.push(s); + } + build() { + return this.stringPieces.join(""); + } +} + +const compileGoto = (gotoNode, stringBuilder) => { + stringBuilder.add(`this.followGoto("${gotoNode.label}");\nreturn;\n`); +}; + +const compileConditional = (conditionalNode, stringBuilder) => { + const { variable, goto: gotoNode } = conditionalNode; + + stringBuilder.add(`if (this.get("${variable}") != 0) {\n`); + compileGoto(gotoNode, stringBuilder); + stringBuilder.add(`}\n`); +}; + +const compileAssignment = (assignmentNode, stringBuilder) => { + const { variable, expr } = assignmentNode; + if (expr.opr) { + if (expr.opr == "+") stringBuilder.add(`this.addOne("${variable}");\n`); + else if (expr.opr == "-") + stringBuilder.add(`this.subtractOne("${variable}");\n`); + } else { + stringBuilder.add("// noop \n"); + } +}; + +const compileInstruction = (instruction, stringBuilder) => { + if (instruction.goto) { + compileGoto(instruction.goto, stringBuilder); + return; // ignore unreachable addition to instructionPointer + } + + if (instruction.conditional) { + compileConditional(instruction.conditional, stringBuilder); + } else if (instruction.assignment) { + compileAssignment(instruction.assignment, stringBuilder); + } + + stringBuilder.add("this.instructionPointer++;\n"); +}; + +const compile = (ast) => { + const stringBuilder = new StringBuilder(); + stringBuilder.add(` + class Program { + constructor() { + this.variables = new Map(); // variable -> natural number val + this.labelInstructions = new Map(); // labels to instruction indices + this.instructions = new Map(); // instruction indices to procedures + + this.instructions.set(0, () => this.main()); + this.instructionPointer = 0; + this.variables.set("Y", 0); + + // -- program-specific state init -- + this.finalInstruction = ${ + ast.instructions.length + 1 + }; // instruction of the implied "exit" label + this.labelInstructions.set("E", this.finalInstruction); // "E" is the exit label + } + + get(variable) { + if (!this.variables.has(variable)) { + this.variables.set(variable, 0); + } + return this.variables.get(variable); + } + + addOne(variable) { + const val = this.get(variable); + this.variables.set(variable, val + 1); + } + + subtractOne(variable) { + const val = this.get(variable); + this.variables.set(variable, val - 1); + } + + followGoto(label) { + this.instructionPointer = this.labelInstructions.get(label); + } + + step() { + if (!this.isCompleted()) { + const procedure = this.instructions.get(this.instructionPointer); + procedure(); + + } + return this.instructionPointer; + } + + isCompleted() { + return this.instructionPointer == this.finalInstruction; + } + + getResult() { + return this.variables.get("Y"); + } + + run(maxIter=50000) { + let iter = 0; + while (!this.isCompleted() && (++iter) < maxIter) this.step(); + if (iter < maxIter) { + return this.getResult(); + } + throw new Error("Iterations went over maxIter=(" + maxIter + "). To resolve, please ask Turing how we can tell if a program will halt during compilation."); + } + + main() { +`); + + stringBuilder.add("// -- build label -> instruction map --\n"); + for (let i = 0; i < ast.instructions.length; i++) { + const line = ast.instructions[i]; + const instructionIdx = i + 1; + if (line.label) { + stringBuilder.add( + `this.instructions.set(${instructionIdx}, () => this.${line.label}());\n`, + ); + stringBuilder.add( + `this.labelInstructions.set("${line.label}", ${instructionIdx});\n`, + ); + } + } + + stringBuilder.add("// -- compiled instructions --\n"); + for (let i = 0; i < ast.instructions.length; i++) { + let instruction = ast.instructions[i]; + const instructionIdx = i + 1; + if (instruction.label) { + stringBuilder.add( + ` this.followGoto("${instruction.label}");\n}\n\n${instruction.label}() {\n`, + ); + stringBuilder.add(`this.instructionPointer = ${instructionIdx};\n`); + instruction = instruction.instruction; + } + + compileInstruction(instruction, stringBuilder); + } + + stringBuilder.add(` }\n}\n`); + stringBuilder.add("// -- \n"); + stringBuilder.add("const program = new Program();\n\n"); + stringBuilder.add("// set the initial Snapshot here\n"); + stringBuilder.add('// program.variables.set("X1", 2);\n\n'); + stringBuilder.add( + "program.run(50_000); // 50_000 is the max iterations before throwing an exception\n", + ); + + return js_beautify(stringBuilder.build(), { + indent_size: 2, + wrap_line_length: 120, + }); +}; diff --git a/godel/js/main.js b/godel/js/main.js index 000ce7a..bd36ef9 100644 --- a/godel/js/main.js +++ b/godel/js/main.js @@ -1,5 +1,121 @@ -const MESSAGES = {}; +const MESSAGES = { + COMPILE: "COMPILE", + COMPILE_RESULT: "COMPILE_RESULT", + EVAL: "EVAL", + EVAL_STATUS: "EVAL_RESULT", +}; -// -- the "real" code +// -- the "real" code -- const state = new Observable(); + +const prepareSource = (text) => text.replaceAll(/\/\/.*/g, "").trim(); + +const main = () => { + let program; + + state.subscribe((msg) => { + if (msg.type == MESSAGES.COMPILE) { + const { value } = msg; + const source = prepareSource(value); + try { + const ast = parser.parse(source); + const program = compile(ast); + + state.notify({ + type: MESSAGES.COMPILE_RESULT, + value: program, + }); + } catch (e) { + state.notify({ + type: MESSAGES.COMPILE_RESULT, + error: e.toString(), + }); + } + } + if (msg.type == MESSAGES.EVAL) { + const source = compiledEditorEl.getValue(); + try { + const result = eval(source); + state.notify({ + type: MESSAGES.EVAL_RESULT, + value: result, + }); + } catch (e) { + state.notify({ + type: MESSAGES.EVAL_RESULT, + error: e.toString(), + }); + } + } + }); +}; +main(); + +// -- a bit of some hacky ui code -- + +const instructionsEl = document.getElementById("instructions"); +const instructionsEditorEl = CodeMirror.fromTextArea(instructionsEl, { + lineNumbers: true, +}); + +const compileButton = document.getElementById("compile"); +const evalButton = document.getElementById("eval"); +const evalStatusEl = document.getElementById("eval_status"); +const compileStatusEl = document.getElementById("compile_status"); +const compiledEl = document.getElementById("compiled"); +const compiledEditorEl = CodeMirror.fromTextArea(compiledEl, { + lineNumbers: true, +}); +state.subscribe((msg) => { + if (msg.type == MESSAGES.COMPILE_RESULT) { + evalStatusEl.classList.remove("error"); + evalStatusEl.classList.remove("success"); + evalStatusEl.innerHTML = ""; + + if (typeof msg.value !== "undefined") { + compiledEditorEl.setValue(msg.value); + + compileStatusEl.classList.add("success"); + compileStatusEl.classList.remove("error"); + compileStatusEl.innerHTML = `Successful compile at ${new Date().toLocaleString()}!`; + } else if (msg.error) { + compiledEditorEl.setValue(""); + + compileStatusEl.classList.remove("success"); + compileStatusEl.classList.add("error"); + compileStatusEl.innerHTML = msg.error; + } + } +}); +state.subscribe((msg) => { + if (msg.type == MESSAGES.EVAL_RESULT) { + if (typeof msg.value !== "undefined") { + evalStatusEl.classList.add("success"); + evalStatusEl.classList.remove("error"); + evalStatusEl.innerHTML = `Result: ${msg.value}`; + } else if (msg.error) { + evalStatusEl.classList.remove("success"); + evalStatusEl.classList.add("error"); + evalStatusEl.innerHTML = msg.error; + } + } +}); + +const urlParams = new URLSearchParams(window.location.search); +if (urlParams.get("instructions")) { + editorEl.setValue(atob(urlParams.get("instructions"))); +} + +compileButton.addEventListener("click", () => { + state.notify({ + type: MESSAGES.COMPILE, + value: instructionsEditorEl.getValue(), + }); +}); + +evalButton.addEventListener("click", () => { + state.notify({ + type: MESSAGES.EVAL, + }); +}); diff --git a/godel/parser.js b/godel/js/parser.js similarity index 67% rename from godel/parser.js rename to godel/js/parser.js index 5fba64e..c582a28 100644 --- a/godel/parser.js +++ b/godel/js/parser.js @@ -1,4 +1,4 @@ -module.exports = /* +parser = /* * Generated by PEG.js 0.10.0. * * http://pegjs.org/ @@ -141,72 +141,83 @@ module.exports = /* peg$startRuleFunctions = { Program: peg$parseProgram }, peg$startRuleFunction = peg$parseProgram, - peg$c0 = function(instructions) { - return { instructions: instructions }; + peg$c0 = /^[\n]/, + peg$c1 = peg$classExpectation(["\n"], false, false), + peg$c2 = function(lines) { + return { instructions: lines.filter((line) => typeof line !== "string" || line.trim() != "") }; }, - peg$c1 = function(instruction) { + peg$c3 = function(instruction) { return instruction; }, - peg$c2 = function(label, instruction) { + peg$c4 = function(label, instruction) { return { label, instruction }; }, - peg$c3 = "[", - peg$c4 = peg$literalExpectation("[", false), - peg$c5 = "]", - peg$c6 = peg$literalExpectation("]", false), - peg$c7 = function(label) { + peg$c5 = "[", + peg$c6 = peg$literalExpectation("[", false), + peg$c7 = "]", + peg$c8 = peg$literalExpectation("]", false), + peg$c9 = function(label) { return label; }, - peg$c8 = function(conditional) { return { conditional }; }, - peg$c9 = function(assignment) { return { assignment }; }, - peg$c10 = "IF", - peg$c11 = peg$literalExpectation("IF", false), - peg$c12 = "!=", - peg$c13 = peg$literalExpectation("!=", false), - peg$c14 = "0", - peg$c15 = peg$literalExpectation("0", false), - peg$c16 = "GOTO", - peg$c17 = peg$literalExpectation("GOTO", false), - peg$c18 = function(variable, label) { - return { variable, label }; + peg$c10 = function(conditional) { return { conditional }; }, + peg$c11 = function(assignment) { return { assignment }; }, + peg$c12 = function(goto) { return { goto }; }, + peg$c13 = function(label) { + return { label }; }, - peg$c19 = "<-", - peg$c20 = peg$literalExpectation("<-", false), - peg$c21 = function(variable, expr) { + peg$c14 = "IF", + peg$c15 = peg$literalExpectation("IF", false), + peg$c16 = "!=", + peg$c17 = peg$literalExpectation("!=", false), + peg$c18 = "0", + peg$c19 = peg$literalExpectation("0", false), + peg$c20 = function(variable, goto) { + return { variable, goto }; + }, + peg$c21 = "<-", + peg$c22 = peg$literalExpectation("<-", false), + peg$c23 = function(variable, expr) { if (expr.left != variable) { error("left hand variable must match right hand"); } return { variable, expr }; }, - peg$c22 = "1", - peg$c23 = peg$literalExpectation("1", false), - peg$c24 = function(left, opr) { + peg$c24 = "1", + peg$c25 = peg$literalExpectation("1", false), + peg$c26 = function(left, opr) { return { left, opr }; }, - peg$c25 = "Y", - peg$c26 = peg$literalExpectation("Y", false), - peg$c27 = function(symbol) { return symbol }, - peg$c28 = "X", - peg$c29 = peg$literalExpectation("X", false), - peg$c30 = "Z", - peg$c31 = peg$literalExpectation("Z", false), - peg$c32 = function(symbol, ind) { + peg$c27 = function(left) { + return { left }; + }, + peg$c28 = "Y", + peg$c29 = peg$literalExpectation("Y", false), + peg$c30 = function(symbol) { return symbol }, + peg$c31 = "X", + peg$c32 = peg$literalExpectation("X", false), + peg$c33 = "Z", + peg$c34 = peg$literalExpectation("Z", false), + peg$c35 = function(symbol, ind) { return symbol + ind; }, - peg$c33 = "+", - peg$c34 = peg$literalExpectation("+", false), - peg$c35 = "-", - peg$c36 = peg$literalExpectation("-", false), - peg$c37 = /^[A-E]/, - peg$c38 = peg$classExpectation([["A", "E"]], false, false), - peg$c39 = peg$otherExpectation("integer"), - peg$c40 = /^[0-9]/, - peg$c41 = peg$classExpectation([["0", "9"]], false, false), - peg$c42 = function() { return parseInt(text(), 10); }, - peg$c43 = peg$otherExpectation("whitespace"), - peg$c44 = /^[ \t\n\r]/, - peg$c45 = peg$classExpectation([" ", "\t", "\n", "\r"], false, false), - peg$c46 = function() { }, + peg$c36 = "GOTO", + peg$c37 = peg$literalExpectation("GOTO", false), + peg$c38 = "+", + peg$c39 = peg$literalExpectation("+", false), + peg$c40 = "-", + peg$c41 = peg$literalExpectation("-", false), + peg$c42 = /^[A-E]/, + peg$c43 = peg$classExpectation([["A", "E"]], false, false), + peg$c44 = "E", + peg$c45 = peg$literalExpectation("E", false), + peg$c46 = peg$otherExpectation("integer"), + peg$c47 = /^[0-9]/, + peg$c48 = peg$classExpectation([["0", "9"]], false, false), + peg$c49 = function() { return parseInt(text(), 10); }, + peg$c50 = peg$otherExpectation("whitespace"), + peg$c51 = /^[ \t]/, + peg$c52 = peg$classExpectation([" ", "\t"], false, false), + peg$c53 = function() { }, peg$currPos = 0, peg$savedPos = 0, @@ -350,13 +361,37 @@ module.exports = /* s0 = peg$currPos; s1 = []; s2 = peg$parseLine(); + if (s2 === peg$FAILED) { + s2 = peg$parse_(); + if (s2 === peg$FAILED) { + if (peg$c0.test(input.charAt(peg$currPos))) { + s2 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c1); } + } + } + } while (s2 !== peg$FAILED) { s1.push(s2); s2 = peg$parseLine(); + if (s2 === peg$FAILED) { + s2 = peg$parse_(); + if (s2 === peg$FAILED) { + if (peg$c0.test(input.charAt(peg$currPos))) { + s2 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c1); } + } + } + } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$c0(s1); + s1 = peg$c2(s1); } s0 = s1; @@ -364,19 +399,46 @@ module.exports = /* } function peg$parseLine() { - var s0, s1, s2; + var s0, s1, s2, s3, s4; s0 = peg$currPos; - s1 = peg$parseLabeledInstruction(); + s1 = peg$parse_(); if (s1 === peg$FAILED) { - s1 = peg$parseInstruction(); + s1 = null; } if (s1 !== peg$FAILED) { - s2 = peg$parse_(); + s2 = peg$parseLabeledInstruction(); + if (s2 === peg$FAILED) { + s2 = peg$parseInstruction(); + } if (s2 !== peg$FAILED) { - peg$savedPos = s0; - s1 = peg$c1(s1); - s0 = s1; + s3 = peg$parse_(); + if (s3 === peg$FAILED) { + s3 = null; + } + if (s3 !== peg$FAILED) { + if (peg$c0.test(input.charAt(peg$currPos))) { + s4 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s4 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c1); } + } + if (s4 === peg$FAILED) { + s4 = null; + } + if (s4 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c3(s2); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } } else { peg$currPos = s0; s0 = peg$FAILED; @@ -400,7 +462,7 @@ module.exports = /* s3 = peg$parseInstruction(); if (s3 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$c2(s1, s3); + s1 = peg$c4(s1, s3); s0 = s1; } else { peg$currPos = s0; @@ -423,11 +485,11 @@ module.exports = /* s0 = peg$currPos; if (input.charCodeAt(peg$currPos) === 91) { - s1 = peg$c3; + s1 = peg$c5; peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c4); } + if (peg$silentFails === 0) { peg$fail(peg$c6); } } if (s1 !== peg$FAILED) { s2 = peg$parse_(); @@ -443,15 +505,15 @@ module.exports = /* } if (s4 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 93) { - s5 = peg$c5; + s5 = peg$c7; peg$currPos++; } else { s5 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c6); } + if (peg$silentFails === 0) { peg$fail(peg$c8); } } if (s5 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$c7(s3); + s1 = peg$c9(s3); s0 = s1; } else { peg$currPos = s0; @@ -484,7 +546,7 @@ module.exports = /* s1 = peg$parseConditional(); if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$c8(s1); + s1 = peg$c10(s1); } s0 = s1; if (s0 === peg$FAILED) { @@ -492,24 +554,62 @@ module.exports = /* s1 = peg$parseAssignment(); if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$c9(s1); + s1 = peg$c11(s1); } s0 = s1; + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = peg$parseGoto(); + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c12(s1); + } + s0 = s1; + } + } + + return s0; + } + + function peg$parseGoto() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + s1 = peg$parseGOTO(); + if (s1 !== peg$FAILED) { + s2 = peg$parse_(); + if (s2 !== peg$FAILED) { + s3 = peg$parseLABEL_V(); + if (s3 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c13(s3); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; } return s0; } function peg$parseConditional() { - var s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11; + var s0, s1, s2, s3, s4, s5, s6, s7, s8, s9; s0 = peg$currPos; - if (input.substr(peg$currPos, 2) === peg$c10) { - s1 = peg$c10; + if (input.substr(peg$currPos, 2) === peg$c14) { + s1 = peg$c14; peg$currPos += 2; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c11); } + if (peg$silentFails === 0) { peg$fail(peg$c15); } } if (s1 !== peg$FAILED) { s2 = peg$parse_(); @@ -517,50 +617,38 @@ module.exports = /* s3 = peg$parseVAR(); if (s3 !== peg$FAILED) { s4 = peg$parse_(); + if (s4 === peg$FAILED) { + s4 = null; + } if (s4 !== peg$FAILED) { - if (input.substr(peg$currPos, 2) === peg$c12) { - s5 = peg$c12; + if (input.substr(peg$currPos, 2) === peg$c16) { + s5 = peg$c16; peg$currPos += 2; } else { s5 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c13); } + if (peg$silentFails === 0) { peg$fail(peg$c17); } } if (s5 !== peg$FAILED) { s6 = peg$parse_(); + if (s6 === peg$FAILED) { + s6 = null; + } if (s6 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 48) { - s7 = peg$c14; + s7 = peg$c18; peg$currPos++; } else { s7 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c15); } + if (peg$silentFails === 0) { peg$fail(peg$c19); } } if (s7 !== peg$FAILED) { s8 = peg$parse_(); if (s8 !== peg$FAILED) { - if (input.substr(peg$currPos, 4) === peg$c16) { - s9 = peg$c16; - peg$currPos += 4; - } else { - s9 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c17); } - } + s9 = peg$parseGoto(); if (s9 !== peg$FAILED) { - s10 = peg$parse_(); - if (s10 !== peg$FAILED) { - s11 = peg$parseLabel(); - if (s11 !== peg$FAILED) { - peg$savedPos = s0; - s1 = peg$c18(s3, s11); - s0 = s1; - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } + peg$savedPos = s0; + s1 = peg$c20(s3, s9); + s0 = s1; } else { peg$currPos = s0; s0 = peg$FAILED; @@ -609,12 +697,12 @@ module.exports = /* if (s1 !== peg$FAILED) { s2 = peg$parse_(); if (s2 !== peg$FAILED) { - if (input.substr(peg$currPos, 2) === peg$c19) { - s3 = peg$c19; + if (input.substr(peg$currPos, 2) === peg$c21) { + s3 = peg$c21; peg$currPos += 2; } else { s3 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c20); } + if (peg$silentFails === 0) { peg$fail(peg$c22); } } if (s3 !== peg$FAILED) { s4 = peg$parse_(); @@ -622,7 +710,7 @@ module.exports = /* s5 = peg$parseExpression(); if (s5 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$c21(s1, s5); + s1 = peg$c23(s1, s5); s0 = s1; } else { peg$currPos = s0; @@ -661,15 +749,15 @@ module.exports = /* s4 = peg$parse_(); if (s4 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 49) { - s5 = peg$c22; + s5 = peg$c24; peg$currPos++; } else { s5 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c23); } + if (peg$silentFails === 0) { peg$fail(peg$c25); } } if (s5 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$c24(s1, s3); + s1 = peg$c26(s1, s3); s0 = s1; } else { peg$currPos = s0; @@ -691,6 +779,15 @@ module.exports = /* peg$currPos = s0; s0 = peg$FAILED; } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = peg$parseVAR(); + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c27(s1); + } + s0 = s1; + } return s0; } @@ -700,33 +797,33 @@ module.exports = /* s0 = peg$currPos; if (input.charCodeAt(peg$currPos) === 89) { - s1 = peg$c25; + s1 = peg$c28; peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c26); } + if (peg$silentFails === 0) { peg$fail(peg$c29); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$c27(s1); + s1 = peg$c30(s1); } s0 = s1; if (s0 === peg$FAILED) { s0 = peg$currPos; if (input.charCodeAt(peg$currPos) === 88) { - s1 = peg$c28; + s1 = peg$c31; peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c29); } + if (peg$silentFails === 0) { peg$fail(peg$c32); } } if (s1 === peg$FAILED) { if (input.charCodeAt(peg$currPos) === 90) { - s1 = peg$c30; + s1 = peg$c33; peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c31); } + if (peg$silentFails === 0) { peg$fail(peg$c34); } } } if (s1 !== peg$FAILED) { @@ -742,7 +839,7 @@ module.exports = /* } if (s2 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$c32(s1, s2); + s1 = peg$c35(s1, s2); s0 = s1; } else { peg$currPos = s0; @@ -757,23 +854,37 @@ module.exports = /* return s0; } + function peg$parseGOTO() { + var s0; + + if (input.substr(peg$currPos, 4) === peg$c36) { + s0 = peg$c36; + peg$currPos += 4; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c37); } + } + + return s0; + } + function peg$parseOPERATION() { var s0; if (input.charCodeAt(peg$currPos) === 43) { - s0 = peg$c33; + s0 = peg$c38; peg$currPos++; } else { s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c34); } + if (peg$silentFails === 0) { peg$fail(peg$c39); } } if (s0 === peg$FAILED) { if (input.charCodeAt(peg$currPos) === 45) { - s0 = peg$c35; + s0 = peg$c40; peg$currPos++; } else { s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c36); } + if (peg$silentFails === 0) { peg$fail(peg$c41); } } } @@ -784,85 +895,99 @@ module.exports = /* var s0, s1, s2, s3; s0 = peg$currPos; - if (peg$c37.test(input.charAt(peg$currPos))) { - s1 = input.charAt(peg$currPos); - peg$currPos++; - } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c38); } - } + s1 = peg$parseEND_LABEL(); if (s1 !== peg$FAILED) { - s2 = []; - s3 = peg$parseInteger(); - if (s3 !== peg$FAILED) { - while (s3 !== peg$FAILED) { - s2.push(s3); - s3 = peg$parseInteger(); - } + peg$savedPos = s0; + s1 = peg$c30(s1); + } + s0 = s1; + if (s0 === peg$FAILED) { + s0 = peg$currPos; + if (peg$c42.test(input.charAt(peg$currPos))) { + s1 = input.charAt(peg$currPos); + peg$currPos++; } else { - s2 = peg$FAILED; + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c43); } } - if (s2 !== peg$FAILED) { - peg$savedPos = s0; - s1 = peg$c32(s1, s2); - s0 = s1; + if (s1 !== peg$FAILED) { + s2 = []; + s3 = peg$parseInteger(); + if (s3 !== peg$FAILED) { + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = peg$parseInteger(); + } + } else { + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c35(s1, s2); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } } else { peg$currPos = s0; s0 = peg$FAILED; } + } + + return s0; + } + + function peg$parseEND_LABEL() { + var s0; + + if (input.charCodeAt(peg$currPos) === 69) { + s0 = peg$c44; + peg$currPos++; } else { - peg$currPos = s0; s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c45); } } return s0; } function peg$parseInteger() { - var s0, s1, s2, s3; + var s0, s1, s2; peg$silentFails++; s0 = peg$currPos; - s1 = peg$parse_(); - if (s1 !== peg$FAILED) { - s2 = []; - if (peg$c40.test(input.charAt(peg$currPos))) { - s3 = input.charAt(peg$currPos); - peg$currPos++; - } else { - s3 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c41); } - } - if (s3 !== peg$FAILED) { - while (s3 !== peg$FAILED) { - s2.push(s3); - if (peg$c40.test(input.charAt(peg$currPos))) { - s3 = input.charAt(peg$currPos); - peg$currPos++; - } else { - s3 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c41); } - } + s1 = []; + if (peg$c47.test(input.charAt(peg$currPos))) { + s2 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c48); } + } + if (s2 !== peg$FAILED) { + while (s2 !== peg$FAILED) { + s1.push(s2); + if (peg$c47.test(input.charAt(peg$currPos))) { + s2 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c48); } } - } else { - s2 = peg$FAILED; - } - if (s2 !== peg$FAILED) { - peg$savedPos = s0; - s1 = peg$c42(); - s0 = s1; - } else { - peg$currPos = s0; - s0 = peg$FAILED; } } else { - peg$currPos = s0; - s0 = peg$FAILED; + s1 = peg$FAILED; } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c49(); + } + s0 = s1; peg$silentFails--; if (s0 === peg$FAILED) { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c39); } + if (peg$silentFails === 0) { peg$fail(peg$c46); } } return s0; @@ -874,32 +999,36 @@ module.exports = /* peg$silentFails++; s0 = peg$currPos; s1 = []; - if (peg$c44.test(input.charAt(peg$currPos))) { + if (peg$c51.test(input.charAt(peg$currPos))) { s2 = input.charAt(peg$currPos); peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c45); } + if (peg$silentFails === 0) { peg$fail(peg$c52); } } - while (s2 !== peg$FAILED) { - s1.push(s2); - if (peg$c44.test(input.charAt(peg$currPos))) { - s2 = input.charAt(peg$currPos); - peg$currPos++; - } else { - s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c45); } + if (s2 !== peg$FAILED) { + while (s2 !== peg$FAILED) { + s1.push(s2); + if (peg$c51.test(input.charAt(peg$currPos))) { + s2 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c52); } + } } + } else { + s1 = peg$FAILED; } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$c46(); + s1 = peg$c53(); } s0 = s1; peg$silentFails--; if (s0 === peg$FAILED) { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c43); } + if (peg$silentFails === 0) { peg$fail(peg$c50); } } return s0;