From ec2b924fdac0b609c2bda4e857113674965732af Mon Sep 17 00:00:00 2001 From: Elizabeth Hunt Date: Thu, 16 Nov 2023 14:56:56 -0700 Subject: godel init foo --- godel/index.html | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 godel/index.html (limited to 'godel/index.html') diff --git a/godel/index.html b/godel/index.html new file mode 100644 index 0000000..84cde8f --- /dev/null +++ b/godel/index.html @@ -0,0 +1,35 @@ + + + + L-Program Compiler + + + + +
+

L-Program Compiler

+

Developed for Kulyukin's CS5000

+
+
+ +
+ +
+
+ +
+
+
+ + + + + + -- cgit v1.2.3-70-g09d2 From 56bf4878236f5464ba19d27b4342fa2a3a99eac6 Mon Sep 17 00:00:00 2001 From: Lizzy Hunt Date: Thu, 16 Nov 2023 19:06:35 -0700 Subject: add compiler --- godel/css/styles.css | 11 + godel/grammar.peg | 27 +- 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 | 1060 ++++++++++++++++++++++++++++++++++++++ godel/parser.js | 931 --------------------------------- 8 files changed, 1414 insertions(+), 972 deletions(-) create mode 100644 godel/js-beautify/js-beautify.js create mode 100644 godel/js/compiler.js create mode 100644 godel/js/parser.js delete mode 100644 godel/parser.js (limited to 'godel/index.html') 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; } +END_LABEL = "E" + Integer "integer" - = _ [0-9]+ { return parseInt(text(), 10); } + = [0-9]+ { return parseInt(text(), 10); } -_ "whitespace" = [ \t\n\r]* { } +_ "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/js/parser.js b/godel/js/parser.js new file mode 100644 index 0000000..c582a28 --- /dev/null +++ b/godel/js/parser.js @@ -0,0 +1,1060 @@ +parser = /* + * Generated by PEG.js 0.10.0. + * + * http://pegjs.org/ + */ +(function() { + "use strict"; + + function peg$subclass(child, parent) { + function ctor() { this.constructor = child; } + ctor.prototype = parent.prototype; + child.prototype = new ctor(); + } + + function peg$SyntaxError(message, expected, found, location) { + this.message = message; + this.expected = expected; + this.found = found; + this.location = location; + this.name = "SyntaxError"; + + if (typeof Error.captureStackTrace === "function") { + Error.captureStackTrace(this, peg$SyntaxError); + } + } + + peg$subclass(peg$SyntaxError, Error); + + peg$SyntaxError.buildMessage = function(expected, found) { + var DESCRIBE_EXPECTATION_FNS = { + literal: function(expectation) { + return "\"" + literalEscape(expectation.text) + "\""; + }, + + "class": function(expectation) { + var escapedParts = "", + i; + + for (i = 0; i < expectation.parts.length; i++) { + escapedParts += expectation.parts[i] instanceof Array + ? classEscape(expectation.parts[i][0]) + "-" + classEscape(expectation.parts[i][1]) + : classEscape(expectation.parts[i]); + } + + return "[" + (expectation.inverted ? "^" : "") + escapedParts + "]"; + }, + + any: function(expectation) { + return "any character"; + }, + + end: function(expectation) { + return "end of input"; + }, + + other: function(expectation) { + return expectation.description; + } + }; + + function hex(ch) { + return ch.charCodeAt(0).toString(16).toUpperCase(); + } + + function literalEscape(s) { + return s + .replace(/\\/g, '\\\\') + .replace(/"/g, '\\"') + .replace(/\0/g, '\\0') + .replace(/\t/g, '\\t') + .replace(/\n/g, '\\n') + .replace(/\r/g, '\\r') + .replace(/[\x00-\x0F]/g, function(ch) { return '\\x0' + hex(ch); }) + .replace(/[\x10-\x1F\x7F-\x9F]/g, function(ch) { return '\\x' + hex(ch); }); + } + + function classEscape(s) { + return s + .replace(/\\/g, '\\\\') + .replace(/\]/g, '\\]') + .replace(/\^/g, '\\^') + .replace(/-/g, '\\-') + .replace(/\0/g, '\\0') + .replace(/\t/g, '\\t') + .replace(/\n/g, '\\n') + .replace(/\r/g, '\\r') + .replace(/[\x00-\x0F]/g, function(ch) { return '\\x0' + hex(ch); }) + .replace(/[\x10-\x1F\x7F-\x9F]/g, function(ch) { return '\\x' + hex(ch); }); + } + + function describeExpectation(expectation) { + return DESCRIBE_EXPECTATION_FNS[expectation.type](expectation); + } + + function describeExpected(expected) { + var descriptions = new Array(expected.length), + i, j; + + for (i = 0; i < expected.length; i++) { + descriptions[i] = describeExpectation(expected[i]); + } + + descriptions.sort(); + + if (descriptions.length > 0) { + for (i = 1, j = 1; i < descriptions.length; i++) { + if (descriptions[i - 1] !== descriptions[i]) { + descriptions[j] = descriptions[i]; + j++; + } + } + descriptions.length = j; + } + + switch (descriptions.length) { + case 1: + return descriptions[0]; + + case 2: + return descriptions[0] + " or " + descriptions[1]; + + default: + return descriptions.slice(0, -1).join(", ") + + ", or " + + descriptions[descriptions.length - 1]; + } + } + + function describeFound(found) { + return found ? "\"" + literalEscape(found) + "\"" : "end of input"; + } + + return "Expected " + describeExpected(expected) + " but " + describeFound(found) + " found."; + }; + + function peg$parse(input, options) { + options = options !== void 0 ? options : {}; + + var peg$FAILED = {}, + + peg$startRuleFunctions = { Program: peg$parseProgram }, + peg$startRuleFunction = peg$parseProgram, + + 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$c3 = function(instruction) { + return instruction; + }, + peg$c4 = function(label, instruction) { + return { label, instruction }; + }, + peg$c5 = "[", + peg$c6 = peg$literalExpectation("[", false), + peg$c7 = "]", + peg$c8 = peg$literalExpectation("]", false), + peg$c9 = function(label) { + return 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$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$c24 = "1", + peg$c25 = peg$literalExpectation("1", false), + peg$c26 = function(left, opr) { + return { left, opr }; + }, + 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$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, + peg$posDetailsCache = [{ line: 1, column: 1 }], + peg$maxFailPos = 0, + peg$maxFailExpected = [], + peg$silentFails = 0, + + peg$result; + + if ("startRule" in options) { + if (!(options.startRule in peg$startRuleFunctions)) { + throw new Error("Can't start parsing from rule \"" + options.startRule + "\"."); + } + + peg$startRuleFunction = peg$startRuleFunctions[options.startRule]; + } + + function text() { + return input.substring(peg$savedPos, peg$currPos); + } + + function location() { + return peg$computeLocation(peg$savedPos, peg$currPos); + } + + function expected(description, location) { + location = location !== void 0 ? location : peg$computeLocation(peg$savedPos, peg$currPos) + + throw peg$buildStructuredError( + [peg$otherExpectation(description)], + input.substring(peg$savedPos, peg$currPos), + location + ); + } + + function error(message, location) { + location = location !== void 0 ? location : peg$computeLocation(peg$savedPos, peg$currPos) + + throw peg$buildSimpleError(message, location); + } + + function peg$literalExpectation(text, ignoreCase) { + return { type: "literal", text: text, ignoreCase: ignoreCase }; + } + + function peg$classExpectation(parts, inverted, ignoreCase) { + return { type: "class", parts: parts, inverted: inverted, ignoreCase: ignoreCase }; + } + + function peg$anyExpectation() { + return { type: "any" }; + } + + function peg$endExpectation() { + return { type: "end" }; + } + + function peg$otherExpectation(description) { + return { type: "other", description: description }; + } + + function peg$computePosDetails(pos) { + var details = peg$posDetailsCache[pos], p; + + if (details) { + return details; + } else { + p = pos - 1; + while (!peg$posDetailsCache[p]) { + p--; + } + + details = peg$posDetailsCache[p]; + details = { + line: details.line, + column: details.column + }; + + while (p < pos) { + if (input.charCodeAt(p) === 10) { + details.line++; + details.column = 1; + } else { + details.column++; + } + + p++; + } + + peg$posDetailsCache[pos] = details; + return details; + } + } + + function peg$computeLocation(startPos, endPos) { + var startPosDetails = peg$computePosDetails(startPos), + endPosDetails = peg$computePosDetails(endPos); + + return { + start: { + offset: startPos, + line: startPosDetails.line, + column: startPosDetails.column + }, + end: { + offset: endPos, + line: endPosDetails.line, + column: endPosDetails.column + } + }; + } + + function peg$fail(expected) { + if (peg$currPos < peg$maxFailPos) { return; } + + if (peg$currPos > peg$maxFailPos) { + peg$maxFailPos = peg$currPos; + peg$maxFailExpected = []; + } + + peg$maxFailExpected.push(expected); + } + + function peg$buildSimpleError(message, location) { + return new peg$SyntaxError(message, null, null, location); + } + + function peg$buildStructuredError(expected, found, location) { + return new peg$SyntaxError( + peg$SyntaxError.buildMessage(expected, found), + expected, + found, + location + ); + } + + function peg$parseProgram() { + var s0, s1, s2; + + 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$c2(s1); + } + s0 = s1; + + return s0; + } + + function peg$parseLine() { + var s0, s1, s2, s3, s4; + + s0 = peg$currPos; + s1 = peg$parse_(); + if (s1 === peg$FAILED) { + s1 = null; + } + if (s1 !== peg$FAILED) { + s2 = peg$parseLabeledInstruction(); + if (s2 === peg$FAILED) { + s2 = peg$parseInstruction(); + } + if (s2 !== peg$FAILED) { + 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; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseLabeledInstruction() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + s1 = peg$parseLabel(); + if (s1 !== peg$FAILED) { + s2 = peg$parse_(); + if (s2 !== peg$FAILED) { + s3 = peg$parseInstruction(); + if (s3 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c4(s1, 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$parseLabel() { + var s0, s1, s2, s3, s4, s5; + + s0 = peg$currPos; + if (input.charCodeAt(peg$currPos) === 91) { + s1 = peg$c5; + peg$currPos++; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c6); } + } + if (s1 !== peg$FAILED) { + s2 = peg$parse_(); + if (s2 === peg$FAILED) { + s2 = null; + } + if (s2 !== peg$FAILED) { + s3 = peg$parseLABEL_V(); + if (s3 !== peg$FAILED) { + s4 = peg$parse_(); + if (s4 === peg$FAILED) { + s4 = null; + } + if (s4 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 93) { + s5 = peg$c7; + peg$currPos++; + } else { + s5 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c8); } + } + if (s5 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c9(s3); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } 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$parseInstruction() { + var s0, s1; + + s0 = peg$currPos; + s1 = peg$parseConditional(); + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c10(s1); + } + s0 = s1; + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = peg$parseAssignment(); + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + 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; + + s0 = peg$currPos; + 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$c15); } + } + if (s1 !== peg$FAILED) { + s2 = peg$parse_(); + if (s2 !== peg$FAILED) { + 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$c16) { + s5 = peg$c16; + peg$currPos += 2; + } else { + s5 = peg$FAILED; + 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$c18; + peg$currPos++; + } else { + s7 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c19); } + } + if (s7 !== peg$FAILED) { + s8 = peg$parse_(); + if (s8 !== peg$FAILED) { + s9 = peg$parseGoto(); + if (s9 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c20(s3, s9); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } 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$parseAssignment() { + var s0, s1, s2, s3, s4, s5; + + s0 = peg$currPos; + s1 = peg$parseVAR(); + if (s1 !== peg$FAILED) { + s2 = peg$parse_(); + if (s2 !== peg$FAILED) { + 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$c22); } + } + if (s3 !== peg$FAILED) { + s4 = peg$parse_(); + if (s4 !== peg$FAILED) { + s5 = peg$parseExpression(); + if (s5 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c23(s1, s5); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } 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$parseExpression() { + var s0, s1, s2, s3, s4, s5; + + s0 = peg$currPos; + s1 = peg$parseVAR(); + if (s1 !== peg$FAILED) { + s2 = peg$parse_(); + if (s2 !== peg$FAILED) { + s3 = peg$parseOPERATION(); + if (s3 !== peg$FAILED) { + s4 = peg$parse_(); + if (s4 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 49) { + s5 = peg$c24; + peg$currPos++; + } else { + s5 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c25); } + } + if (s5 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c26(s1, s3); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + 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; + } + + function peg$parseVAR() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + if (input.charCodeAt(peg$currPos) === 89) { + s1 = peg$c28; + peg$currPos++; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c29); } + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c30(s1); + } + s0 = s1; + if (s0 === peg$FAILED) { + s0 = peg$currPos; + if (input.charCodeAt(peg$currPos) === 88) { + s1 = peg$c31; + peg$currPos++; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c32); } + } + if (s1 === peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 90) { + s1 = peg$c33; + peg$currPos++; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c34); } + } + } + 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$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$c38; + peg$currPos++; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c39); } + } + if (s0 === peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 45) { + s0 = peg$c40; + peg$currPos++; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c41); } + } + } + + return s0; + } + + function peg$parseLABEL_V() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + s1 = peg$parseEND_LABEL(); + if (s1 !== peg$FAILED) { + 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 { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c43); } + } + 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 { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c45); } + } + + return s0; + } + + function peg$parseInteger() { + var s0, s1, s2; + + peg$silentFails++; + s0 = peg$currPos; + 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 { + 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$c46); } + } + + return s0; + } + + function peg$parse_() { + var s0, s1, s2; + + peg$silentFails++; + s0 = peg$currPos; + s1 = []; + 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); } + } + 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$c53(); + } + s0 = s1; + peg$silentFails--; + if (s0 === peg$FAILED) { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c50); } + } + + return s0; + } + + peg$result = peg$startRuleFunction(); + + if (peg$result !== peg$FAILED && peg$currPos === input.length) { + return peg$result; + } else { + if (peg$result !== peg$FAILED && peg$currPos < input.length) { + peg$fail(peg$endExpectation()); + } + + throw peg$buildStructuredError( + peg$maxFailExpected, + peg$maxFailPos < input.length ? input.charAt(peg$maxFailPos) : null, + peg$maxFailPos < input.length + ? peg$computeLocation(peg$maxFailPos, peg$maxFailPos + 1) + : peg$computeLocation(peg$maxFailPos, peg$maxFailPos) + ); + } + } + + return { + SyntaxError: peg$SyntaxError, + parse: peg$parse + }; +})(); diff --git a/godel/parser.js b/godel/parser.js deleted file mode 100644 index 5fba64e..0000000 --- a/godel/parser.js +++ /dev/null @@ -1,931 +0,0 @@ -module.exports = /* - * Generated by PEG.js 0.10.0. - * - * http://pegjs.org/ - */ -(function() { - "use strict"; - - function peg$subclass(child, parent) { - function ctor() { this.constructor = child; } - ctor.prototype = parent.prototype; - child.prototype = new ctor(); - } - - function peg$SyntaxError(message, expected, found, location) { - this.message = message; - this.expected = expected; - this.found = found; - this.location = location; - this.name = "SyntaxError"; - - if (typeof Error.captureStackTrace === "function") { - Error.captureStackTrace(this, peg$SyntaxError); - } - } - - peg$subclass(peg$SyntaxError, Error); - - peg$SyntaxError.buildMessage = function(expected, found) { - var DESCRIBE_EXPECTATION_FNS = { - literal: function(expectation) { - return "\"" + literalEscape(expectation.text) + "\""; - }, - - "class": function(expectation) { - var escapedParts = "", - i; - - for (i = 0; i < expectation.parts.length; i++) { - escapedParts += expectation.parts[i] instanceof Array - ? classEscape(expectation.parts[i][0]) + "-" + classEscape(expectation.parts[i][1]) - : classEscape(expectation.parts[i]); - } - - return "[" + (expectation.inverted ? "^" : "") + escapedParts + "]"; - }, - - any: function(expectation) { - return "any character"; - }, - - end: function(expectation) { - return "end of input"; - }, - - other: function(expectation) { - return expectation.description; - } - }; - - function hex(ch) { - return ch.charCodeAt(0).toString(16).toUpperCase(); - } - - function literalEscape(s) { - return s - .replace(/\\/g, '\\\\') - .replace(/"/g, '\\"') - .replace(/\0/g, '\\0') - .replace(/\t/g, '\\t') - .replace(/\n/g, '\\n') - .replace(/\r/g, '\\r') - .replace(/[\x00-\x0F]/g, function(ch) { return '\\x0' + hex(ch); }) - .replace(/[\x10-\x1F\x7F-\x9F]/g, function(ch) { return '\\x' + hex(ch); }); - } - - function classEscape(s) { - return s - .replace(/\\/g, '\\\\') - .replace(/\]/g, '\\]') - .replace(/\^/g, '\\^') - .replace(/-/g, '\\-') - .replace(/\0/g, '\\0') - .replace(/\t/g, '\\t') - .replace(/\n/g, '\\n') - .replace(/\r/g, '\\r') - .replace(/[\x00-\x0F]/g, function(ch) { return '\\x0' + hex(ch); }) - .replace(/[\x10-\x1F\x7F-\x9F]/g, function(ch) { return '\\x' + hex(ch); }); - } - - function describeExpectation(expectation) { - return DESCRIBE_EXPECTATION_FNS[expectation.type](expectation); - } - - function describeExpected(expected) { - var descriptions = new Array(expected.length), - i, j; - - for (i = 0; i < expected.length; i++) { - descriptions[i] = describeExpectation(expected[i]); - } - - descriptions.sort(); - - if (descriptions.length > 0) { - for (i = 1, j = 1; i < descriptions.length; i++) { - if (descriptions[i - 1] !== descriptions[i]) { - descriptions[j] = descriptions[i]; - j++; - } - } - descriptions.length = j; - } - - switch (descriptions.length) { - case 1: - return descriptions[0]; - - case 2: - return descriptions[0] + " or " + descriptions[1]; - - default: - return descriptions.slice(0, -1).join(", ") - + ", or " - + descriptions[descriptions.length - 1]; - } - } - - function describeFound(found) { - return found ? "\"" + literalEscape(found) + "\"" : "end of input"; - } - - return "Expected " + describeExpected(expected) + " but " + describeFound(found) + " found."; - }; - - function peg$parse(input, options) { - options = options !== void 0 ? options : {}; - - var peg$FAILED = {}, - - peg$startRuleFunctions = { Program: peg$parseProgram }, - peg$startRuleFunction = peg$parseProgram, - - peg$c0 = function(instructions) { - return { instructions: instructions }; - }, - peg$c1 = function(instruction) { - return instruction; - }, - peg$c2 = function(label, instruction) { - return { label, instruction }; - }, - peg$c3 = "[", - peg$c4 = peg$literalExpectation("[", false), - peg$c5 = "]", - peg$c6 = peg$literalExpectation("]", false), - peg$c7 = 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$c19 = "<-", - peg$c20 = peg$literalExpectation("<-", false), - peg$c21 = 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) { - 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) { - 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$currPos = 0, - peg$savedPos = 0, - peg$posDetailsCache = [{ line: 1, column: 1 }], - peg$maxFailPos = 0, - peg$maxFailExpected = [], - peg$silentFails = 0, - - peg$result; - - if ("startRule" in options) { - if (!(options.startRule in peg$startRuleFunctions)) { - throw new Error("Can't start parsing from rule \"" + options.startRule + "\"."); - } - - peg$startRuleFunction = peg$startRuleFunctions[options.startRule]; - } - - function text() { - return input.substring(peg$savedPos, peg$currPos); - } - - function location() { - return peg$computeLocation(peg$savedPos, peg$currPos); - } - - function expected(description, location) { - location = location !== void 0 ? location : peg$computeLocation(peg$savedPos, peg$currPos) - - throw peg$buildStructuredError( - [peg$otherExpectation(description)], - input.substring(peg$savedPos, peg$currPos), - location - ); - } - - function error(message, location) { - location = location !== void 0 ? location : peg$computeLocation(peg$savedPos, peg$currPos) - - throw peg$buildSimpleError(message, location); - } - - function peg$literalExpectation(text, ignoreCase) { - return { type: "literal", text: text, ignoreCase: ignoreCase }; - } - - function peg$classExpectation(parts, inverted, ignoreCase) { - return { type: "class", parts: parts, inverted: inverted, ignoreCase: ignoreCase }; - } - - function peg$anyExpectation() { - return { type: "any" }; - } - - function peg$endExpectation() { - return { type: "end" }; - } - - function peg$otherExpectation(description) { - return { type: "other", description: description }; - } - - function peg$computePosDetails(pos) { - var details = peg$posDetailsCache[pos], p; - - if (details) { - return details; - } else { - p = pos - 1; - while (!peg$posDetailsCache[p]) { - p--; - } - - details = peg$posDetailsCache[p]; - details = { - line: details.line, - column: details.column - }; - - while (p < pos) { - if (input.charCodeAt(p) === 10) { - details.line++; - details.column = 1; - } else { - details.column++; - } - - p++; - } - - peg$posDetailsCache[pos] = details; - return details; - } - } - - function peg$computeLocation(startPos, endPos) { - var startPosDetails = peg$computePosDetails(startPos), - endPosDetails = peg$computePosDetails(endPos); - - return { - start: { - offset: startPos, - line: startPosDetails.line, - column: startPosDetails.column - }, - end: { - offset: endPos, - line: endPosDetails.line, - column: endPosDetails.column - } - }; - } - - function peg$fail(expected) { - if (peg$currPos < peg$maxFailPos) { return; } - - if (peg$currPos > peg$maxFailPos) { - peg$maxFailPos = peg$currPos; - peg$maxFailExpected = []; - } - - peg$maxFailExpected.push(expected); - } - - function peg$buildSimpleError(message, location) { - return new peg$SyntaxError(message, null, null, location); - } - - function peg$buildStructuredError(expected, found, location) { - return new peg$SyntaxError( - peg$SyntaxError.buildMessage(expected, found), - expected, - found, - location - ); - } - - function peg$parseProgram() { - var s0, s1, s2; - - s0 = peg$currPos; - s1 = []; - s2 = peg$parseLine(); - while (s2 !== peg$FAILED) { - s1.push(s2); - s2 = peg$parseLine(); - } - if (s1 !== peg$FAILED) { - peg$savedPos = s0; - s1 = peg$c0(s1); - } - s0 = s1; - - return s0; - } - - function peg$parseLine() { - var s0, s1, s2; - - s0 = peg$currPos; - s1 = peg$parseLabeledInstruction(); - if (s1 === peg$FAILED) { - s1 = peg$parseInstruction(); - } - if (s1 !== peg$FAILED) { - s2 = peg$parse_(); - if (s2 !== peg$FAILED) { - peg$savedPos = s0; - s1 = peg$c1(s1); - s0 = s1; - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - - return s0; - } - - function peg$parseLabeledInstruction() { - var s0, s1, s2, s3; - - s0 = peg$currPos; - s1 = peg$parseLabel(); - if (s1 !== peg$FAILED) { - s2 = peg$parse_(); - if (s2 !== peg$FAILED) { - s3 = peg$parseInstruction(); - if (s3 !== peg$FAILED) { - peg$savedPos = s0; - s1 = peg$c2(s1, 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$parseLabel() { - var s0, s1, s2, s3, s4, s5; - - s0 = peg$currPos; - if (input.charCodeAt(peg$currPos) === 91) { - s1 = peg$c3; - peg$currPos++; - } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c4); } - } - if (s1 !== peg$FAILED) { - s2 = peg$parse_(); - if (s2 === peg$FAILED) { - s2 = null; - } - if (s2 !== peg$FAILED) { - s3 = peg$parseLABEL_V(); - if (s3 !== peg$FAILED) { - s4 = peg$parse_(); - if (s4 === peg$FAILED) { - s4 = null; - } - if (s4 !== peg$FAILED) { - if (input.charCodeAt(peg$currPos) === 93) { - s5 = peg$c5; - peg$currPos++; - } else { - s5 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c6); } - } - if (s5 !== peg$FAILED) { - peg$savedPos = s0; - s1 = peg$c7(s3); - s0 = s1; - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } 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$parseInstruction() { - var s0, s1; - - s0 = peg$currPos; - s1 = peg$parseConditional(); - if (s1 !== peg$FAILED) { - peg$savedPos = s0; - s1 = peg$c8(s1); - } - s0 = s1; - if (s0 === peg$FAILED) { - s0 = peg$currPos; - s1 = peg$parseAssignment(); - if (s1 !== peg$FAILED) { - peg$savedPos = s0; - s1 = peg$c9(s1); - } - s0 = s1; - } - - return s0; - } - - function peg$parseConditional() { - var s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11; - - s0 = peg$currPos; - if (input.substr(peg$currPos, 2) === peg$c10) { - s1 = peg$c10; - peg$currPos += 2; - } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c11); } - } - if (s1 !== peg$FAILED) { - s2 = peg$parse_(); - if (s2 !== peg$FAILED) { - s3 = peg$parseVAR(); - if (s3 !== peg$FAILED) { - s4 = peg$parse_(); - if (s4 !== peg$FAILED) { - if (input.substr(peg$currPos, 2) === peg$c12) { - s5 = peg$c12; - peg$currPos += 2; - } else { - s5 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c13); } - } - if (s5 !== peg$FAILED) { - s6 = peg$parse_(); - if (s6 !== peg$FAILED) { - if (input.charCodeAt(peg$currPos) === 48) { - s7 = peg$c14; - peg$currPos++; - } else { - s7 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c15); } - } - 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); } - } - 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; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } 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$parseAssignment() { - var s0, s1, s2, s3, s4, s5; - - s0 = peg$currPos; - s1 = peg$parseVAR(); - if (s1 !== peg$FAILED) { - s2 = peg$parse_(); - if (s2 !== peg$FAILED) { - if (input.substr(peg$currPos, 2) === peg$c19) { - s3 = peg$c19; - peg$currPos += 2; - } else { - s3 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c20); } - } - if (s3 !== peg$FAILED) { - s4 = peg$parse_(); - if (s4 !== peg$FAILED) { - s5 = peg$parseExpression(); - if (s5 !== peg$FAILED) { - peg$savedPos = s0; - s1 = peg$c21(s1, s5); - s0 = s1; - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } 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$parseExpression() { - var s0, s1, s2, s3, s4, s5; - - s0 = peg$currPos; - s1 = peg$parseVAR(); - if (s1 !== peg$FAILED) { - s2 = peg$parse_(); - if (s2 !== peg$FAILED) { - s3 = peg$parseOPERATION(); - if (s3 !== peg$FAILED) { - s4 = peg$parse_(); - if (s4 !== peg$FAILED) { - if (input.charCodeAt(peg$currPos) === 49) { - s5 = peg$c22; - peg$currPos++; - } else { - s5 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c23); } - } - if (s5 !== peg$FAILED) { - peg$savedPos = s0; - s1 = peg$c24(s1, s3); - s0 = s1; - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } 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$parseVAR() { - var s0, s1, s2, s3; - - s0 = peg$currPos; - if (input.charCodeAt(peg$currPos) === 89) { - s1 = peg$c25; - peg$currPos++; - } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c26); } - } - if (s1 !== peg$FAILED) { - peg$savedPos = s0; - s1 = peg$c27(s1); - } - s0 = s1; - if (s0 === peg$FAILED) { - s0 = peg$currPos; - if (input.charCodeAt(peg$currPos) === 88) { - s1 = peg$c28; - peg$currPos++; - } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c29); } - } - if (s1 === peg$FAILED) { - if (input.charCodeAt(peg$currPos) === 90) { - s1 = peg$c30; - peg$currPos++; - } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c31); } - } - } - 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$c32(s1, s2); - s0 = s1; - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } - - return s0; - } - - function peg$parseOPERATION() { - var s0; - - if (input.charCodeAt(peg$currPos) === 43) { - s0 = peg$c33; - peg$currPos++; - } else { - s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c34); } - } - if (s0 === peg$FAILED) { - if (input.charCodeAt(peg$currPos) === 45) { - s0 = peg$c35; - peg$currPos++; - } else { - s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c36); } - } - } - - return s0; - } - - function peg$parseLABEL_V() { - 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); } - } - 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$c32(s1, s2); - s0 = s1; - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - - return s0; - } - - function peg$parseInteger() { - var s0, s1, s2, s3; - - 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); } - } - } - } 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; - } - peg$silentFails--; - if (s0 === peg$FAILED) { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c39); } - } - - return s0; - } - - function peg$parse_() { - var s0, s1, s2; - - peg$silentFails++; - s0 = peg$currPos; - s1 = []; - 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); } - } - 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 (s1 !== peg$FAILED) { - peg$savedPos = s0; - s1 = peg$c46(); - } - s0 = s1; - peg$silentFails--; - if (s0 === peg$FAILED) { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c43); } - } - - return s0; - } - - peg$result = peg$startRuleFunction(); - - if (peg$result !== peg$FAILED && peg$currPos === input.length) { - return peg$result; - } else { - if (peg$result !== peg$FAILED && peg$currPos < input.length) { - peg$fail(peg$endExpectation()); - } - - throw peg$buildStructuredError( - peg$maxFailExpected, - peg$maxFailPos < input.length ? input.charAt(peg$maxFailPos) : null, - peg$maxFailPos < input.length - ? peg$computeLocation(peg$maxFailPos, peg$maxFailPos + 1) - : peg$computeLocation(peg$maxFailPos, peg$maxFailPos) - ); - } - } - - return { - SyntaxError: peg$SyntaxError, - parse: peg$parse - }; -})(); -- cgit v1.2.3-70-g09d2 From 7d897cb2b5f3292c403700dbac98f79f1052422b Mon Sep 17 00:00:00 2001 From: Elizabeth Hunt Date: Fri, 17 Nov 2023 10:04:55 -0700 Subject: add addition l-program --- godel/index.html | 116 +++++++++++++++++++++++++++++++++------------------ godel/js/compiler.js | 22 +++++----- 2 files changed, 88 insertions(+), 50 deletions(-) (limited to 'godel/index.html') diff --git a/godel/index.html b/godel/index.html index 055f13d..1769959 100644 --- a/godel/index.html +++ b/godel/index.html @@ -1,46 +1,82 @@ - + - - Liz's L-Program Compiler - - - - -
-

Liz's L-Program Compiler

-

Developed for Kulyukin's CS5000

-
-
-
-

L Source

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

Liz's L-Program Compiler

+

Developed for Kulyukin's CS5000

+
+
+
+

L Source

+ +
+
-
-

Compiled JS

- -
- -
+
+ +
+
+
+

Compiled JS

+ +
+ +
+
+
- - - - - - - - +
+ + + + + + + diff --git a/godel/js/compiler.js b/godel/js/compiler.js index 65ebbcd..e63f5b0 100644 --- a/godel/js/compiler.js +++ b/godel/js/compiler.js @@ -65,7 +65,8 @@ const compile = (ast) => { this.finalInstruction = ${ ast.instructions.length + 1 }; // instruction of the implied "exit" label - this.labelInstructions.set("E", this.finalInstruction); // "E" is the exit label + // "E" is the exit label + this.labelInstructions.set("E", this.finalInstruction); } get(variable) { @@ -106,13 +107,14 @@ const compile = (ast) => { return this.variables.get("Y"); } - run(maxIter=50000) { + run(maxIter=500_000) { 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."); + throw new Error("Too many iterations. To resolve, please ask" + + " Turing how we can find if a program will halt during compilation."); } main() { @@ -124,10 +126,10 @@ const compile = (ast) => { const instructionIdx = i + 1; if (line.label) { stringBuilder.add( - `this.instructions.set(${instructionIdx}, () => this.${line.label}());\n`, + `this.instructions.set(${instructionIdx}, () => this.${line.label}());\n` ); stringBuilder.add( - `this.labelInstructions.set("${line.label}", ${instructionIdx});\n`, + `this.labelInstructions.set("${line.label}", ${instructionIdx});\n` ); } } @@ -138,7 +140,7 @@ const compile = (ast) => { const instructionIdx = i + 1; if (instruction.label) { stringBuilder.add( - ` this.followGoto("${instruction.label}");\n}\n\n${instruction.label}() {\n`, + ` this.followGoto("${instruction.label}");\n}\n\n${instruction.label}() {\n` ); stringBuilder.add(`this.instructionPointer = ${instructionIdx};\n`); instruction = instruction.instruction; @@ -152,12 +154,12 @@ const compile = (ast) => { 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", - ); + stringBuilder.add("program.run();\n"); + stringBuilder.add("console.log(program.variables);\n"); + stringBuilder.add("program.getResult();\n"); return js_beautify(stringBuilder.build(), { indent_size: 2, - wrap_line_length: 120, + wrap_line_length: 100, }); }; -- cgit v1.2.3-70-g09d2 From a54a7ba7c95965268d7a2a3c64a6a6c599fdb9da Mon Sep 17 00:00:00 2001 From: Elizabeth Hunt Date: Fri, 17 Nov 2023 12:09:44 -0700 Subject: finish compiler! --- godel/css/styles.css | 11 ++++ godel/grammar.peg | 50 +++++++++++----- godel/index.html | 23 +++++-- godel/js/compiler.js | 47 ++++++++++----- godel/js/godelWorker.js | 27 +++++++++ godel/js/main.js | 64 ++++++++++++++++---- godel/js/parser.js | 156 +++++++++++++++++++++++------------------------- 7 files changed, 251 insertions(+), 127 deletions(-) create mode 100644 godel/js/godelWorker.js (limited to 'godel/index.html') diff --git a/godel/css/styles.css b/godel/css/styles.css index b9c5c10..799e183 100644 --- a/godel/css/styles.css +++ b/godel/css/styles.css @@ -69,3 +69,14 @@ hr { border-top: 2px solid black; border-bottom: none; } + +pre { + white-space: pre-wrap; + word-wrap: break-word; +} + +@media only screen and (max-width: 1000px) { + .source-container { + flex-direction: column; + } +} diff --git a/godel/grammar.peg b/godel/grammar.peg index 73ba08e..a66d5a5 100644 --- a/godel/grammar.peg +++ b/godel/grammar.peg @@ -1,9 +1,17 @@ -Program = lines: (Line / (_/[\n]))* { +Program = lines: (ProgramInstruction / (_/[\n]))* { return { instructions: lines.filter((line) => typeof line !== "string" || line.trim() != "") }; } -Line = _? instruction: (LabeledInstruction / Instruction) _? [\n]? { - return instruction; +ProgramInstruction = _? instruction: (LabeledInstruction / Instruction) _? [\n]? { + let x = 0; + let y = 0; + if (instruction.label) { + x = instruction.label.godel; + y = instruction.instruction.godel; + } else { + y = instruction.godel; + } + return { instruction, godel: ((2 ** x) * ((2 * y) + 1) - 1) }; } LabeledInstruction = label:Label _ instruction:Instruction { @@ -14,33 +22,41 @@ Label = "[" _? label:LABEL_V _? "]" { return label; } -Instruction = conditional: Conditional { return { conditional }; } - / assignment: Assignment { return { assignment }; } - / goto: Goto { return { goto }; } +Instruction = conditional: Conditional { return { conditional, godel: conditional.godel }; } + / assignment: Assignment { return { assignment, godel: assignment.godel }; } + / goto: Goto { return { goto, godel: goto.godel }; } Goto = GOTO _ label: LABEL_V { - return { label }; + return { label, godel: label.godel + 2 }; } Conditional = "IF" _ variable: VAR _? "!=" _? "0" _ goto: Goto { - return { variable, goto }; + const y = variable.godel - 1; + const x = goto.godel; + return { variable, goto, godel: ((2 ** x) * ((2 * y) + 1) - 1) }; } Assignment = variable: VAR _ "<-" _ expr: Expression { - if (expr.left != variable) { + if (expr.left.symbol != variable.symbol) { error("left hand variable must match right hand"); } - return { variable, expr }; + const x = expr.instructionNumber; + const y = variable.godel - 1; + return { variable, expr, godel: ((2 ** x) * ((2 * y) + 1) - 1) }; } Expression = left: VAR _ opr: OPERATION _ "1" { - return { left, opr }; + const instructionNumber = { "+" : 1, "-" : 2 }[opr]; + return { left, opr, instructionNumber }; } / left: VAR { - return { left }; + return { left, instructionNumber: 0 }; } -VAR = symbol:"Y" { return symbol } / symbol:("X" / "Z") ind:Integer+ { - return symbol + ind; +VAR = symbol:"Y" { return { symbol, godel: 1 }; } / symbol:("X" / "Z") ind:Integer+ { + const index = parseInt(ind); + const order = ["X", "Z"]; + const godel = index * order.length + order.indexOf(symbol); + return { symbol: symbol + ind, godel }; } GOTO = "GOTO" @@ -48,10 +64,12 @@ GOTO = "GOTO" OPERATION = "+" / "-" LABEL_V = symbol:END_LABEL { return symbol } / symbol:[A-E] ind:Integer+ { - return symbol + ind; + const index = parseInt(ind); + const godel = (symbol.charCodeAt(0) - "A".charCodeAt(0) + 1) + 5*(index-1); + return { symbol: symbol + ind, godel }; } -END_LABEL = "E" +END_LABEL = "E1" Integer "integer" = [0-9]+ { return parseInt(text(), 10); } diff --git a/godel/index.html b/godel/index.html index 1769959..f8e8dad 100644 --- a/godel/index.html +++ b/godel/index.html @@ -17,20 +17,22 @@ @@ -71,6 +73,17 @@
+
+

Godel

+

Sequence:

+

+      
+

Number:

+
+

+    
diff --git a/godel/js/compiler.js b/godel/js/compiler.js index e63f5b0..e978244 100644 --- a/godel/js/compiler.js +++ b/godel/js/compiler.js @@ -11,11 +11,14 @@ class StringBuilder { } const compileGoto = (gotoNode, stringBuilder) => { - stringBuilder.add(`this.followGoto("${gotoNode.label}");\nreturn;\n`); + stringBuilder.add(`this.followGoto("${gotoNode.label.symbol}");\nreturn;\n`); }; const compileConditional = (conditionalNode, stringBuilder) => { - const { variable, goto: gotoNode } = conditionalNode; + const { + variable: { symbol: variable }, + goto: gotoNode, + } = conditionalNode; stringBuilder.add(`if (this.get("${variable}") != 0) {\n`); compileGoto(gotoNode, stringBuilder); @@ -23,7 +26,10 @@ const compileConditional = (conditionalNode, stringBuilder) => { }; const compileAssignment = (assignmentNode, stringBuilder) => { - const { variable, expr } = assignmentNode; + const { + variable: { symbol: variable }, + expr, + } = assignmentNode; if (expr.opr) { if (expr.opr == "+") stringBuilder.add(`this.addOne("${variable}");\n`); else if (expr.opr == "-") @@ -49,6 +55,8 @@ const compileInstruction = (instruction, stringBuilder) => { }; const compile = (ast) => { + const godelSequence = []; + const stringBuilder = new StringBuilder(); stringBuilder.add(` class Program { @@ -65,8 +73,8 @@ const compile = (ast) => { this.finalInstruction = ${ ast.instructions.length + 1 }; // instruction of the implied "exit" label - // "E" is the exit label - this.labelInstructions.set("E", this.finalInstruction); + // "E1" is the exit label + this.labelInstructions.set("E1", this.finalInstruction); } get(variable) { @@ -122,25 +130,31 @@ const compile = (ast) => { stringBuilder.add("// -- build label -> instruction map --\n"); for (let i = 0; i < ast.instructions.length; i++) { - const line = ast.instructions[i]; + const instruction = ast.instructions[i]; + godelSequence.push(instruction.godel); + + const line = instruction.instruction; const instructionIdx = i + 1; if (line.label) { + const symbol = line.label.symbol; stringBuilder.add( - `this.instructions.set(${instructionIdx}, () => this.${line.label}());\n` + `this.instructions.set(${instructionIdx}, () => this.${symbol}());\n` ); stringBuilder.add( - `this.labelInstructions.set("${line.label}", ${instructionIdx});\n` + `this.labelInstructions.set("${symbol}", ${instructionIdx});\n` ); } } stringBuilder.add("// -- compiled instructions --\n"); for (let i = 0; i < ast.instructions.length; i++) { - let instruction = ast.instructions[i]; + let instruction = ast.instructions[i].instruction; const instructionIdx = i + 1; if (instruction.label) { + const symbol = instruction.label.symbol; + stringBuilder.add( - ` this.followGoto("${instruction.label}");\n}\n\n${instruction.label}() {\n` + ` this.followGoto("${symbol}");\n}\n\n${symbol}() {\n` ); stringBuilder.add(`this.instructionPointer = ${instructionIdx};\n`); instruction = instruction.instruction; @@ -152,14 +166,17 @@ const compile = (ast) => { 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("// !! set the initial Snapshot here !!\n"); stringBuilder.add('// program.variables.set("X1", 2);\n\n'); stringBuilder.add("program.run();\n"); stringBuilder.add("console.log(program.variables);\n"); stringBuilder.add("program.getResult();\n"); - return js_beautify(stringBuilder.build(), { - indent_size: 2, - wrap_line_length: 100, - }); + return { + js: js_beautify(stringBuilder.build(), { + indent_size: 2, + wrap_line_length: 100, + }), + godelSequence, + }; }; diff --git a/godel/js/godelWorker.js b/godel/js/godelWorker.js new file mode 100644 index 0000000..594a4ad --- /dev/null +++ b/godel/js/godelWorker.js @@ -0,0 +1,27 @@ +const isPrime = (n) => + !Array(Math.ceil(Math.sqrt(n))) + .fill(0) + .map((_, i) => i + 2) // first prime is 2 + .some((i) => n !== i && n % i === 0); + +const primesCache = [2]; +const p = (i) => { + if (primesCache.length <= i) { + let x = primesCache.at(-1); + while (primesCache.length <= i) { + if (isPrime(++x)) primesCache.push(x); + } + } + return primesCache.at(i - 1); +}; + +const computeGodelNumber = (godelSequence) => + godelSequence.reduce((acc, num, i) => { + const prime = p(i + 1); + return BigInt(acc) * BigInt(prime) ** BigInt(num); + }, 1) - BigInt(1); + +self.addEventListener("message", (e) => { + const godelNumber = computeGodelNumber(e.data); + postMessage(godelNumber); +}); diff --git a/godel/js/main.js b/godel/js/main.js index bd36ef9..898c558 100644 --- a/godel/js/main.js +++ b/godel/js/main.js @@ -18,15 +18,19 @@ const main = () => { if (msg.type == MESSAGES.COMPILE) { const { value } = msg; const source = prepareSource(value); + try { const ast = parser.parse(source); - const program = compile(ast); + const { js, godelSequence } = compile(ast); state.notify({ type: MESSAGES.COMPILE_RESULT, - value: program, + success: true, + js, + godelSequence, }); } catch (e) { + console.error(e); state.notify({ type: MESSAGES.COMPILE_RESULT, error: e.toString(), @@ -39,6 +43,7 @@ const main = () => { const result = eval(source); state.notify({ type: MESSAGES.EVAL_RESULT, + success: true, value: result, }); } catch (e) { @@ -54,33 +59,46 @@ main(); // -- a bit of some hacky ui code -- -const instructionsEl = document.getElementById("instructions"); -const instructionsEditorEl = CodeMirror.fromTextArea(instructionsEl, { +const codeMirrorConfig = { lineNumbers: true, -}); +}; +const instructionsEl = document.getElementById("instructions"); +const instructionsEditorEl = CodeMirror.fromTextArea( + instructionsEl, + codeMirrorConfig +); 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, -}); +const compiledEditorEl = CodeMirror.fromTextArea(compiledEl, codeMirrorConfig); +const godelSequenceEl = document.getElementById("godel_sequence"); +const godelNumberEl = document.getElementById("godel_number"); +const godelNumberComputeBtn = document.getElementById("godel_number_comp"); + 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); + if (msg.success) { + const { js, godelSequence } = msg; + compiledEditorEl.setValue(js); + + godelSequenceEl.innerHTML = `[${godelSequence.join(", ")}]`; + godelNumberComputeBtn.style.display = "inline"; compileStatusEl.classList.add("success"); compileStatusEl.classList.remove("error"); compileStatusEl.innerHTML = `Successful compile at ${new Date().toLocaleString()}!`; } else if (msg.error) { compiledEditorEl.setValue(""); + godelSequenceEl.innerHTML = ""; + godelNumberEl.innerHTML = ""; + godelNumberComputeBtn.style.display = "none"; compileStatusEl.classList.remove("success"); compileStatusEl.classList.add("error"); @@ -88,9 +106,33 @@ state.subscribe((msg) => { } } }); + +state.subscribe((msg) => { + if (msg.type == MESSAGES.COMPILE_RESULT) { + if (msg.success) { + const { godelSequence } = msg; + + godelNumberComputeBtn.onclick = () => { + godelNumberEl.innerHTML = "working..."; + + const worker = new Worker("js/godelWorker.js"); + + worker.addEventListener("message", (e) => { + const godelNumber = e.data; + godelNumberEl.innerHTML = godelNumber.toString(); + }); + + worker.postMessage(godelSequence); + }; + } else if (msg.error) { + godelNumberComputeBtn.onclick = () => {}; + } + } +}); + state.subscribe((msg) => { if (msg.type == MESSAGES.EVAL_RESULT) { - if (typeof msg.value !== "undefined") { + if (msg.success) { evalStatusEl.classList.add("success"); evalStatusEl.classList.remove("error"); evalStatusEl.innerHTML = `Result: ${msg.value}`; diff --git a/godel/js/parser.js b/godel/js/parser.js index c582a28..808132e 100644 --- a/godel/js/parser.js +++ b/godel/js/parser.js @@ -147,7 +147,15 @@ parser = /* return { instructions: lines.filter((line) => typeof line !== "string" || line.trim() != "") }; }, peg$c3 = function(instruction) { - return instruction; + let x = 0; + let y = 0; + if (instruction.label) { + x = instruction.label.godel; + y = instruction.instruction.godel; + } else { + y = instruction.godel; + } + return { instruction, godel: ((2 ** x) * ((2 * y) + 1) - 1) }; }, peg$c4 = function(label, instruction) { return { label, instruction }; @@ -159,11 +167,11 @@ parser = /* peg$c9 = function(label) { return label; }, - peg$c10 = function(conditional) { return { conditional }; }, - peg$c11 = function(assignment) { return { assignment }; }, - peg$c12 = function(goto) { return { goto }; }, + peg$c10 = function(conditional) { return { conditional, godel: conditional.godel }; }, + peg$c11 = function(assignment) { return { assignment, godel: assignment.godel }; }, + peg$c12 = function(goto) { return { goto, godel: goto.godel }; }, peg$c13 = function(label) { - return { label }; + return { label, godel: label.godel + 2 }; }, peg$c14 = "IF", peg$c15 = peg$literalExpectation("IF", false), @@ -172,33 +180,41 @@ parser = /* peg$c18 = "0", peg$c19 = peg$literalExpectation("0", false), peg$c20 = function(variable, goto) { - return { variable, goto }; + const y = variable.godel - 1; + const x = goto.godel; + return { variable, goto, godel: ((2 ** x) * ((2 * y) + 1) - 1) }; }, peg$c21 = "<-", peg$c22 = peg$literalExpectation("<-", false), peg$c23 = function(variable, expr) { - if (expr.left != variable) { + if (expr.left.symbol != variable.symbol) { error("left hand variable must match right hand"); } - return { variable, expr }; + const x = expr.instructionNumber; + const y = variable.godel - 1; + return { variable, expr, godel: ((2 ** x) * ((2 * y) + 1) - 1) }; }, peg$c24 = "1", peg$c25 = peg$literalExpectation("1", false), peg$c26 = function(left, opr) { - return { left, opr }; + const instructionNumber = { "+" : 1, "-" : 2 }[opr]; + return { left, opr, instructionNumber }; }, peg$c27 = function(left) { - return { left }; + return { left, instructionNumber: 0 }; }, peg$c28 = "Y", peg$c29 = peg$literalExpectation("Y", false), - peg$c30 = function(symbol) { return symbol }, + peg$c30 = function(symbol) { return { symbol, godel: 1 }; }, 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; + const index = parseInt(ind); + const order = ["X", "Z"]; + const godel = index * order.length + order.indexOf(symbol); + return { symbol: symbol + ind, godel }; }, peg$c36 = "GOTO", peg$c37 = peg$literalExpectation("GOTO", false), @@ -208,16 +224,19 @@ parser = /* 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$c44 = function(symbol, ind) { + const index = parseInt(ind); + const godel = (symbol.charCodeAt(0) - "A".charCodeAt(0) + 1) + 5*(index-1); + return { symbol: symbol + ind, godel }; + }, + peg$c45 = peg$otherExpectation("integer"), + peg$c46 = /^[0-9]/, + peg$c47 = peg$classExpectation([["0", "9"]], false, false), + peg$c48 = function() { return parseInt(text(), 10); }, + peg$c49 = peg$otherExpectation("whitespace"), + peg$c50 = /^[ \t]/, + peg$c51 = peg$classExpectation([" ", "\t"], false, false), + peg$c52 = function() { }, peg$currPos = 0, peg$savedPos = 0, @@ -360,7 +379,7 @@ parser = /* s0 = peg$currPos; s1 = []; - s2 = peg$parseLine(); + s2 = peg$parseProgramInstruction(); if (s2 === peg$FAILED) { s2 = peg$parse_(); if (s2 === peg$FAILED) { @@ -375,7 +394,7 @@ parser = /* } while (s2 !== peg$FAILED) { s1.push(s2); - s2 = peg$parseLine(); + s2 = peg$parseProgramInstruction(); if (s2 === peg$FAILED) { s2 = peg$parse_(); if (s2 === peg$FAILED) { @@ -398,7 +417,7 @@ parser = /* return s0; } - function peg$parseLine() { + function peg$parseProgramInstruction() { var s0, s1, s2, s3, s4; s0 = peg$currPos; @@ -895,58 +914,35 @@ parser = /* var s0, s1, s2, s3; s0 = peg$currPos; - s1 = peg$parseEND_LABEL(); - if (s1 !== peg$FAILED) { - peg$savedPos = s0; - s1 = peg$c30(s1); + if (peg$c42.test(input.charAt(peg$currPos))) { + s1 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c43); } } - s0 = s1; - if (s0 === peg$FAILED) { - s0 = peg$currPos; - if (peg$c42.test(input.charAt(peg$currPos))) { - s1 = input.charAt(peg$currPos); - peg$currPos++; + if (s1 !== peg$FAILED) { + s2 = []; + s3 = peg$parseInteger(); + if (s3 !== peg$FAILED) { + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = peg$parseInteger(); + } } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c43); } + s2 = peg$FAILED; } - 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; - } + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c44(s1, s2); + s0 = s1; } 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; @@ -958,22 +954,22 @@ parser = /* peg$silentFails++; s0 = peg$currPos; s1 = []; - if (peg$c47.test(input.charAt(peg$currPos))) { + if (peg$c46.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 (peg$silentFails === 0) { peg$fail(peg$c47); } } if (s2 !== peg$FAILED) { while (s2 !== peg$FAILED) { s1.push(s2); - if (peg$c47.test(input.charAt(peg$currPos))) { + if (peg$c46.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 (peg$silentFails === 0) { peg$fail(peg$c47); } } } } else { @@ -981,13 +977,13 @@ parser = /* } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$c49(); + s1 = peg$c48(); } s0 = s1; peg$silentFails--; if (s0 === peg$FAILED) { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c46); } + if (peg$silentFails === 0) { peg$fail(peg$c45); } } return s0; @@ -999,22 +995,22 @@ parser = /* peg$silentFails++; s0 = peg$currPos; s1 = []; - if (peg$c51.test(input.charAt(peg$currPos))) { + if (peg$c50.test(input.charAt(peg$currPos))) { s2 = input.charAt(peg$currPos); peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c52); } + if (peg$silentFails === 0) { peg$fail(peg$c51); } } if (s2 !== peg$FAILED) { while (s2 !== peg$FAILED) { s1.push(s2); - if (peg$c51.test(input.charAt(peg$currPos))) { + if (peg$c50.test(input.charAt(peg$currPos))) { s2 = input.charAt(peg$currPos); peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c52); } + if (peg$silentFails === 0) { peg$fail(peg$c51); } } } } else { @@ -1022,13 +1018,13 @@ parser = /* } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$c53(); + s1 = peg$c52(); } s0 = s1; peg$silentFails--; if (s0 === peg$FAILED) { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c50); } + if (peg$silentFails === 0) { peg$fail(peg$c49); } } return s0; -- cgit v1.2.3-70-g09d2 From 57a4d439847bf3d63513b2443dfdf1eca5ecbb02 Mon Sep 17 00:00:00 2001 From: Elizabeth Hunt Date: Fri, 17 Nov 2023 12:12:57 -0700 Subject: add copy state button --- godel/index.html | 3 ++- godel/js/main.js | 14 +++++++++++++- 2 files changed, 15 insertions(+), 2 deletions(-) (limited to 'godel/index.html') diff --git a/godel/index.html b/godel/index.html index f8e8dad..f74a48e 100644 --- a/godel/index.html +++ b/godel/index.html @@ -54,7 +54,8 @@ Y <- Y + 1 GOTO C1
- +
{ + const instructions = btoa(instructionsEditorEl.getValue()); + + navigator.clipboard + .writeText( + window.location.href.split("?")[0] + `?instructions=${instructions}` + ) + .then(() => alert("copied to clipboard")); +}); state.subscribe((msg) => { if (msg.type == MESSAGES.COMPILE_RESULT) { @@ -146,7 +158,7 @@ state.subscribe((msg) => { const urlParams = new URLSearchParams(window.location.search); if (urlParams.get("instructions")) { - editorEl.setValue(atob(urlParams.get("instructions"))); + instructionsEditorEl.setValue(atob(urlParams.get("instructions"))); } compileButton.addEventListener("click", () => { -- cgit v1.2.3-70-g09d2