├── .gitignore ├── .travis.yml ├── FUNDING.yml ├── LICENSE ├── ascii.html ├── base64_encode.html ├── build.py ├── cfg2cnf.html ├── cfg2ll.html ├── css ├── ascii.css ├── automata.css ├── base64_encode.css ├── cfg2cnf.css ├── cfg2ll.css ├── cyk.css ├── first_follow.css ├── index.css ├── lalr.css ├── left_fact.css ├── left_rec.css ├── ll1.css ├── lr0.css ├── lr1.css ├── min_dfa.css ├── nfa2dfa.css ├── punch_card.css ├── random_hex.css ├── regex2nfa.css ├── toolbox.css └── url_encode.css ├── cyk.html ├── first_follow.html ├── index.html ├── js ├── ascii.js ├── automata.js ├── base64_encode.js ├── cfg2cnf.js ├── cfg2ll.js ├── cyk.js ├── first_follow.js ├── index.js ├── lalr.js ├── left_fact.js ├── left_rec.js ├── lexical.js ├── ll1.js ├── lr0.js ├── lr1.js ├── min_dfa.js ├── nfa2dfa.js ├── punch_card.js ├── random_hex.js ├── regex2nfa.js ├── syntax.js └── url_encode.js ├── lalr.html ├── left_fact.html ├── left_rec.html ├── lib ├── css │ ├── bootstrap-material-design.min.css │ ├── bootstrap-theme.min.css │ ├── bootstrap.min.css │ └── ripples.min.css ├── fonts │ ├── glyphicons-halflings-regular.eot │ ├── glyphicons-halflings-regular.svg │ ├── glyphicons-halflings-regular.ttf │ ├── glyphicons-halflings-regular.woff │ └── glyphicons-halflings-regular.woff2 └── js │ ├── bootstrap.min.js │ ├── d3.v3.min.js │ ├── dagre-d3.min.js │ ├── jquery.min.js │ ├── material.min.js │ └── ripples.min.js ├── ll1.html ├── lr0.html ├── lr1.html ├── min_dfa.html ├── nfa2dfa.html ├── package.json ├── parts ├── ascii.html ├── base64_encode.html ├── cfg2cnf.html ├── cfg2ll.html ├── cyk.html ├── first_follow.html ├── index.html ├── lalr.html ├── left_fact.html ├── left_rec.html ├── ll1.html ├── lr0.html ├── lr1.html ├── min_dfa.html ├── nfa2dfa.html ├── punch_card.html ├── random_hex.html ├── regex2nfa.html └── url_encode.html ├── punch_card.html ├── random_hex.html ├── regex2nfa.html ├── robots.txt ├── sitemap.txt ├── template.html ├── test ├── test_lexical_min_dfa.js ├── test_lexical_parse_regex.js ├── test_lexical_regex_to_nfa.js ├── test_syntax_automaton_lalr.js ├── test_syntax_automaton_lr0.js ├── test_syntax_automaton_lr1.js ├── test_syntax_closure.js ├── test_syntax_closure_lr1.js ├── test_syntax_first_follow.js ├── test_syntax_left_factoring.js ├── test_syntax_left_recursion.js ├── test_syntax_parse_grammar.js └── test_syntax_table_ll1.js └── url_encode.html /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | npm-debug.log 3 | .DS_Store 4 | .idea 5 | package-lock.json 6 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "node" 4 | branches: 5 | only: 6 | - gh-pages 7 | - /.*/ 8 | before-install: 9 | - pip install --user pycodestyle 10 | - $(which npm) install -g jslint 11 | before-script: 12 | - pycodestyle --max-line-length=100 . 13 | - npm run lint 14 | script: 15 | - npm test 16 | -------------------------------------------------------------------------------- /FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: ['CyberZHG'] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 13 | -------------------------------------------------------------------------------- /ascii.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ASCII 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 68 | 69 |
70 | 71 |
72 | 73 | 74 |
75 | 76 | 77 | 78 | 79 | 80 | 81 | 86 | 87 | 88 | 97 | 98 | 99 | 100 | -------------------------------------------------------------------------------- /base64_encode.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Base64 Encode/Decode 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 68 | 69 |
70 | 71 |
72 | 73 |

Source:

74 |
75 |
76 |
77 | 78 | 79 | 80 |
81 |
82 | 83 | 84 | 85 | 86 | 87 | 88 |
89 |
90 | 91 |

Target:

92 |
93 |
94 |
95 | 96 | 97 | 98 |
99 | 100 | 101 |
102 | 103 | 104 | 105 | 106 | 107 | 108 | 113 | 114 | 115 | 124 | 125 | 126 | 127 | -------------------------------------------------------------------------------- /build.py: -------------------------------------------------------------------------------- 1 | import os 2 | from time import sleep, strftime, gmtime 3 | 4 | TEMPLATE_FILE = 'template.html' 5 | PARTS_FOLDER = 'parts' 6 | MAGIC_TITLE = 'FC32C705' 7 | MAGIC_BODY = '75CAF6CF' 8 | MAGIC_CSS = 'EAC9ED81' 9 | MAGIC_JS = 'BB33DD4B' 10 | MAGIC_TEMPLATE = '3B893512' 11 | 12 | last = {} 13 | while True: 14 | sleep(3) 15 | last_modified = os.path.getmtime(TEMPLATE_FILE) 16 | if MAGIC_TEMPLATE in last and last[MAGIC_TEMPLATE] != last_modified: 17 | last = {} 18 | if MAGIC_TEMPLATE not in last: 19 | with open(TEMPLATE_FILE) as reader: 20 | template = reader.read() 21 | last[MAGIC_TEMPLATE] = last_modified 22 | has_modification = False 23 | for file_name in os.listdir(PARTS_FOLDER): 24 | if file_name[-5:] != '.html': 25 | continue 26 | file_path = os.path.join(PARTS_FOLDER, file_name) 27 | last_modified = os.path.getmtime(file_path) 28 | if file_name in last and last_modified == last[file_name]: 29 | continue 30 | has_modification = True 31 | last[file_name] = last_modified 32 | print(strftime("%Y-%m-%d %H:%M:%S", gmtime()) + ' ' + file_name) 33 | with open(file_path) as reader: 34 | title = reader.readline().strip()[4:-3].strip() 35 | prefix = file_name[:-5] 36 | css_path = 'css/' + prefix + '.css' 37 | if not os.path.exists(css_path): 38 | with open(css_path, 'w') as writer: 39 | pass 40 | js_path = 'js/' + prefix + '.js' 41 | if not os.path.exists(js_path): 42 | with open(js_path, 'w') as writer: 43 | pass 44 | html = template.replace(MAGIC_TITLE, title) \ 45 | .replace(MAGIC_BODY, reader.read()) \ 46 | .replace(MAGIC_CSS, prefix) \ 47 | .replace(MAGIC_JS, prefix) 48 | with open(file_name, 'w') as writer: 49 | writer.write(html) 50 | if has_modification: 51 | with open('sitemap.txt', 'w') as writer: 52 | writer.write('https://cyberzhg.github.io/toolbox/\n') 53 | for file_name in os.listdir(PARTS_FOLDER): 54 | if file_name[-5:] != '.html': 55 | continue 56 | writer.write('https://cyberzhg.github.io/toolbox/' + file_name[:-5] + '\n') 57 | -------------------------------------------------------------------------------- /css/ascii.css: -------------------------------------------------------------------------------- 1 | .container-body { 2 | max-width: 800px; 3 | margin: 0 auto; 4 | margin-top: 70px; 5 | } 6 | -------------------------------------------------------------------------------- /css/automata.css: -------------------------------------------------------------------------------- 1 | .edgePath path { 2 | stroke: #000; /* Arrow color */ 3 | fill: #000; /* Arrow Tip color */ 4 | stroke-width: 1.5px; 5 | } 6 | 7 | foreignobject { 8 | color: #000; 9 | } 10 | 11 | .node rect, 12 | .node circle, 13 | .node ellipse, 14 | .node polygon { 15 | stroke: #000; 16 | fill: #FFF; 17 | fill-opacity: 0; 18 | } 19 | -------------------------------------------------------------------------------- /css/base64_encode.css: -------------------------------------------------------------------------------- 1 | textarea { 2 | width: 100%; 3 | height: 200px; 4 | } 5 | 6 | .btn { 7 | margin-bottom: 10px; 8 | } 9 | -------------------------------------------------------------------------------- /css/cfg2cnf.css: -------------------------------------------------------------------------------- 1 | .well li, #input_grammar, #output_grammar { 2 | font-family: Consolas; 3 | } 4 | -------------------------------------------------------------------------------- /css/cfg2ll.css: -------------------------------------------------------------------------------- 1 | .well li, #input_grammar, #output_grammar { 2 | font-family: Consolas; 3 | } 4 | -------------------------------------------------------------------------------- /css/cyk.css: -------------------------------------------------------------------------------- 1 | .well li, #input_grammar, #input_code, #output_grammar, table { 2 | font-family: Consolas; 3 | } 4 | -------------------------------------------------------------------------------- /css/first_follow.css: -------------------------------------------------------------------------------- 1 | .well li, td, #input_grammar, #output_grammar { 2 | font-family: Consolas; 3 | } 4 | -------------------------------------------------------------------------------- /css/index.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CyberZHG/toolbox/045e527997445b7f5ad3da1927040dde553ddcc7/css/index.css -------------------------------------------------------------------------------- /css/lalr.css: -------------------------------------------------------------------------------- 1 | .well li, #input_grammar, #output_grammar, table, tspan { 2 | font-family: Consolas; 3 | } 4 | -------------------------------------------------------------------------------- /css/left_fact.css: -------------------------------------------------------------------------------- 1 | .well li, #input_grammar, #output_grammar { 2 | font-family: Consolas; 3 | } 4 | -------------------------------------------------------------------------------- /css/left_rec.css: -------------------------------------------------------------------------------- 1 | .well li, #input_grammar, #output_grammar { 2 | font-family: Consolas; 3 | } 4 | -------------------------------------------------------------------------------- /css/ll1.css: -------------------------------------------------------------------------------- 1 | .well li, #input_grammar, #output_grammar, table { 2 | font-family: Consolas; 3 | } 4 | -------------------------------------------------------------------------------- /css/lr0.css: -------------------------------------------------------------------------------- 1 | .well li, #input_grammar, #output_grammar, table, tspan { 2 | font-family: Consolas; 3 | } 4 | -------------------------------------------------------------------------------- /css/lr1.css: -------------------------------------------------------------------------------- 1 | .well li, #input_grammar, #output_grammar, table, tspan { 2 | font-family: Consolas; 3 | } 4 | -------------------------------------------------------------------------------- /css/min_dfa.css: -------------------------------------------------------------------------------- 1 | .well li, #input_regex { 2 | font-family: Consolas; 3 | } 4 | -------------------------------------------------------------------------------- /css/nfa2dfa.css: -------------------------------------------------------------------------------- 1 | .well li, #input_regex { 2 | font-family: Consolas; 3 | } 4 | -------------------------------------------------------------------------------- /css/punch_card.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CyberZHG/toolbox/045e527997445b7f5ad3da1927040dde553ddcc7/css/punch_card.css -------------------------------------------------------------------------------- /css/random_hex.css: -------------------------------------------------------------------------------- 1 | #div_num { 2 | font-family: Consolas; 3 | } 4 | -------------------------------------------------------------------------------- /css/regex2nfa.css: -------------------------------------------------------------------------------- 1 | .well li, #input_regex { 2 | font-family: Consolas; 3 | } 4 | -------------------------------------------------------------------------------- /css/toolbox.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: "Microsoft Yahei", "Helvetica Neue", Helvetica, Arial, sans-serif; 3 | } 4 | 5 | .container-body { 6 | margin-top: 70px; 7 | margin-left: 10px; 8 | margin-right: 10px; 9 | } -------------------------------------------------------------------------------- /css/url_encode.css: -------------------------------------------------------------------------------- 1 | textarea { 2 | width: 100%; 3 | height: 200px; 4 | } 5 | 6 | .btn { 7 | margin-bottom: 10px; 8 | } 9 | -------------------------------------------------------------------------------- /cyk.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | CYK 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 68 | 69 |
70 | 71 |
72 | 73 |
74 |

Introduction

75 |
76 |

77 | Construction of parsing tables using CYK (Cocke–Younger–Kasami) algorithm for CNF grammars. 78 |

79 |
80 |
81 | 82 |
83 |

Supported grammars

84 |
    85 |
  • A -> A c | A a d | b d | ϵ
    (All tokens must be separated by space characters)
  • 86 |
  • A -> A c
       | A a d
       | b d
       | ϵ
  • 87 |
  • S -> A a | b
    A -> A c | S d | ϵ
  • 88 |
  • (Copy ϵ to input if needed)
  • 89 |
90 |
91 |
92 | 93 |
94 |

Example

95 |
    96 |
  • 97 | Grammar:
    98 | S -> A B | B C
    99 | A -> B A | a
    100 | B -> C C | b
    101 | C -> A B | a 102 |
  • 103 |
  • Input: b b a b a a
  • 104 |
105 |
106 |
107 |
108 | 109 |
110 |
111 | 112 |
113 | 119 |
120 |
121 |
122 |
123 |
124 | 125 |
126 | 127 |
128 |
129 |
130 |
131 |
132 | 133 |
134 |
135 | 140 |
141 |
142 |
143 |
144 |
145 |
146 | 147 |
148 | 149 |
150 |
151 |
152 | 153 | 154 | 155 | 156 |
157 | 158 | 159 | 160 | 161 | 162 | 163 | 168 | 169 | 170 | 179 | 180 | 181 | 182 | -------------------------------------------------------------------------------- /first_follow.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | First & Follow 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 68 | 69 |
70 | 71 |
72 | 73 |
74 |

Introduction

75 |
76 |

77 | Compute first and follow set. 78 |

79 |
80 |
81 | 82 |
83 |

Supported grammars

84 |
    85 |
  • A -> A c | A a d | b d | ϵ
    (All tokens must be separated by space characters)
  • 86 |
  • A -> A c
       | A a d
       | b d
       | ϵ
  • 87 |
  • S -> A a | b
    A -> A c | S d | ϵ
  • 88 |
  • (Copy ϵ to input if needed)
  • 89 |
90 |
91 |
92 | 93 |
94 |

Examples

95 |
    96 |
  • S -> S S + | S S * | a
  • 97 |
  • S -> 0 S 1 | 0 1
  • 98 |
  • S -> + S S | * S S | a
  • 99 |
  • S -> S ( S ) S | ϵ
  • 100 |
  • S -> S + S | S S | ( S ) | S * | a
  • 101 |
  • S -> ( L ) | a L -> L , S | S
  • 102 |
  • S -> a S b S | b S a S | ϵ
  • 103 |
  • 104 | bexpr -> bexpr or bterm | bterm
    105 | bterm -> bterm and bfactor | bfactor
    106 | bfactor -> not bfactor | ( bexpr ) | true | false 107 |
  • 108 |
109 |
110 |
111 |
112 | 113 |
114 |
115 | 116 |
117 | 118 |
119 |
120 |
121 |
122 |
123 | 124 |
125 |
126 | 131 |
132 |
133 |
134 |
135 |
136 | 137 |
138 | 139 |
140 |
141 |
142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 158 | 159 | 160 | 169 | 170 | 171 | 172 | -------------------------------------------------------------------------------- /js/ascii.js: -------------------------------------------------------------------------------- 1 | /*jslint browser: true*/ 2 | /*global $*/ 3 | 4 | $(document).ready(function () { 5 | 'use strict'; 6 | var i, encoded, html, 7 | specialChars = { 8 | '0': 'NUL', 9 | '1': 'SOH', 10 | '2': 'STX', 11 | '3': 'ETX', 12 | '4': 'EOT', 13 | '5': 'ENQ', 14 | '6': 'ACK', 15 | '7': 'BEL', 16 | '8': 'BS', 17 | '9': 'TAB', 18 | '10': 'LF', 19 | '11': 'VT', 20 | '12': 'FF', 21 | '13': 'CR', 22 | '14': 'SO', 23 | '15': 'SI', 24 | '16': 'DLE', 25 | '17': 'DC1', 26 | '18': 'DC2', 27 | '19': 'DC3', 28 | '20': 'DC4', 29 | '21': 'NAK', 30 | '22': 'SYN', 31 | '23': 'ETB', 32 | '24': 'CAN', 33 | '25': 'EM', 34 | '26': 'SUB', 35 | '27': 'ESC', 36 | '28': 'FS', 37 | '29': 'GS', 38 | '30': 'RS', 39 | '31': 'US', 40 | '32': 'Space', 41 | '127': 'DEL' 42 | }, 43 | ascii = document.getElementById('ascii'); 44 | html = ''; 45 | html += '
'; 46 | html += 'Bin'; 47 | html += 'Oct'; 48 | html += 'Dec'; 49 | html += 'Hex'; 50 | html += 'Char'; 51 | html += 'HTML'; 52 | html += '
'; 53 | 54 | function paddingLeft(str, len) { 55 | var pad; 56 | if (str.length === len) { 57 | return str; 58 | } 59 | pad = new [].constructor((len - str.length) + 1); 60 | return pad.join('0') + str; 61 | } 62 | 63 | function htmlEncode(html) { 64 | return document.createElement('a').appendChild(document.createTextNode(html)).parentNode.innerHTML; 65 | } 66 | 67 | 68 | for (i = 0; i < 128; i += 1) { 69 | html += '
'; 70 | html += '' + paddingLeft(i.toString(2), 8) + ''; 71 | html += '' + paddingLeft(i.toString(8), 3) + ''; 72 | html += '' + paddingLeft(i.toString(10), 3) + ''; 73 | html += '' + paddingLeft(i.toString(16), 2) + ''; 74 | if (specialChars.hasOwnProperty(i.toString())) { 75 | html += '' + specialChars[i.toString()] + ''; 76 | } else { 77 | html += '' + String.fromCharCode(i) + ''; 78 | } 79 | encoded = htmlEncode(String.fromCharCode(i)); 80 | if (!encoded || encoded[0] !== '&') { 81 | encoded = '&#' + i; 82 | } 83 | html += '' + htmlEncode(encoded) + ''; 84 | html += '
'; 85 | } 86 | ascii.innerHTML = html; 87 | }); 88 | -------------------------------------------------------------------------------- /js/base64_encode.js: -------------------------------------------------------------------------------- 1 | /*jslint browser: true*/ 2 | /*global $*/ 3 | 4 | $(document).ready(function () { 5 | 'use strict'; 6 | 7 | function b64EncodeUnicode(str) { 8 | return window.btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function (match, p1) { 9 | match = match.prototype; // For jslint. 10 | return String.fromCharCode('0x' + p1); 11 | })); 12 | } 13 | 14 | function b64DecodeUnicode(str) { 15 | return decodeURIComponent(Array.prototype.map.call(window.atob(str), function (c) { 16 | return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2); 17 | }).join('')); 18 | } 19 | 20 | $('#button_encode').click(function () { 21 | $('#text_target').val(b64EncodeUnicode($('#text_source').val())); 22 | }); 23 | 24 | $('#button_decode').click(function () { 25 | try { 26 | $('#text_target').val(b64DecodeUnicode($('#text_source').val())); 27 | } catch (e) { 28 | $('#text_target').val(e); 29 | } 30 | }); 31 | 32 | }); 33 | -------------------------------------------------------------------------------- /js/cfg2ll.js: -------------------------------------------------------------------------------- 1 | /*jslint browser: true*/ 2 | /*global window, parseGrammar, leftFactoring, eliminateLeftRecursion, toPretty, $*/ 3 | 4 | $(document).ready(function () { 5 | 'use strict'; 6 | 7 | function b64EncodeUnicode(str) { 8 | return window.btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function (match, p1) { 9 | match = match.prototype; // For jslint. 10 | return String.fromCharCode('0x' + p1); 11 | })); 12 | } 13 | 14 | function b64DecodeUnicode(str) { 15 | return decodeURIComponent(Array.prototype.map.call(window.atob(str.replace(' ', '+')), function (c) { 16 | return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2); 17 | }).join('')); 18 | } 19 | 20 | function getParameterByName(name) { 21 | var url = window.location.href, 22 | regex, 23 | results; 24 | name = name.replace(/[\[\]]/g, "\\$&"); 25 | regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"); 26 | results = regex.exec(url); 27 | if (!results) { 28 | return null; 29 | } 30 | if (!results[2]) { 31 | return ''; 32 | } 33 | return decodeURIComponent(results[2].replace(/\+/g, " ")); 34 | } 35 | 36 | $('#button_convert').click(function () { 37 | var grammar = parseGrammar($('#input_grammar').val()), 38 | factored = leftFactoring(grammar), 39 | eliminated = eliminateLeftRecursion(factored), 40 | pretty = toPretty(eliminated), 41 | prefix = window.location.href.split('?')[0] + '?grammar=', 42 | input = b64EncodeUnicode($('#input_grammar').val()); 43 | $('#input_url').val(prefix + input); 44 | $('#alert_error').hide(); 45 | $('#output_grammar').text(pretty); 46 | }); 47 | 48 | var input = getParameterByName('grammar'); 49 | if (input) { 50 | input = b64DecodeUnicode(input); 51 | $('#input_grammar').val(input); 52 | $('#button_convert').click(); 53 | } 54 | 55 | }); 56 | -------------------------------------------------------------------------------- /js/cyk.js: -------------------------------------------------------------------------------- 1 | /*jslint browser: true*/ 2 | /*global window, Set, parseGrammar, $*/ 3 | 4 | $(document).ready(function () { 5 | 'use strict'; 6 | 7 | function b64EncodeUnicode(str) { 8 | return window.btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function (match, p1) { 9 | match = match.prototype; // For jslint. 10 | return String.fromCharCode('0x' + p1); 11 | })); 12 | } 13 | 14 | function b64DecodeUnicode(str) { 15 | return decodeURIComponent(Array.prototype.map.call(window.atob(str.replace(' ', '+')), function (c) { 16 | return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2); 17 | }).join('')); 18 | } 19 | 20 | function getParameterByName(name) { 21 | var url = window.location.href, 22 | regex, 23 | results; 24 | name = name.replace(/[\[\]]/g, "\\$&"); 25 | regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"); 26 | results = regex.exec(url); 27 | if (!results) { 28 | return null; 29 | } 30 | if (!results[2]) { 31 | return ''; 32 | } 33 | return decodeURIComponent(results[2].replace(/\+/g, " ")); 34 | } 35 | 36 | function parseCode(code) { 37 | return code.split(' ').filter(function (token) { 38 | return token.length > 0; 39 | }); 40 | } 41 | 42 | function constructCYKParsingTable(grammar, code) { 43 | var i, j, k, l, li, ri, 44 | key = '', 45 | keys = Object.keys(grammar), 46 | inverse = {}, 47 | table = []; 48 | // Record inverse grammar 49 | for (i = 0; i < keys.length; i += 1) { 50 | for (j = 0; j < grammar[keys[i]].length; j += 1) { 51 | key = grammar[keys[i]][j].join(' '); 52 | if (!inverse.hasOwnProperty(key)) { 53 | inverse[key] = []; 54 | } 55 | inverse[key].push(keys[i]); 56 | } 57 | } 58 | // Initiliaze table and diagonal 59 | for (i = 0; i < code.length; i += 1) { 60 | table.push([]); 61 | for (j = 0; j < code.length; j += 1) { 62 | table[i].push([]); 63 | } 64 | if (inverse.hasOwnProperty(code[i])) { 65 | table[i][i] = table[i][i].concat(inverse[code[i]]); 66 | } 67 | } 68 | // Extend by dynamic programming 69 | for (l = 1; l < code.length; l += 1) { 70 | for (i = 0; i + l < code.length; i += 1) { 71 | j = i + l; 72 | for (k = i; k < j; k += 1) { 73 | for (li = 0; li < table[i][k].length; li += 1) { 74 | for (ri = 0; ri < table[k + 1][j].length; ri += 1) { 75 | key = table[i][k][li] + ' ' + table[k + 1][j][ri]; 76 | if (inverse.hasOwnProperty(key)) { 77 | table[i][j] = table[i][j].concat(inverse[key]); 78 | } 79 | } 80 | } 81 | } 82 | table[i][j] = Array.from(new Set(table[i][j])); 83 | } 84 | } 85 | return table; 86 | } 87 | 88 | function showParsingTable(code, table) { 89 | var i, j, 90 | html = ''; 91 | html += ''; 92 | html += ''; 93 | html += ''; 94 | html += ''; 95 | for (i = 0; i < code.length; i += 1) { 96 | html += ''; 97 | } 98 | html += ''; 99 | html += ''; 100 | html += ''; 101 | for (j = 0; j < code.length; j += 1) { 102 | html += ''; 103 | html += ''; 104 | for (i = 0; i < code.length; i += 1) { 105 | html += ''; 106 | } 107 | html += ''; 108 | } 109 | html += ''; 110 | html += '
j \\ i' + i + '
' + j + '' + table[i][j].join(' ') + '
'; 111 | $('#parsing_table').html(html); 112 | } 113 | 114 | $('#button_construct').click(function () { 115 | var grammar = parseGrammar($('#input_grammar').val()), 116 | code = parseCode($('#input_code').val()), 117 | table = constructCYKParsingTable(grammar, code), 118 | prefix = window.location.href.split('?')[0] + '?grammar=', 119 | input = b64EncodeUnicode($('#input_grammar').val()); 120 | $('#input_url').val(prefix + input); 121 | $('#alert_error').hide(); 122 | showParsingTable(code, table); 123 | }); 124 | 125 | var input = getParameterByName('grammar'); 126 | if (input) { 127 | input = b64DecodeUnicode(input); 128 | $('#input_grammar').val(input); 129 | $('#button_construct').click(); 130 | } 131 | 132 | }); 133 | -------------------------------------------------------------------------------- /js/first_follow.js: -------------------------------------------------------------------------------- 1 | /*jslint browser: true*/ 2 | /*global window, parseGrammar, calcNullables, calcFirsts, calcFollows, $*/ 3 | 4 | $(document).ready(function () { 5 | 'use strict'; 6 | 7 | function b64EncodeUnicode(str) { 8 | return window.btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function (match, p1) { 9 | match = match.prototype; // For jslint. 10 | return String.fromCharCode('0x' + p1); 11 | })); 12 | } 13 | 14 | function b64DecodeUnicode(str) { 15 | return decodeURIComponent(Array.prototype.map.call(window.atob(str.replace(' ', '+')), function (c) { 16 | return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2); 17 | }).join('')); 18 | } 19 | 20 | function getParameterByName(name) { 21 | var url = window.location.href, 22 | regex, 23 | results; 24 | name = name.replace(/[\[\]]/g, "\\$&"); 25 | regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"); 26 | results = regex.exec(url); 27 | if (!results) { 28 | return null; 29 | } 30 | if (!results[2]) { 31 | return ''; 32 | } 33 | return decodeURIComponent(results[2].replace(/\+/g, " ")); 34 | } 35 | 36 | $('#button_compute').click(function () { 37 | var grammar = parseGrammar($('#input_grammar').val()), 38 | nullables = calcNullables(grammar), 39 | firsts = calcFirsts(grammar, nullables), 40 | follows = calcFollows(grammar, nullables, firsts), 41 | symbols = Object.keys(follows), 42 | html = '', 43 | prefix = window.location.href.split('?')[0] + '?grammar=', 44 | input = b64EncodeUnicode($('#input_grammar').val()); 45 | $('#input_url').val(prefix + input); 46 | $('#alert_error').hide(); 47 | html += ''; 48 | html += ''; 49 | html += ''; 50 | html += ''; 51 | html += ''; 52 | html += ''; 53 | html += ''; 54 | html += ''; 55 | html += ''; 56 | html += ''; 57 | symbols.sort(); 58 | symbols.forEach(function (symbol) { 59 | html += ''; 60 | html += ''; 61 | html += ''; 62 | html += ''; 63 | html += ''; 64 | html += ''; 65 | }); 66 | html += ''; 67 | html += '
SymbolNullableFirstFollow
' + symbol + '' + nullables[symbol] + '' + firsts[symbol].join(' ') + '' + follows[symbol].join(' ') + '
'; 68 | $('#result_table').html(html); 69 | }); 70 | 71 | var input = getParameterByName('grammar'); 72 | if (input) { 73 | input = b64DecodeUnicode(input); 74 | $('#input_grammar').val(input); 75 | $('#button_compute').click(); 76 | } 77 | 78 | }); 79 | -------------------------------------------------------------------------------- /js/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CyberZHG/toolbox/045e527997445b7f5ad3da1927040dde553ddcc7/js/index.js -------------------------------------------------------------------------------- /js/lalr.js: -------------------------------------------------------------------------------- 1 | /*jslint browser: true*/ 2 | /*global window, parseGrammar, calcFollows, constructLALRAutomaton, genAutomatonLR1, $*/ 3 | 4 | $(document).ready(function () { 5 | 'use strict'; 6 | 7 | function b64EncodeUnicode(str) { 8 | return window.btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function (match, p1) { 9 | match = match.prototype; // For jslint. 10 | return String.fromCharCode('0x' + p1); 11 | })); 12 | } 13 | 14 | function b64DecodeUnicode(str) { 15 | return decodeURIComponent(Array.prototype.map.call(window.atob(str.replace(' ', '+')), function (c) { 16 | return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2); 17 | }).join('')); 18 | } 19 | 20 | function getParameterByName(name) { 21 | var url = window.location.href, 22 | regex, 23 | results; 24 | name = name.replace(/[\[\]]/g, "\\$&"); 25 | regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"); 26 | results = regex.exec(url); 27 | if (!results) { 28 | return null; 29 | } 30 | if (!results[2]) { 31 | return ''; 32 | } 33 | return decodeURIComponent(results[2].replace(/\+/g, " ")); 34 | } 35 | 36 | function showParsingTable(grammar, follows, automaton) { 37 | var i, j, k, 38 | keys = Object.keys(grammar), 39 | symbol, 40 | symbols = [], 41 | queue = [automaton], 42 | front = 0, 43 | node, 44 | nums, 45 | nodes = {'0': automaton}, 46 | html = '', 47 | td, 48 | count; 49 | if (!follows) { 50 | return; 51 | } 52 | while (front < queue.length) { 53 | node = queue[front]; 54 | front += 1; 55 | symbol = Object.keys(node.edges); 56 | for (j = 0; j < symbol.length; j += 1) { 57 | if (symbol[j] !== '$') { 58 | if (keys.indexOf(symbol[j]) < 0 && symbols.indexOf(symbol[j]) < 0) { 59 | symbols.push(symbol[j]); 60 | } 61 | } 62 | if (!nodes.hasOwnProperty(node.edges[symbol[j]].num)) { 63 | nodes[node.edges[symbol[j]].num] = node.edges[symbol[j]]; 64 | queue.push(node.edges[symbol[j]]); 65 | } 66 | } 67 | } 68 | symbols.sort(); 69 | symbols.push('$'); 70 | 71 | html += ''; 72 | html += ''; 73 | html += ''; 74 | html += ''; 75 | html += ''; 76 | html += ''; 77 | html += ''; 78 | html += ''; 79 | for (i = 0; i < symbols.length; i += 1) { 80 | html += ''; 81 | } 82 | for (i = 0; i < keys.length; i += 1) { 83 | html += ''; 84 | } 85 | html += ''; 86 | html += ''; 87 | html += ''; 88 | nums = Object.keys(nodes); 89 | for (i = 0; i < nums.length; i += 1) { 90 | html += ''; 91 | html += ''; 92 | node = nodes[nums[i]]; 93 | for (j = 0; j < symbols.length; j += 1) { 94 | td = ''; 95 | count = 0; 96 | if (symbols[j] === '$' && node.accept) { 97 | count += 1; 98 | td += 'acc'; 99 | } 100 | if (node.edges.hasOwnProperty(symbols[j])) { 101 | if (count > 0) { 102 | td += '
'; 103 | } 104 | count += 1; 105 | td += 's' + node.edges[symbols[j]].num; 106 | } 107 | if (node.reduces.hasOwnProperty(symbols[j])) { 108 | for (k = 0; k < node.reduces[symbols[j]].length; k += 1) { 109 | if (count > 0) { 110 | td += '
'; 111 | } 112 | count += 1; 113 | td += 'r( ' + node.reduces[symbols[j]][k].head + ' -> ' + node.reduces[symbols[j]][k].body.join(' ') + ' )'; 114 | } 115 | } 116 | if (count > 1) { 117 | html += ''; 118 | } else { 119 | html += ''; 120 | } 121 | } 122 | for (j = 0; j < keys.length; j += 1) { 123 | if (node.edges.hasOwnProperty(keys[j])) { 124 | html += ''; 125 | } else { 126 | html += ''; 127 | } 128 | } 129 | html += ''; 130 | } 131 | html += ''; 132 | html += '
STATEACTIONGOTO
' + symbols[i] + '' + keys[i] + '
' + nums[i] + '' + td + '' + td + '' + node.edges[keys[j]].num + '
'; 133 | $('#parsing_table').html(html); 134 | } 135 | 136 | $('#button_construct').click(function () { 137 | var grammar = parseGrammar($('#input_grammar').val()), 138 | follows = calcFollows(grammar), 139 | automaton = constructLALRAutomaton(grammar), 140 | prefix = window.location.href.split('?')[0] + '?grammar=', 141 | input = b64EncodeUnicode($('#input_grammar').val()); 142 | $('#input_url').val(prefix + input); 143 | $('#alert_error').hide(); 144 | showParsingTable(grammar, follows, automaton); 145 | $('svg').attr("width", $('svg').parent().width()); 146 | genAutomatonLR1('svg', automaton); 147 | }); 148 | 149 | var input = getParameterByName('grammar'); 150 | if (input) { 151 | input = b64DecodeUnicode(input); 152 | $('#input_grammar').val(input); 153 | $('#button_construct').click(); 154 | } 155 | 156 | }); 157 | -------------------------------------------------------------------------------- /js/left_fact.js: -------------------------------------------------------------------------------- 1 | /*jslint browser: true*/ 2 | /*global window, parseGrammar, leftFactoring, toPretty, $*/ 3 | 4 | $(document).ready(function () { 5 | 'use strict'; 6 | 7 | function b64EncodeUnicode(str) { 8 | return window.btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function (match, p1) { 9 | match = match.prototype; // For jslint. 10 | return String.fromCharCode('0x' + p1); 11 | })); 12 | } 13 | 14 | function b64DecodeUnicode(str) { 15 | return decodeURIComponent(Array.prototype.map.call(window.atob(str.replace(' ', '+')), function (c) { 16 | return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2); 17 | }).join('')); 18 | } 19 | 20 | function getParameterByName(name) { 21 | var url = window.location.href, 22 | regex, 23 | results; 24 | name = name.replace(/[\[\]]/g, "\\$&"); 25 | regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"); 26 | results = regex.exec(url); 27 | if (!results) { 28 | return null; 29 | } 30 | if (!results[2]) { 31 | return ''; 32 | } 33 | return decodeURIComponent(results[2].replace(/\+/g, " ")); 34 | } 35 | 36 | $('#button_convert').click(function () { 37 | var grammar = parseGrammar($('#input_grammar').val()), 38 | factored = leftFactoring(grammar), 39 | pretty = toPretty(factored), 40 | prefix = window.location.href.split('?')[0] + '?grammar=', 41 | input = b64EncodeUnicode($('#input_grammar').val()); 42 | $('#input_url').val(prefix + input); 43 | $('#alert_error').hide(); 44 | $('#output_grammar').text(pretty); 45 | }); 46 | 47 | var input = getParameterByName('grammar'); 48 | if (input) { 49 | input = b64DecodeUnicode(input); 50 | $('#input_grammar').val(input); 51 | $('#button_convert').click(); 52 | } 53 | 54 | }); 55 | -------------------------------------------------------------------------------- /js/left_rec.js: -------------------------------------------------------------------------------- 1 | /*jslint browser: true*/ 2 | /*global window, parseGrammar, eliminateLeftRecursion, toPretty, $*/ 3 | 4 | $(document).ready(function () { 5 | 'use strict'; 6 | 7 | function b64EncodeUnicode(str) { 8 | return window.btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function (match, p1) { 9 | match = match.prototype; // For jslint. 10 | return String.fromCharCode('0x' + p1); 11 | })); 12 | } 13 | 14 | function b64DecodeUnicode(str) { 15 | return decodeURIComponent(Array.prototype.map.call(window.atob(str.replace(' ', '+')), function (c) { 16 | return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2); 17 | }).join('')); 18 | } 19 | 20 | function getParameterByName(name) { 21 | var url = window.location.href, 22 | regex, 23 | results; 24 | name = name.replace(/[\[\]]/g, "\\$&"); 25 | regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"); 26 | results = regex.exec(url); 27 | if (!results) { 28 | return null; 29 | } 30 | if (!results[2]) { 31 | return ''; 32 | } 33 | return decodeURIComponent(results[2].replace(/\+/g, " ")); 34 | } 35 | 36 | $('#button_convert').click(function () { 37 | var grammar = parseGrammar($('#input_grammar').val()), 38 | eliminated = eliminateLeftRecursion(grammar), 39 | pretty = toPretty(eliminated), 40 | prefix = window.location.href.split('?')[0] + '?grammar=', 41 | input = b64EncodeUnicode($('#input_grammar').val()); 42 | $('#input_url').val(prefix + input); 43 | $('#alert_error').hide(); 44 | $('#output_grammar').text(pretty); 45 | }); 46 | 47 | var input = getParameterByName('grammar'); 48 | if (input) { 49 | input = b64DecodeUnicode(input); 50 | $('#input_grammar').val(input); 51 | $('#button_convert').click(); 52 | } 53 | 54 | }); 55 | -------------------------------------------------------------------------------- /js/ll1.js: -------------------------------------------------------------------------------- 1 | /*jslint browser: true*/ 2 | /*global window, parseGrammar, constructLL1ParsingTable, $*/ 3 | 4 | $(document).ready(function () { 5 | 'use strict'; 6 | 7 | function b64EncodeUnicode(str) { 8 | return window.btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function (match, p1) { 9 | match = match.prototype; // For jslint. 10 | return String.fromCharCode('0x' + p1); 11 | })); 12 | } 13 | 14 | function b64DecodeUnicode(str) { 15 | return decodeURIComponent(Array.prototype.map.call(window.atob(str.replace(' ', '+')), function (c) { 16 | return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2); 17 | }).join('')); 18 | } 19 | 20 | function getParameterByName(name) { 21 | var url = window.location.href, 22 | regex, 23 | results; 24 | name = name.replace(/[\[\]]/g, "\\$&"); 25 | regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"); 26 | results = regex.exec(url); 27 | if (!results) { 28 | return null; 29 | } 30 | if (!results[2]) { 31 | return ''; 32 | } 33 | return decodeURIComponent(results[2].replace(/\+/g, " ")); 34 | } 35 | 36 | function showParsingTable(grammar, table) { 37 | var i, j, k, 38 | keys = Object.keys(grammar), 39 | symbol, 40 | symbols = [], 41 | html = ''; 42 | for (i = 0; i < keys.length; i += 1) { 43 | symbol = Object.keys(table[keys[i]]); 44 | for (j = 0; j < symbol.length; j += 1) { 45 | if (symbol[j] !== '$' && symbols.indexOf(symbol[j]) < 0) { 46 | symbols.push(symbol[j]); 47 | } 48 | } 49 | } 50 | symbols.sort(); 51 | symbols.push('$'); 52 | html += ''; 53 | html += ''; 54 | html += ''; 55 | html += ''; 56 | for (i = 0; i < symbols.length; i += 1) { 57 | html += ''; 58 | } 59 | html += ''; 60 | html += ''; 61 | html += ''; 62 | for (i = 0; i < keys.length; i += 1) { 63 | html += ''; 64 | html += ''; 65 | for (j = 0; j < symbols.length; j += 1) { 66 | if (table[keys[i]].hasOwnProperty(symbols[j])) { 67 | if (table[keys[i]][symbols[j]].length > 1) { 68 | html += ''; 79 | } else { 80 | html += ''; 81 | } 82 | } 83 | html += ''; 84 | } 85 | html += ''; 86 | html += '
Head' + symbols[i] + '
' + keys[i] + ''; 69 | } else { 70 | html += ''; 71 | } 72 | for (k = 0; k < table[keys[i]][symbols[j]].length; k += 1) { 73 | if (k > 0) { 74 | html += '
'; 75 | } 76 | html += [keys[i], '->'].concat(table[keys[i]][symbols[j]][k]).join(' '); 77 | } 78 | html += '
'; 87 | $('#parsing_table').html(html); 88 | } 89 | 90 | $('#button_construct').click(function () { 91 | var grammar = parseGrammar($('#input_grammar').val()), 92 | table = constructLL1ParsingTable(grammar), 93 | prefix = window.location.href.split('?')[0] + '?grammar=', 94 | input = b64EncodeUnicode($('#input_grammar').val()); 95 | $('#input_url').val(prefix + input); 96 | $('#alert_error').hide(); 97 | showParsingTable(grammar, table); 98 | }); 99 | 100 | var input = getParameterByName('grammar'); 101 | if (input) { 102 | input = b64DecodeUnicode(input); 103 | $('#input_grammar').val(input); 104 | $('#button_construct').click(); 105 | } 106 | 107 | }); 108 | -------------------------------------------------------------------------------- /js/lr0.js: -------------------------------------------------------------------------------- 1 | /*jslint browser: true*/ 2 | /*global window, parseGrammar, calcFollows, constructLR0Automaton, genAutomatonLR0, $*/ 3 | 4 | $(document).ready(function () { 5 | 'use strict'; 6 | 7 | function b64EncodeUnicode(str) { 8 | return window.btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function (match, p1) { 9 | match = match.prototype; // For jslint. 10 | return String.fromCharCode('0x' + p1); 11 | })); 12 | } 13 | 14 | function b64DecodeUnicode(str) { 15 | return decodeURIComponent(Array.prototype.map.call(window.atob(str.replace(' ', '+')), function (c) { 16 | return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2); 17 | }).join('')); 18 | } 19 | 20 | function getParameterByName(name) { 21 | var url = window.location.href, 22 | regex, 23 | results; 24 | name = name.replace(/[\[\]]/g, "\\$&"); 25 | regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"); 26 | results = regex.exec(url); 27 | if (!results) { 28 | return null; 29 | } 30 | if (!results[2]) { 31 | return ''; 32 | } 33 | return decodeURIComponent(results[2].replace(/\+/g, " ")); 34 | } 35 | 36 | function showParsingTable(grammar, follows, automaton) { 37 | var i, j, k, 38 | keys = Object.keys(grammar), 39 | symbol, 40 | symbols = [], 41 | queue = [automaton], 42 | front = 0, 43 | node, 44 | nums, 45 | nodes = {'0': automaton}, 46 | html = '', 47 | td, 48 | count; 49 | if (!follows) { 50 | return; 51 | } 52 | while (front < queue.length) { 53 | node = queue[front]; 54 | front += 1; 55 | symbol = Object.keys(node.edges); 56 | for (j = 0; j < symbol.length; j += 1) { 57 | if (symbol[j] !== '$') { 58 | if (keys.indexOf(symbol[j]) < 0 && symbols.indexOf(symbol[j]) < 0) { 59 | symbols.push(symbol[j]); 60 | } 61 | } 62 | if (!nodes.hasOwnProperty(node.edges[symbol[j]].num)) { 63 | nodes[node.edges[symbol[j]].num] = node.edges[symbol[j]]; 64 | queue.push(node.edges[symbol[j]]); 65 | } 66 | } 67 | } 68 | symbols.sort(); 69 | symbols.push('$'); 70 | 71 | html += ''; 72 | html += ''; 73 | html += ''; 74 | html += ''; 75 | html += ''; 76 | html += ''; 77 | html += ''; 78 | html += ''; 79 | for (i = 0; i < symbols.length; i += 1) { 80 | html += ''; 81 | } 82 | for (i = 0; i < keys.length; i += 1) { 83 | html += ''; 84 | } 85 | html += ''; 86 | html += ''; 87 | html += ''; 88 | nums = Object.keys(nodes); 89 | for (i = 0; i < nums.length; i += 1) { 90 | html += ''; 91 | html += ''; 92 | node = nodes[nums[i]]; 93 | for (j = 0; j < symbols.length; j += 1) { 94 | td = ''; 95 | count = 0; 96 | if (symbols[j] === '$' && node.accept) { 97 | count += 1; 98 | td += 'acc'; 99 | } 100 | if (node.edges.hasOwnProperty(symbols[j])) { 101 | if (count > 0) { 102 | td += '
'; 103 | } 104 | count += 1; 105 | td += 's' + node.edges[symbols[j]].num; 106 | } 107 | if (node.reduces.hasOwnProperty(symbols[j])) { 108 | for (k = 0; k < node.reduces[symbols[j]].length; k += 1) { 109 | if (count > 0) { 110 | td += '
'; 111 | } 112 | count += 1; 113 | td += 'r( ' + node.reduces[symbols[j]][k].head + ' -> ' + node.reduces[symbols[j]][k].body.join(' ') + ' )'; 114 | } 115 | } 116 | if (count > 1) { 117 | html += ''; 118 | } else { 119 | html += ''; 120 | } 121 | } 122 | for (j = 0; j < keys.length; j += 1) { 123 | if (node.edges.hasOwnProperty(keys[j])) { 124 | html += ''; 125 | } else { 126 | html += ''; 127 | } 128 | } 129 | html += ''; 130 | } 131 | html += ''; 132 | html += '
STATEACTIONGOTO
' + symbols[i] + '' + keys[i] + '
' + nums[i] + '' + td + '' + td + '' + node.edges[keys[j]].num + '
'; 133 | $('#parsing_table').html(html); 134 | } 135 | 136 | $('#button_construct').click(function () { 137 | var grammar = parseGrammar($('#input_grammar').val()), 138 | follows = calcFollows(grammar), 139 | automaton = constructLR0Automaton(grammar), 140 | prefix = window.location.href.split('?')[0] + '?grammar=', 141 | input = b64EncodeUnicode($('#input_grammar').val()); 142 | $('#input_url').val(prefix + input); 143 | $('#alert_error').hide(); 144 | showParsingTable(grammar, follows, automaton); 145 | $('svg').attr("width", $('svg').parent().width()); 146 | genAutomatonLR0('svg', automaton); 147 | }); 148 | 149 | var input = getParameterByName('grammar'); 150 | if (input) { 151 | input = b64DecodeUnicode(input); 152 | $('#input_grammar').val(input); 153 | $('#button_construct').click(); 154 | } 155 | 156 | }); 157 | -------------------------------------------------------------------------------- /js/lr1.js: -------------------------------------------------------------------------------- 1 | /*jslint browser: true*/ 2 | /*global window, parseGrammar, calcFollows, constructLR1Automaton, genAutomatonLR1, $*/ 3 | 4 | $(document).ready(function () { 5 | 'use strict'; 6 | 7 | function b64EncodeUnicode(str) { 8 | return window.btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function (match, p1) { 9 | match = match.prototype; // For jslint. 10 | return String.fromCharCode('0x' + p1); 11 | })); 12 | } 13 | 14 | function b64DecodeUnicode(str) { 15 | return decodeURIComponent(Array.prototype.map.call(window.atob(str.replace(' ', '+')), function (c) { 16 | return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2); 17 | }).join('')); 18 | } 19 | 20 | function getParameterByName(name) { 21 | var url = window.location.href, 22 | regex, 23 | results; 24 | name = name.replace(/[\[\]]/g, "\\$&"); 25 | regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"); 26 | results = regex.exec(url); 27 | if (!results) { 28 | return null; 29 | } 30 | if (!results[2]) { 31 | return ''; 32 | } 33 | return decodeURIComponent(results[2].replace(/\+/g, " ")); 34 | } 35 | 36 | function showParsingTable(grammar, follows, automaton) { 37 | var i, j, k, 38 | keys = Object.keys(grammar), 39 | symbol, 40 | symbols = [], 41 | queue = [automaton], 42 | front = 0, 43 | node, 44 | nums, 45 | nodes = {'0': automaton}, 46 | html = '', 47 | td, 48 | count; 49 | if (!follows) { 50 | return; 51 | } 52 | while (front < queue.length) { 53 | node = queue[front]; 54 | front += 1; 55 | symbol = Object.keys(node.edges); 56 | for (j = 0; j < symbol.length; j += 1) { 57 | if (symbol[j] !== '$') { 58 | if (keys.indexOf(symbol[j]) < 0 && symbols.indexOf(symbol[j]) < 0) { 59 | symbols.push(symbol[j]); 60 | } 61 | } 62 | if (!nodes.hasOwnProperty(node.edges[symbol[j]].num)) { 63 | nodes[node.edges[symbol[j]].num] = node.edges[symbol[j]]; 64 | queue.push(node.edges[symbol[j]]); 65 | } 66 | } 67 | } 68 | symbols.sort(); 69 | symbols.push('$'); 70 | 71 | html += ''; 72 | html += ''; 73 | html += ''; 74 | html += ''; 75 | html += ''; 76 | html += ''; 77 | html += ''; 78 | html += ''; 79 | for (i = 0; i < symbols.length; i += 1) { 80 | html += ''; 81 | } 82 | for (i = 0; i < keys.length; i += 1) { 83 | html += ''; 84 | } 85 | html += ''; 86 | html += ''; 87 | html += ''; 88 | nums = Object.keys(nodes); 89 | for (i = 0; i < nums.length; i += 1) { 90 | html += ''; 91 | html += ''; 92 | node = nodes[nums[i]]; 93 | for (j = 0; j < symbols.length; j += 1) { 94 | td = ''; 95 | count = 0; 96 | if (symbols[j] === '$' && node.accept) { 97 | count += 1; 98 | td += 'acc'; 99 | } 100 | if (node.edges.hasOwnProperty(symbols[j])) { 101 | if (count > 0) { 102 | td += '
'; 103 | } 104 | count += 1; 105 | td += 's' + node.edges[symbols[j]].num; 106 | } 107 | if (node.reduces.hasOwnProperty(symbols[j])) { 108 | for (k = 0; k < node.reduces[symbols[j]].length; k += 1) { 109 | if (count > 0) { 110 | td += '
'; 111 | } 112 | count += 1; 113 | td += 'r( ' + node.reduces[symbols[j]][k].head + ' -> ' + node.reduces[symbols[j]][k].body.join(' ') + ' )'; 114 | } 115 | } 116 | if (count > 1) { 117 | html += ''; 118 | } else { 119 | html += ''; 120 | } 121 | } 122 | for (j = 0; j < keys.length; j += 1) { 123 | if (node.edges.hasOwnProperty(keys[j])) { 124 | html += ''; 125 | } else { 126 | html += ''; 127 | } 128 | } 129 | html += ''; 130 | } 131 | html += ''; 132 | html += '
STATEACTIONGOTO
' + symbols[i] + '' + keys[i] + '
' + nums[i] + '' + td + '' + td + '' + node.edges[keys[j]].num + '
'; 133 | $('#parsing_table').html(html); 134 | } 135 | 136 | $('#button_construct').click(function () { 137 | var grammar = parseGrammar($('#input_grammar').val()), 138 | follows = calcFollows(grammar), 139 | automaton = constructLR1Automaton(grammar), 140 | prefix = window.location.href.split('?')[0] + '?grammar=', 141 | input = b64EncodeUnicode($('#input_grammar').val()); 142 | $('#input_url').val(prefix + input); 143 | $('#alert_error').hide(); 144 | showParsingTable(grammar, follows, automaton); 145 | $('svg').attr("width", $('svg').parent().width()); 146 | genAutomatonLR1('svg', automaton); 147 | }); 148 | 149 | var input = getParameterByName('grammar'); 150 | if (input) { 151 | input = b64DecodeUnicode(input); 152 | $('#input_grammar').val(input); 153 | $('#button_construct').click(); 154 | } 155 | 156 | }); 157 | -------------------------------------------------------------------------------- /js/min_dfa.js: -------------------------------------------------------------------------------- 1 | /*jslint browser: true*/ 2 | /*global window, regexToNfa, nfaToDfa, minDfa, genAutomataSVG, $*/ 3 | 4 | $(document).ready(function () { 5 | 'use strict'; 6 | 7 | function b64EncodeUnicode(str) { 8 | return window.btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function (match, p1) { 9 | match = match.prototype; // For jslint. 10 | return String.fromCharCode('0x' + p1); 11 | })); 12 | } 13 | 14 | function b64DecodeUnicode(str) { 15 | return decodeURIComponent(Array.prototype.map.call(window.atob(str.replace(' ', '+')), function (c) { 16 | return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2); 17 | }).join('')); 18 | } 19 | 20 | function getParameterByName(name) { 21 | var url = window.location.href, 22 | regex, 23 | results; 24 | name = name.replace(/[\[\]]/g, "\\$&"); 25 | regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"); 26 | results = regex.exec(url); 27 | if (!results) { 28 | return null; 29 | } 30 | if (!results[2]) { 31 | return ''; 32 | } 33 | return decodeURIComponent(results[2].replace(/\+/g, " ")); 34 | } 35 | 36 | function toNature(col) { 37 | var i, 38 | j, 39 | base = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 40 | result = 0; 41 | if ('1' <= col[0] && col[0] <= '9') { 42 | result = parseInt(col, 10); 43 | } else { 44 | for (i = 0, j = col.length - 1; i < col.length; i += 1, j -= 1) { 45 | result += Math.pow(base.length, j) * (base.indexOf(col[i]) + 1); 46 | } 47 | } 48 | return result; 49 | } 50 | 51 | function genDfaTable(start) { 52 | var i, 53 | j, 54 | states = {}, 55 | nodes = [], 56 | stack = [start], 57 | symbols = [], 58 | top, 59 | html = ''; 60 | while (stack.length > 0) { 61 | top = stack.pop(); 62 | if (!states.hasOwnProperty(top.id)) { 63 | states[top.id] = top; 64 | top.nature = toNature(top.id); 65 | nodes.push(top); 66 | for (i = 0; i < top.edges.length; i += 1) { 67 | if (top.edges[i][0] !== 'ϵ' && symbols.indexOf(top.edges[i][0]) < 0) { 68 | symbols.push(top.edges[i][0]); 69 | } 70 | stack.push(top.edges[i][1]); 71 | } 72 | } 73 | } 74 | nodes.sort(function (a, b) { 75 | return a.nature - b.nature; 76 | }); 77 | symbols.sort(); 78 | html += ''; 79 | html += ''; 80 | html += ''; 81 | html += ''; 82 | html += ''; 83 | html += ''; 84 | for (i = 0; i < symbols.length; i += 1) { 85 | html += ''; 86 | } 87 | html += ''; 88 | html += ''; 89 | html += ''; 90 | for (i = 0; i < nodes.length; i += 1) { 91 | html += ''; 92 | html += ''; 93 | html += ''; 94 | html += ''; 95 | for (j = 0; j < symbols.length; j += 1) { 96 | html += ''; 101 | } 102 | html += ''; 103 | } 104 | html += ''; 105 | html += '
DFA STATEMin-DFA STATETYPE' + symbols[i] + '
{' + nodes[i].key + '}' + nodes[i].id + '' + nodes[i].type + ''; 97 | if (nodes[i].trans.hasOwnProperty(symbols[j])) { 98 | html += nodes[i].trans[symbols[j]].id; 99 | } 100 | html += '
'; 106 | return html; 107 | } 108 | 109 | $('#button_convert').click(function () { 110 | var nfa = regexToNfa($('#input_regex').val()), 111 | dfa, 112 | url, 113 | prefix = window.location.href.split('?')[0] + '?regex=', 114 | input = b64EncodeUnicode($('#input_regex').val()); 115 | $('#input_url').val(prefix + input); 116 | $('#alert_error').hide(); 117 | if (typeof nfa === 'string') { 118 | $('#p_error').text(nfa); 119 | $('#alert_error').show(); 120 | } else { 121 | dfa = minDfa(nfaToDfa(nfa)); 122 | $('#dfa_table').html(genDfaTable(dfa)); 123 | $('svg').attr('width', $('svg').parent().width()); 124 | genAutomataSVG('svg', dfa); 125 | url = prefix.replace('min_dfa', 'nfa2dfa') + input; 126 | $('#dfa_link').html('DFA: ' + url + ''); 127 | } 128 | }); 129 | 130 | var input = getParameterByName('regex'); 131 | if (input) { 132 | input = b64DecodeUnicode(input); 133 | $('#input_regex').val(input); 134 | $('#button_convert').click(); 135 | } 136 | 137 | }); 138 | -------------------------------------------------------------------------------- /js/nfa2dfa.js: -------------------------------------------------------------------------------- 1 | /*jslint browser: true*/ 2 | /*global window, regexToNfa, nfaToDfa, genAutomataSVG, $*/ 3 | 4 | $(document).ready(function () { 5 | 'use strict'; 6 | 7 | function b64EncodeUnicode(str) { 8 | return window.btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function (match, p1) { 9 | match = match.prototype; // For jslint. 10 | return String.fromCharCode('0x' + p1); 11 | })); 12 | } 13 | 14 | function b64DecodeUnicode(str) { 15 | return decodeURIComponent(Array.prototype.map.call(window.atob(str.replace(' ', '+')), function (c) { 16 | return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2); 17 | }).join('')); 18 | } 19 | 20 | function getParameterByName(name) { 21 | var url = window.location.href, 22 | regex, 23 | results; 24 | name = name.replace(/[\[\]]/g, "\\$&"); 25 | regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"); 26 | results = regex.exec(url); 27 | if (!results) { 28 | return null; 29 | } 30 | if (!results[2]) { 31 | return ''; 32 | } 33 | return decodeURIComponent(results[2].replace(/\+/g, " ")); 34 | } 35 | 36 | function toNature(col) { 37 | var i, 38 | j, 39 | base = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 40 | result = 0; 41 | for (i = 0, j = col.length - 1; i < col.length; i += 1, j -= 1) { 42 | result += Math.pow(base.length, j) * (base.indexOf(col[i]) + 1); 43 | } 44 | return result; 45 | } 46 | 47 | function genDfaTable(start) { 48 | var i, 49 | j, 50 | states = {}, 51 | nodes = [], 52 | stack = [start], 53 | symbols = [], 54 | top, 55 | html = ''; 56 | while (stack.length > 0) { 57 | top = stack.pop(); 58 | if (!states.hasOwnProperty(top.id)) { 59 | states[top.id] = top; 60 | top.nature = toNature(top.id); 61 | nodes.push(top); 62 | for (i = 0; i < top.edges.length; i += 1) { 63 | if (top.edges[i][0] !== 'ϵ' && symbols.indexOf(top.edges[i][0]) < 0) { 64 | symbols.push(top.edges[i][0]); 65 | } 66 | stack.push(top.edges[i][1]); 67 | } 68 | } 69 | } 70 | nodes.sort(function (a, b) { 71 | return a.nature - b.nature; 72 | }); 73 | symbols.sort(); 74 | html += ''; 75 | html += ''; 76 | html += ''; 77 | html += ''; 78 | html += ''; 79 | html += ''; 80 | for (i = 0; i < symbols.length; i += 1) { 81 | html += ''; 82 | } 83 | html += ''; 84 | html += ''; 85 | html += ''; 86 | for (i = 0; i < nodes.length; i += 1) { 87 | html += ''; 88 | html += ''; 89 | html += ''; 90 | html += ''; 91 | for (j = 0; j < symbols.length; j += 1) { 92 | html += ''; 97 | } 98 | html += ''; 99 | } 100 | html += ''; 101 | html += '
NFA STATEDFA STATETYPE' + symbols[i] + '
{' + nodes[i].key + '}' + nodes[i].id + '' + nodes[i].type + ''; 93 | if (nodes[i].trans.hasOwnProperty(symbols[j])) { 94 | html += nodes[i].trans[symbols[j]].id; 95 | } 96 | html += '
'; 102 | return html; 103 | } 104 | 105 | $('#button_convert').click(function () { 106 | var nfa = regexToNfa($('#input_regex').val()), 107 | dfa, 108 | url, 109 | prefix = window.location.href.split('?')[0] + '?regex=', 110 | input = b64EncodeUnicode($('#input_regex').val()); 111 | $('#input_url').val(prefix + input); 112 | $('#alert_error').hide(); 113 | if (typeof nfa === 'string') { 114 | $('#p_error').text(nfa); 115 | $('#alert_error').show(); 116 | } else { 117 | dfa = nfaToDfa(nfa); 118 | $('#dfa_table').html(genDfaTable(dfa)); 119 | $('svg').attr('width', $('svg').parent().width()); 120 | genAutomataSVG('svg', dfa); 121 | url = prefix.replace('nfa2dfa', 'regex2nfa') + input; 122 | $('#nfa_link').html('NFA: ' + url + ''); 123 | url = prefix.replace('nfa2dfa', 'min_dfa') + input; 124 | $('#min_dfa_link').html('Min-DFA: ' + url + ''); 125 | } 126 | }); 127 | 128 | var input = getParameterByName('regex'); 129 | if (input) { 130 | input = b64DecodeUnicode(input); 131 | $('#input_regex').val(input); 132 | $('#button_convert').click(); 133 | } 134 | 135 | }); 136 | -------------------------------------------------------------------------------- /js/punch_card.js: -------------------------------------------------------------------------------- 1 | /*jslint browser: true*/ 2 | /*global window, $*/ 3 | 4 | $(document).ready(function () { 5 | 'use strict'; 6 | 7 | var buckets = []; 8 | 9 | function getLastYear() { 10 | return new Date(new Date().setFullYear(new Date().getFullYear() - 1)); 11 | } 12 | 13 | function getISOString(date) { 14 | return date.toISOString().split('.')[0] + 'Z'; 15 | } 16 | 17 | function objToQuery(obj) { 18 | var key, parts = []; 19 | for (key in obj) { 20 | if (obj.hasOwnProperty(key)) { 21 | parts.push(encodeURIComponent(key) + '=' + encodeURIComponent(obj[key])); 22 | } 23 | } 24 | return parts.join('&'); 25 | } 26 | 27 | function getBuckets(commits) { 28 | var i, j, date; 29 | if (buckets.length === 0) { 30 | for (i = 0; i < 7; i += 1) { 31 | buckets.push([]); 32 | for (j = 0; j < 24; j += 1) { 33 | buckets[i].push(0); 34 | } 35 | } 36 | } 37 | for (i = 0; i < commits.length; i += 1) { 38 | date = new Date(commits[i].commit.author.date); 39 | buckets[date.getDay()][date.getHours()] += 1; 40 | } 41 | return buckets; 42 | } 43 | 44 | function drawPunchCard(buckets) { 45 | var i, j, 46 | maxCommitCnt = 0, 47 | days = ['SUN', 'MON', 'TUE', 'WED', 'THU', 'FRI', 'SAT'], 48 | canvas = $('#canvas_card'), 49 | context = canvas[0].getContext('2d'), 50 | width = canvas.width(), 51 | height = canvas.height(), 52 | widthInt = width / 26, 53 | heightInt = height / 9; 54 | for (i = 0; i < buckets.length; i += 1) { 55 | for (j = 0; j < buckets[i].length; j += 1) { 56 | if (buckets[i][j] > maxCommitCnt) { 57 | maxCommitCnt = buckets[i][j]; 58 | } 59 | } 60 | } 61 | maxCommitCnt += 1e-6; 62 | context.clearRect(0, 0, width, height); 63 | context.fillStyle = 'black'; 64 | context.textAlign = 'center'; 65 | context.textBaseline = 'middle'; 66 | for (i = 0; i < days.length; i += 1) { 67 | context.fillText(days[i], widthInt, heightInt * (i + 1)); 68 | } 69 | for (j = 0; j < 24; j += 1) { 70 | context.fillText(j, widthInt * (j + 2), heightInt * 8); 71 | } 72 | for (i = 0; i < buckets.length; i += 1) { 73 | for (j = 0; j < buckets[i].length; j += 1) { 74 | if (buckets[i][j] !== 0) { 75 | context.beginPath(); 76 | context.arc( 77 | widthInt * (j + 2), 78 | heightInt * (i + 1), 79 | Math.min(widthInt, heightInt) * 0.45 * Math.sqrt(buckets[i][j] / maxCommitCnt), 80 | 0, 81 | 2 * Math.PI 82 | ); 83 | context.fillStyle = 'rgba(0, 0, 0, ' + (0.4 + 0.6 * buckets[i][j] / maxCommitCnt) + ')'; 84 | context.fill(); 85 | } 86 | } 87 | } 88 | } 89 | 90 | function queryCommits(url, page) { 91 | $.getJSON(url + '&page=' + page, function (commits) { 92 | if (commits.length > 0) { 93 | drawPunchCard(getBuckets(commits)); 94 | queryCommits(url, page + 1); 95 | } 96 | }); 97 | } 98 | 99 | $('#button_gen').click(function () { 100 | var url = 'https://api.github.com/repos/', 101 | owner = $('#owner').val(), 102 | repo = $('#repo').val(), 103 | author = $('#author').val(), 104 | prev = getISOString(getLastYear()), 105 | now = getISOString(new Date()), 106 | canvas = $('#canvas_card'), 107 | width = canvas.parent().width(), 108 | height = canvas.parent().width() * 0.4, 109 | params = {}; 110 | canvas.attr('width', width); 111 | canvas.attr('height', height); 112 | url += owner + '/' + repo + '/commits'; 113 | params.since = prev; 114 | params.until = now; 115 | if (author) { 116 | params.author = author; 117 | } 118 | url += '?' + objToQuery(params); 119 | queryCommits(url, 1); 120 | }); 121 | 122 | function getParameterByName(name) { 123 | var url = window.location.href, 124 | regex, 125 | results; 126 | name = name.replace(/[\[\]]/g, "\\$&"); 127 | regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"); 128 | results = regex.exec(url); 129 | if (!results) { 130 | return null; 131 | } 132 | if (!results[2]) { 133 | return ''; 134 | } 135 | return decodeURIComponent(results[2].replace(/\+/g, " ")); 136 | } 137 | 138 | if (getParameterByName('owner') && getParameterByName('repo')) { 139 | $('#owner').val(getParameterByName('owner')); 140 | $('#repo').val(getParameterByName('repo')); 141 | $('#button_gen').click(); 142 | } 143 | 144 | }); 145 | -------------------------------------------------------------------------------- /js/random_hex.js: -------------------------------------------------------------------------------- 1 | /*jslint browser: true*/ 2 | /*global $*/ 3 | 4 | $(document).ready(function () { 5 | 'use strict'; 6 | 7 | var i, j, s, html, div_num = document.getElementById('div_num'); 8 | 9 | function dec2hex(c) { 10 | if (c < 10) { 11 | return String.fromCharCode('0'.charCodeAt(0) + c); 12 | } 13 | return String.fromCharCode('A'.charCodeAt(0) + c - 10); 14 | } 15 | 16 | html = ''; 17 | html += '
'; 18 | for (i = 0; i < 480; i += 1) { 19 | s = ''; 20 | for (j = 0; j < 8; j += 1) { 21 | s += dec2hex(Math.floor(Math.random() * 16)); 22 | } 23 | html += '' + s + ''; 24 | } 25 | html += '
'; 26 | div_num.innerHTML = html; 27 | }); 28 | -------------------------------------------------------------------------------- /js/regex2nfa.js: -------------------------------------------------------------------------------- 1 | /*jslint browser: true*/ 2 | /*global window, regexToNfa, genAutomataSVG, $*/ 3 | 4 | $(document).ready(function () { 5 | 'use strict'; 6 | 7 | function b64EncodeUnicode(str) { 8 | return window.btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function (match, p1) { 9 | match = match.prototype; // For jslint. 10 | return String.fromCharCode('0x' + p1); 11 | })); 12 | } 13 | 14 | function b64DecodeUnicode(str) { 15 | return decodeURIComponent(Array.prototype.map.call(window.atob(str.replace(' ', '+')), function (c) { 16 | return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2); 17 | }).join('')); 18 | } 19 | 20 | function getParameterByName(name) { 21 | var url = window.location.href, 22 | regex, 23 | results; 24 | name = name.replace(/[\[\]]/g, "\\$&"); 25 | regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"); 26 | results = regex.exec(url); 27 | if (!results) { 28 | return null; 29 | } 30 | if (!results[2]) { 31 | return ''; 32 | } 33 | return decodeURIComponent(results[2].replace(/\+/g, " ")); 34 | } 35 | 36 | $('#button_convert').click(function () { 37 | var url, 38 | start = regexToNfa($('#input_regex').val()), 39 | prefix = window.location.href.split('?')[0] + '?regex=', 40 | input = b64EncodeUnicode($('#input_regex').val()); 41 | $('#input_url').val(prefix + input); 42 | $('#alert_error').hide(); 43 | if (typeof start === 'string') { 44 | $('#p_error').text(start); 45 | $('#alert_error').show(); 46 | } else { 47 | $('svg').attr("width", $('svg').parent().width()); 48 | genAutomataSVG('svg', start); 49 | url = prefix.replace('regex2nfa', 'nfa2dfa') + input; 50 | $('#dfa_link').html('DFA: ' + url + ''); 51 | } 52 | }); 53 | 54 | var input = getParameterByName('regex'); 55 | if (input) { 56 | input = b64DecodeUnicode(input); 57 | $('#input_regex').val(input); 58 | $('#button_convert').click(); 59 | } 60 | 61 | }); 62 | -------------------------------------------------------------------------------- /js/url_encode.js: -------------------------------------------------------------------------------- 1 | /*jslint browser: true*/ 2 | /*global $*/ 3 | 4 | $(document).ready(function () { 5 | 'use strict'; 6 | 7 | $('#button_encode').click(function () { 8 | $('#text_target').val(encodeURIComponent($('#text_source').val())); 9 | }); 10 | 11 | $('#button_decode').click(function () { 12 | try { 13 | $('#text_target').val(decodeURIComponent($('#text_source').val())); 14 | } catch (e) { 15 | $('#text_target').val(e); 16 | } 17 | }); 18 | 19 | }); 20 | -------------------------------------------------------------------------------- /lib/css/ripples.min.css: -------------------------------------------------------------------------------- 1 | .withripple{position:relative}.ripple-container{position:absolute;top:0;left:0;z-index:1;width:100%;height:100%;overflow:hidden;border-radius:inherit;pointer-events:none}.ripple{position:absolute;width:20px;height:20px;margin-left:-10px;margin-top:-10px;border-radius:100%;background-color:#000;background-color:rgba(0,0,0,.05);-webkit-transform:scale(1);-ms-transform:scale(1);-o-transform:scale(1);transform:scale(1);-webkit-transform-origin:50%;-ms-transform-origin:50%;-o-transform-origin:50%;transform-origin:50%;opacity:0;pointer-events:none}.ripple.ripple-on{-webkit-transition:opacity .15s ease-in 0s,-webkit-transform .5s cubic-bezier(.4,0,.2,1) .1s;-o-transition:opacity .15s ease-in 0s,-o-transform .5s cubic-bezier(.4,0,.2,1) .1s;transition:opacity .15s ease-in 0s,transform .5s cubic-bezier(.4,0,.2,1) .1s;opacity:.1}.ripple.ripple-out{-webkit-transition:opacity .1s linear 0s!important;-o-transition:opacity .1s linear 0s!important;transition:opacity .1s linear 0s!important;opacity:0} 2 | /*# sourceMappingURL=ripples.min.css.map */ -------------------------------------------------------------------------------- /lib/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CyberZHG/toolbox/045e527997445b7f5ad3da1927040dde553ddcc7/lib/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /lib/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CyberZHG/toolbox/045e527997445b7f5ad3da1927040dde553ddcc7/lib/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /lib/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CyberZHG/toolbox/045e527997445b7f5ad3da1927040dde553ddcc7/lib/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /lib/fonts/glyphicons-halflings-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CyberZHG/toolbox/045e527997445b7f5ad3da1927040dde553ddcc7/lib/fonts/glyphicons-halflings-regular.woff2 -------------------------------------------------------------------------------- /lib/js/material.min.js: -------------------------------------------------------------------------------- 1 | !function(a){function b(a){return"undefined"==typeof a.which?!0:"number"==typeof a.which&&a.which>0?!a.ctrlKey&&!a.metaKey&&!a.altKey&&8!=a.which&&9!=a.which&&13!=a.which&&16!=a.which&&17!=a.which&&20!=a.which&&27!=a.which:!1}function c(b){var c=a(b);c.prop("disabled")||c.closest(".form-group").addClass("is-focused")}function d(a,b){var c;return c=a.hasClass("checkbox-inline")||a.hasClass("radio-inline")?a:a.closest(".checkbox").length?a.closest(".checkbox"):a.closest(".radio"),c.toggleClass("disabled",b)}function e(b){var e=!1;(b.is(a.material.options.checkboxElements)||b.is(a.material.options.radioElements))&&(e=!0),b.closest("label").hover(function(){var b=a(this).find("input"),f=b.prop("disabled");e&&d(a(this),f),f||c(b)},function(){f(a(this).find("input"))})}function f(b){a(b).closest(".form-group").removeClass("is-focused")}a.expr[":"].notmdproc=function(b){return a(b).data("mdproc")?!1:!0},a.material={options:{validate:!0,input:!0,ripples:!0,checkbox:!0,togglebutton:!0,radio:!0,arrive:!0,autofill:!1,withRipples:[".btn:not(.btn-link)",".card-image",".navbar a:not(.withoutripple)",".dropdown-menu a",".nav-tabs a:not(.withoutripple)",".withripple",".pagination li:not(.active):not(.disabled) a:not(.withoutripple)"].join(","),inputElements:"input.form-control, textarea.form-control, select.form-control",checkboxElements:".checkbox > label > input[type=checkbox], label.checkbox-inline > input[type=checkbox]",togglebuttonElements:".togglebutton > label > input[type=checkbox]",radioElements:".radio > label > input[type=radio], label.radio-inline > input[type=radio]"},checkbox:function(b){var c=a(b?b:this.options.checkboxElements).filter(":notmdproc").data("mdproc",!0).after("");e(c)},togglebutton:function(b){var c=a(b?b:this.options.togglebuttonElements).filter(":notmdproc").data("mdproc",!0).after("");e(c)},radio:function(b){var c=a(b?b:this.options.radioElements).filter(":notmdproc").data("mdproc",!0).after("");e(c)},input:function(b){a(b?b:this.options.inputElements).filter(":notmdproc").data("mdproc",!0).each(function(){var b=a(this),c=b.closest(".form-group");0!==c.length||"hidden"===b.attr("type")||b.attr("hidden")||(b.wrap("
"),c=b.closest(".form-group")),b.attr("data-hint")&&(b.after("

"+b.attr("data-hint")+"

"),b.removeAttr("data-hint"));var d={"input-lg":"form-group-lg","input-sm":"form-group-sm"};if(a.each(d,function(a,d){b.hasClass(a)&&(b.removeClass(a),c.addClass(d))}),b.hasClass("floating-label")){var e=b.attr("placeholder");b.attr("placeholder",null).removeClass("floating-label");var f=b.attr("id"),g="";f&&(g="for='"+f+"'"),c.addClass("label-floating"),b.after("")}(null===b.val()||"undefined"==b.val()||""===b.val())&&c.addClass("is-empty"),c.find("input[type=file]").length>0&&c.addClass("is-fileinput")})},attachInputEventHandlers:function(){var d=this.options.validate;a(document).on("keydown paste",".form-control",function(c){b(c)&&a(this).closest(".form-group").removeClass("is-empty")}).on("keyup change",".form-control",function(){var b=a(this),c=b.closest(".form-group"),e="undefined"==typeof b[0].checkValidity||b[0].checkValidity();""===b.val()?c.addClass("is-empty"):c.removeClass("is-empty"),d&&(e?c.removeClass("has-error"):c.addClass("has-error"))}).on("focus",".form-control, .form-group.is-fileinput",function(){c(this)}).on("blur",".form-control, .form-group.is-fileinput",function(){f(this)}).on("change",".form-group input",function(){var b=a(this);if("file"!=b.attr("type")){var c=b.closest(".form-group"),d=b.val();d?c.removeClass("is-empty"):c.addClass("is-empty")}}).on("change",".form-group.is-fileinput input[type='file']",function(){var b=a(this),c=b.closest(".form-group"),d="";a.each(this.files,function(a,b){d+=b.name+", "}),d=d.substring(0,d.length-2),d?c.removeClass("is-empty"):c.addClass("is-empty"),c.find("input.form-control[readonly]").val(d)})},ripples:function(b){a(b?b:this.options.withRipples).ripples()},autofill:function(){var b=setInterval(function(){a("input[type!=checkbox]").each(function(){var b=a(this);b.val()&&b.val()!==b.attr("value")&&b.trigger("change")})},100);setTimeout(function(){clearInterval(b)},1e4)},attachAutofillEventHandlers:function(){var b;a(document).on("focus","input",function(){var c=a(this).parents("form").find("input").not("[type=file]");b=setInterval(function(){c.each(function(){var b=a(this);b.val()!==b.attr("value")&&b.trigger("change")})},100)}).on("blur",".form-group input",function(){clearInterval(b)})},init:function(b){this.options=a.extend({},this.options,b);var c=a(document);a.fn.ripples&&this.options.ripples&&this.ripples(),this.options.input&&(this.input(),this.attachInputEventHandlers()),this.options.checkbox&&this.checkbox(),this.options.togglebutton&&this.togglebutton(),this.options.radio&&this.radio(),this.options.autofill&&(this.autofill(),this.attachAutofillEventHandlers()),document.arrive&&this.options.arrive&&(a.fn.ripples&&this.options.ripples&&c.arrive(this.options.withRipples,function(){a.material.ripples(a(this))}),this.options.input&&c.arrive(this.options.inputElements,function(){a.material.input(a(this))}),this.options.checkbox&&c.arrive(this.options.checkboxElements,function(){a.material.checkbox(a(this))}),this.options.radio&&c.arrive(this.options.radioElements,function(){a.material.radio(a(this))}),this.options.togglebutton&&c.arrive(this.options.togglebuttonElements,function(){a.material.togglebutton(a(this))}))}}}(jQuery); 2 | //# sourceMappingURL=material.min.js.map -------------------------------------------------------------------------------- /lib/js/ripples.min.js: -------------------------------------------------------------------------------- 1 | !function(a,b,c,d){"use strict";function e(b,c){g=this,this.element=a(b),this.options=a.extend({},h,c),this._defaults=h,this._name=f,this.init()}var f="ripples",g=null,h={};e.prototype.init=function(){var c=this.element;c.on("mousedown touchstart",function(d){if(!g.isTouch()||"mousedown"!==d.type){c.find(".ripple-container").length||c.append('
');var e=c.children(".ripple-container"),f=g.getRelY(e,d),h=g.getRelX(e,d);if(f||h){var i=g.getRipplesColor(c),j=a("
");j.addClass("ripple").css({left:h,top:f,"background-color":i}),e.append(j),function(){return b.getComputedStyle(j[0]).opacity}(),g.rippleOn(c,j),setTimeout(function(){g.rippleEnd(j)},500),c.on("mouseup mouseleave touchend",function(){j.data("mousedown","off"),"off"===j.data("animating")&&g.rippleOut(j)})}}})},e.prototype.getNewSize=function(a,b){return Math.max(a.outerWidth(),a.outerHeight())/b.outerWidth()*2.5},e.prototype.getRelX=function(a,b){var c=a.offset();return g.isTouch()?(b=b.originalEvent,1===b.touches.length?b.touches[0].pageX-c.left:!1):b.pageX-c.left},e.prototype.getRelY=function(a,b){var c=a.offset();return g.isTouch()?(b=b.originalEvent,1===b.touches.length?b.touches[0].pageY-c.top:!1):b.pageY-c.top},e.prototype.getRipplesColor=function(a){var c=a.data("ripple-color")?a.data("ripple-color"):b.getComputedStyle(a[0]).color;return c},e.prototype.hasTransitionSupport=function(){var a=c.body||c.documentElement,b=a.style,e=b.transition!==d||b.WebkitTransition!==d||b.MozTransition!==d||b.MsTransition!==d||b.OTransition!==d;return e},e.prototype.isTouch=function(){return/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)},e.prototype.rippleEnd=function(a){a.data("animating","off"),"off"===a.data("mousedown")&&g.rippleOut(a)},e.prototype.rippleOut=function(a){a.off(),g.hasTransitionSupport()?a.addClass("ripple-out"):a.animate({opacity:0},100,function(){a.trigger("transitionend")}),a.on("transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd",function(){a.remove()})},e.prototype.rippleOn=function(a,b){var c=g.getNewSize(a,b);g.hasTransitionSupport()?b.css({"-ms-transform":"scale("+c+")","-moz-transform":"scale("+c+")","-webkit-transform":"scale("+c+")",transform:"scale("+c+")"}).addClass("ripple-on").data("animating","on").data("mousedown","on"):b.animate({width:2*Math.max(a.outerWidth(),a.outerHeight()),height:2*Math.max(a.outerWidth(),a.outerHeight()),"margin-left":-1*Math.max(a.outerWidth(),a.outerHeight()),"margin-top":-1*Math.max(a.outerWidth(),a.outerHeight()),opacity:.2},500,function(){b.trigger("transitionend")})},a.fn.ripples=function(b){return this.each(function(){a.data(this,"plugin_"+f)||a.data(this,"plugin_"+f,new e(this,b))})}}(jQuery,window,document); 2 | //# sourceMappingURL=ripples.min.js.map -------------------------------------------------------------------------------- /ll1.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | LL(1) 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 68 | 69 |
70 | 71 |
72 | 73 |
74 |

Introduction

75 |
76 |

77 | Construction of parsing tables for LL(1) grammars. 78 |

79 |
80 |
81 | 82 |
83 |

Supported grammars

84 |
    85 |
  • A -> A c | A a d | b d | ϵ
    (All tokens must be separated by space characters)
  • 86 |
  • A -> A c
       | A a d
       | b d
       | ϵ
  • 87 |
  • S -> A a | b
    A -> A c | S d | ϵ
  • 88 |
  • (Copy ϵ to input if needed)
  • 89 |
90 |
91 |
92 | 93 |
94 |

Examples

95 |
    96 |
  • S -> S S + | S S * | a
  • 97 |
  • S -> 0 S 1 | 0 1
  • 98 |
  • S -> + S S | * S S | a
  • 99 |
  • S -> S ( S ) S | ϵ
  • 100 |
  • S -> S + S | S S | ( S ) | S * | a
  • 101 |
  • S -> ( L ) | a L -> L , S | S
  • 102 |
  • S -> a S b S | b S a S | ϵ
  • 103 |
  • 104 | bexpr -> bexpr or bterm | bterm
    105 | bterm -> bterm and bfactor | bfactor
    106 | bfactor -> not bfactor | ( bexpr ) | true | false 107 |
  • 108 |
109 |
110 |
111 |
112 | 113 |
114 |
115 | 116 |
117 | 124 |
125 |
126 |
127 |
128 |
129 | 130 |
131 |
132 | 137 |
138 |
139 |
140 |
141 |
142 |
143 | 144 |
145 | 146 |
147 |
148 |
149 | 150 | 151 | 152 | 153 |
154 | 155 | 156 | 157 | 158 | 159 | 160 | 165 | 166 | 167 | 176 | 177 | 178 | 179 | -------------------------------------------------------------------------------- /min_dfa.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Regex => NFA => DFA => Min-DFA 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 68 | 69 |
70 | 71 | 72 | 73 |
74 | 75 |
76 |

Introduction

77 |
78 |

79 | Convert simple regular expressions to minimum deterministic finite automaton. (Regex => NFA => DFA => Min-DFA) 80 |

81 |
82 |
83 | 84 |
85 |

Supported grammars

86 |
    87 |
  • r = (s)
  • 88 |
  • r = st
  • 89 |
  • r = s|t
  • 90 |
  • r = s*
  • 91 |
  • r = s+
  • 92 |
  • r = s?
  • 93 |
  • r = ϵ
    (Copy this character to input if needed)
  • 94 |
95 |
96 |
97 | 98 |
99 |

Examples

100 |
    101 |
  • (a|b)*
  • 102 |
  • (a*|b*)*
  • 103 |
  • ((ϵ|a)b*)*
  • 104 |
  • (a|b)*abb(a|b)*
  • 105 |
106 |
107 |
108 |
109 | 110 |
111 |
112 | 113 |
114 | 115 |
116 |
117 |
118 |
119 |
120 | 121 |
122 |
123 | 128 | 129 |
130 |
131 |
132 |
133 |
134 |
135 | 136 | 137 | 138 |
139 |
140 |
141 |
142 | 143 |
144 | 145 |
146 |
147 |
148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 |
156 | 157 | 158 | 159 | 160 | 161 | 162 | 167 | 168 | 169 | 178 | 179 | 180 | 181 | -------------------------------------------------------------------------------- /nfa2dfa.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Regex => NFA => DFA 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 68 | 69 |
70 | 71 | 72 | 73 |
74 | 75 |
76 |

Introduction

77 |
78 |

79 | Convert simple regular expressions to deterministic finite automaton. (Regex => NFA => DFA) 80 |

81 |
82 |
83 | 84 |
85 |

Supported grammars

86 |
    87 |
  • r = (s)
  • 88 |
  • r = st
  • 89 |
  • r = s|t
  • 90 |
  • r = s*
  • 91 |
  • r = s+
  • 92 |
  • r = s?
  • 93 |
  • r = ϵ
    (Copy this character to input if needed)
  • 94 |
95 |
96 |
97 | 98 |
99 |

Examples

100 |
    101 |
  • (a|b)*
  • 102 |
  • (a*|b*)*
  • 103 |
  • ((ϵ|a)b*)*
  • 104 |
  • (a|b)*abb(a|b)*
  • 105 |
106 |
107 |
108 |
109 | 110 |
111 |
112 | 113 |
114 | 115 |
116 |
117 |
118 |
119 |
120 | 121 |
122 |
123 | 128 | 129 | 130 |
131 |
132 |
133 |
134 |
135 |
136 | 137 | 138 | 139 |
140 |
141 |
142 |
143 | 144 |
145 | 146 |
147 |
148 |
149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 |
157 | 158 | 159 | 160 | 161 | 162 | 163 | 168 | 169 | 170 | 179 | 180 | 181 | 182 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "toolbox", 3 | "version": "0.0.1", 4 | "devDependencies": { 5 | "assert": "1.4.1", 6 | "jslint": "^0.10.3", 7 | "mocha": "^3.0.1" 8 | }, 9 | "scripts": { 10 | "lint": "jslint ./js/*.js && jslint ./test/*.js", 11 | "test": "mocha" 12 | }, 13 | "dependencies": {} 14 | } 15 | -------------------------------------------------------------------------------- /parts/ascii.html: -------------------------------------------------------------------------------- 1 | 2 |
3 | -------------------------------------------------------------------------------- /parts/base64_encode.html: -------------------------------------------------------------------------------- 1 | 2 |
3 | 4 |

Source:

5 |
6 |
7 |
8 | 9 | 10 | 11 |
12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 |
21 | 22 |

Target:

23 |
24 |
25 |
26 | 27 | 28 | 29 |
30 | -------------------------------------------------------------------------------- /parts/cfg2cnf.html: -------------------------------------------------------------------------------- 1 | 2 |
3 | 4 |
5 |

Introduction

6 |
7 |

8 | Try converting the given context free grammar to Chomsky normal form. 9 |

10 |
11 |
12 | 13 |
14 |

Supported grammars

15 |
    16 |
  • A -> A c | A a d | b d | ϵ
    (All tokens must be separated by space characters)
  • 17 |
  • A -> A c
       | A a d
       | b d
       | ϵ
  • 18 |
  • S -> A a | b
    A -> A c | S d | ϵ
  • 19 |
  • (Copy ϵ to input if needed)
  • 20 |
21 |
22 |
23 | 24 |
25 |

Examples

26 |
    27 |
  • S -> S S + | S S * | a
  • 28 |
  • S -> 0 S 1 | 0 1
  • 29 |
  • S -> + S S | * S S | a
  • 30 |
  • S -> S ( S ) S | ϵ
  • 31 |
  • S -> S + S | S S | ( S ) | S * | a
  • 32 |
  • S -> ( L ) | a L -> L , S | S
  • 33 |
  • S -> a S b S | b S a S | ϵ
  • 34 |
  • 35 | bexpr -> bexpr or bterm | bterm
    36 | bterm -> bterm and bfactor | bfactor
    37 | bfactor -> not bfactor | ( bexpr ) | true | false 38 |
  • 39 |
40 |
41 |
42 |
43 | 44 |
45 |
46 | 47 |
48 | 49 |
50 |
51 |
52 |
53 |
54 | 55 |
56 |
57 | 62 |
63 |
64 | 65 |
66 | 67 |
68 |
69 |
70 |
71 |
72 | 73 |
74 | 75 |
76 |
77 |
78 | 79 | 80 | -------------------------------------------------------------------------------- /parts/cfg2ll.html: -------------------------------------------------------------------------------- 1 | 2 |
3 | 4 |
5 |

Introduction

6 |
7 |

8 | Try converting the given context free grammar to LL(k) class by performing left factoring then eliminating left recursion. 9 |

10 |
11 |
12 | 13 |
14 |

Supported grammars

15 |
    16 |
  • A -> A c | A a d | b d | ϵ
    (All tokens must be separated by space characters)
  • 17 |
  • A -> A c
       | A a d
       | b d
       | ϵ
  • 18 |
  • S -> A a | b
    A -> A c | S d | ϵ
  • 19 |
  • (Copy ϵ to input if needed)
  • 20 |
21 |
22 |
23 | 24 |
25 |

Examples

26 |
    27 |
  • S -> S S + | S S * | a
  • 28 |
  • S -> 0 S 1 | 0 1
  • 29 |
  • S -> + S S | * S S | a
  • 30 |
  • S -> S ( S ) S | ϵ
  • 31 |
  • S -> S + S | S S | ( S ) | S * | a
  • 32 |
  • S -> ( L ) | a L -> L , S | S
  • 33 |
  • S -> a S b S | b S a S | ϵ
  • 34 |
  • 35 | bexpr -> bexpr or bterm | bterm
    36 | bterm -> bterm and bfactor | bfactor
    37 | bfactor -> not bfactor | ( bexpr ) | true | false 38 |
  • 39 |
40 |
41 |
42 |
43 | 44 |
45 |
46 | 47 |
48 | 49 |
50 |
51 |
52 |
53 |
54 | 55 |
56 |
57 | 62 |
63 |
64 | 65 |
66 | 67 |
68 |
69 |
70 |
71 |
72 | 73 |
74 | 75 |
76 |
77 |
78 | 79 | 80 | -------------------------------------------------------------------------------- /parts/cyk.html: -------------------------------------------------------------------------------- 1 | 2 |
3 | 4 |
5 |

Introduction

6 |
7 |

8 | Construction of parsing tables using CYK (Cocke–Younger–Kasami) algorithm for CNF grammars. 9 |

10 |
11 |
12 | 13 |
14 |

Supported grammars

15 |
    16 |
  • A -> A c | A a d | b d | ϵ
    (All tokens must be separated by space characters)
  • 17 |
  • A -> A c
       | A a d
       | b d
       | ϵ
  • 18 |
  • S -> A a | b
    A -> A c | S d | ϵ
  • 19 |
  • (Copy ϵ to input if needed)
  • 20 |
21 |
22 |
23 | 24 |
25 |

Example

26 |
    27 |
  • 28 | Grammar:
    29 | S -> A B | B C
    30 | A -> B A | a
    31 | B -> C C | b
    32 | C -> A B | a 33 |
  • 34 |
  • Input: b b a b a a
  • 35 |
36 |
37 |
38 |
39 | 40 |
41 |
42 | 43 |
44 | 50 |
51 |
52 |
53 |
54 |
55 | 56 |
57 | 58 |
59 |
60 |
61 |
62 |
63 | 64 |
65 |
66 | 71 |
72 |
73 |
74 |
75 |
76 |
77 | 78 |
79 | 80 |
81 |
82 |
83 | 84 | 85 | -------------------------------------------------------------------------------- /parts/first_follow.html: -------------------------------------------------------------------------------- 1 | 2 |
3 | 4 |
5 |

Introduction

6 |
7 |

8 | Compute first and follow set. 9 |

10 |
11 |
12 | 13 |
14 |

Supported grammars

15 |
    16 |
  • A -> A c | A a d | b d | ϵ
    (All tokens must be separated by space characters)
  • 17 |
  • A -> A c
       | A a d
       | b d
       | ϵ
  • 18 |
  • S -> A a | b
    A -> A c | S d | ϵ
  • 19 |
  • (Copy ϵ to input if needed)
  • 20 |
21 |
22 |
23 | 24 |
25 |

Examples

26 |
    27 |
  • S -> S S + | S S * | a
  • 28 |
  • S -> 0 S 1 | 0 1
  • 29 |
  • S -> + S S | * S S | a
  • 30 |
  • S -> S ( S ) S | ϵ
  • 31 |
  • S -> S + S | S S | ( S ) | S * | a
  • 32 |
  • S -> ( L ) | a L -> L , S | S
  • 33 |
  • S -> a S b S | b S a S | ϵ
  • 34 |
  • 35 | bexpr -> bexpr or bterm | bterm
    36 | bterm -> bterm and bfactor | bfactor
    37 | bfactor -> not bfactor | ( bexpr ) | true | false 38 |
  • 39 |
40 |
41 |
42 |
43 | 44 |
45 |
46 | 47 |
48 | 49 |
50 |
51 |
52 |
53 |
54 | 55 |
56 |
57 | 62 |
63 |
64 | 65 |
66 |
67 | 68 |
69 | 70 |
71 |
72 |
73 | 74 | 75 | -------------------------------------------------------------------------------- /parts/index.html: -------------------------------------------------------------------------------- 1 | 2 |
3 | 4 |

Contents

5 |
6 |
7 |
8 | 9 |

Cheat Sheet

10 |
11 |
12 |
13 | 15 | 16 | ASCII 17 | 18 | 19 | Bin, oct, dec, hex, ascii and html representation. 20 | 21 |
22 |
23 | 24 |

Encoding

25 |
26 |
27 |
28 | 30 | 31 | Base64 Encode/Decode 32 | 33 | 34 | The encoding and decoding of Base64. 35 | 36 |
37 |
38 | 40 | 41 | URL Encode/Decode 42 | 43 | 44 | The encoding and decoding of URL. 45 | 46 |
47 |
48 | 49 |

Random

50 |
51 |
52 |
53 | 55 | 56 | Random HEX 57 | 58 | 59 | Generate random hexadecimal strings. 60 | 61 |
62 |
63 | 64 |

GitHub

65 |
66 |
67 |
68 | 70 | 71 | Punch Card 72 | 73 | 74 | Generate punch card for a public repo. 75 | 76 |
77 |
78 | 79 |

Compiler

80 |
81 |
82 |
83 | 85 | 86 | Regex => NFA 87 | 88 | 89 | Convert simple regular expressions to nondeterministic finite automaton. 90 | 91 |
92 |
93 | 95 | 96 | Regex => NFA => DFA 97 | 98 | 99 | Convert simple regular expressions to deterministic finite automaton. 100 | 101 |
102 |
103 | 105 | 106 | Regex => NFA => DFA => Min-DFA 107 | 108 | 109 | Convert simple regular expressions to minimum deterministic finite automaton. 110 | 111 |
112 |
113 | 115 | 116 | Left factoring 117 | 118 | 119 | Left factoring. 120 | 121 |
122 |
123 | 125 | 126 | Left recursion 127 | 128 | 129 | Try to eliminate left recursion. 130 | 131 |
132 |
133 | 135 | 136 | CFG => LL(k) 137 | 138 | 139 | Try to convert context-free grammar to LL(k) class. 140 | 141 |
142 |
143 | 145 | 146 | CFG => CNF 147 | 148 | 149 | Try to convert context-free grammar to Chomsky normal form. 150 | 151 |
152 |
153 | 155 | 156 | First & Follow 157 | 158 | 159 | Compute first and follow sets for context-free grammars. 160 | 161 |
162 |
163 | 165 | 166 | LR(0)/SLR(1) 167 | 168 | 169 | Construct parsing table and automaton for LR(0)/SLR(1) grammars. 170 | 171 |
172 |
173 | 175 | 176 | LR(1) 177 | 178 | 179 | Construct parsing table and automaton for LR(1) grammars. 180 | 181 |
182 |
183 | 185 | 186 | LALR 187 | 188 | 189 | Construct parsing table and automaton for LALR grammars. 190 | 191 |
192 |
193 | 195 | 196 | CYK 197 | 198 | 199 | Construction of parsing tables using CYK algorithm for CNF grammars. 200 | 201 |
202 | -------------------------------------------------------------------------------- /parts/lalr.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
5 | 6 |
7 |

Introduction

8 |
9 |

10 | Construct automaton and parsing table for LALR grammars. 11 |

12 |
13 |
14 | 15 |
16 |

Supported grammars

17 |
    18 |
  • A -> A c | A a d | b d | ϵ
    (All tokens must be separated by space characters)
  • 19 |
  • A -> A c
       | A a d
       | b d
       | ϵ
  • 20 |
  • S -> A a | b
    A -> A c | S d | ϵ
  • 21 |
  • (Copy ϵ to input if needed)
  • 22 |
23 |
24 |
25 | 26 |
27 |

Examples

28 |
    29 |
  • S -> S S + | S S * | a
  • 30 |
  • S -> 0 S 1 | 0 1
  • 31 |
  • S -> + S S | * S S | a
  • 32 |
  • S -> S ( S ) S | ϵ
  • 33 |
  • S -> S + S | S S | ( S ) | S * | a
  • 34 |
  • S -> ( L ) | a L -> L , S | S
  • 35 |
  • S -> a S b S | b S a S | ϵ
  • 36 |
  • 37 | bexpr -> bexpr or bterm | bterm
    38 | bterm -> bterm and bfactor | bfactor
    39 | bfactor -> not bfactor | ( bexpr ) | true | false 40 |
  • 41 |
42 |
43 |
44 |
45 | 46 |
47 |
48 | 49 |
50 | 54 |
55 |
56 |
57 |
58 |
59 | 60 |
61 |
62 | 67 |
68 |
69 | 70 | 71 | 72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 | 81 |
82 | 83 |
84 |
85 |
86 | 87 | 88 | 89 | 90 | 91 | -------------------------------------------------------------------------------- /parts/left_fact.html: -------------------------------------------------------------------------------- 1 | 2 |
3 | 4 |
5 |

Introduction

6 |
7 |

8 | Left factoring. 9 |

10 |
11 |
12 | 13 |
14 |

Supported grammars

15 |
    16 |
  • A -> A c | A a d | b d | ϵ
    (All tokens must be separated by space characters)
  • 17 |
  • A -> A c
       | A a d
       | b d
       | ϵ
  • 18 |
  • S -> A a | b
    A -> A c | S d | ϵ
  • 19 |
  • (Copy ϵ to input if needed)
  • 20 |
21 |
22 |
23 | 24 |
25 |

Examples

26 |
    27 |
  • S -> S S + | S S * | a
  • 28 |
  • S -> 0 S 1 | 0 1
  • 29 |
  • S -> + S S | * S S | a
  • 30 |
  • S -> S ( S ) S | ϵ
  • 31 |
  • S -> S + S | S S | ( S ) | S * | a
  • 32 |
  • S -> ( L ) | a L -> L , S | S
  • 33 |
  • S -> a S b S | b S a S | ϵ
  • 34 |
  • 35 | bexpr -> bexpr or bterm | bterm
    36 | bterm -> bterm and bfactor | bfactor
    37 | bfactor -> not bfactor | ( bexpr ) | true | false 38 |
  • 39 |
40 |
41 |
42 |
43 | 44 |
45 |
46 | 47 |
48 | 49 |
50 |
51 |
52 |
53 |
54 | 55 |
56 |
57 | 62 |
63 |
64 | 65 |
66 | 67 |
68 |
69 |
70 |
71 |
72 | 73 |
74 | 75 |
76 |
77 |
78 | 79 | 80 | -------------------------------------------------------------------------------- /parts/left_rec.html: -------------------------------------------------------------------------------- 1 | 2 |
3 | 4 |
5 |

Introduction

6 |
7 |

8 | Try to perform the elimination of left recursion, the input grammar should have no cycles or ϵ-productions. 9 |

10 |
11 |
12 | 13 |
14 |

Supported grammars

15 |
    16 |
  • A -> A c | A a d | b d | ϵ
    (All tokens must be separated by space characters)
  • 17 |
  • A -> A c
       | A a d
       | b d
       | ϵ
  • 18 |
  • S -> A a | b
    A -> A c | S d | ϵ
  • 19 |
  • (Copy ϵ to input if needed)
  • 20 |
21 |
22 |
23 | 24 |
25 |

Examples

26 |
    27 |
  • S -> S S + | S S * | a
  • 28 |
  • S -> 0 S 1 | 0 1
  • 29 |
  • S -> + S S | * S S | a
  • 30 |
  • S -> S ( S ) S | ϵ
  • 31 |
  • S -> S + S | S S | ( S ) | S * | a
  • 32 |
  • S -> ( L ) | a L -> L , S | S
  • 33 |
  • S -> a S b S | b S a S | ϵ
  • 34 |
  • 35 | bexpr -> bexpr or bterm | bterm
    36 | bterm -> bterm and bfactor | bfactor
    37 | bfactor -> not bfactor | ( bexpr ) | true | false 38 |
  • 39 |
40 |
41 |
42 |
43 | 44 |
45 |
46 | 47 |
48 | 49 |
50 |
51 |
52 |
53 |
54 | 55 |
56 |
57 | 62 |
63 |
64 | 65 |
66 | 67 |
68 |
69 |
70 |
71 |
72 | 73 |
74 | 75 |
76 |
77 |
78 | 79 | 80 | -------------------------------------------------------------------------------- /parts/ll1.html: -------------------------------------------------------------------------------- 1 | 2 |
3 | 4 |
5 |

Introduction

6 |
7 |

8 | Construction of parsing tables for LL(1) grammars. 9 |

10 |
11 |
12 | 13 |
14 |

Supported grammars

15 |
    16 |
  • A -> A c | A a d | b d | ϵ
    (All tokens must be separated by space characters)
  • 17 |
  • A -> A c
       | A a d
       | b d
       | ϵ
  • 18 |
  • S -> A a | b
    A -> A c | S d | ϵ
  • 19 |
  • (Copy ϵ to input if needed)
  • 20 |
21 |
22 |
23 | 24 |
25 |

Examples

26 |
    27 |
  • S -> S S + | S S * | a
  • 28 |
  • S -> 0 S 1 | 0 1
  • 29 |
  • S -> + S S | * S S | a
  • 30 |
  • S -> S ( S ) S | ϵ
  • 31 |
  • S -> S + S | S S | ( S ) | S * | a
  • 32 |
  • S -> ( L ) | a L -> L , S | S
  • 33 |
  • S -> a S b S | b S a S | ϵ
  • 34 |
  • 35 | bexpr -> bexpr or bterm | bterm
    36 | bterm -> bterm and bfactor | bfactor
    37 | bfactor -> not bfactor | ( bexpr ) | true | false 38 |
  • 39 |
40 |
41 |
42 |
43 | 44 |
45 |
46 | 47 |
48 | 55 |
56 |
57 |
58 |
59 |
60 | 61 |
62 |
63 | 68 |
69 |
70 |
71 |
72 |
73 |
74 | 75 |
76 | 77 |
78 |
79 |
80 | 81 | 82 | -------------------------------------------------------------------------------- /parts/lr0.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
5 | 6 |
7 |

Introduction

8 |
9 |

10 | Construct automaton for LR(0) grammars and construct parsing table for SLR(1) grammars. 11 |

12 |
13 |
14 | 15 |
16 |

Supported grammars

17 |
    18 |
  • A -> A c | A a d | b d | ϵ
    (All tokens must be separated by space characters)
  • 19 |
  • A -> A c
       | A a d
       | b d
       | ϵ
  • 20 |
  • S -> A a | b
    A -> A c | S d | ϵ
  • 21 |
  • (Copy ϵ to input if needed)
  • 22 |
23 |
24 |
25 | 26 |
27 |

Examples

28 |
    29 |
  • S -> S S + | S S * | a
  • 30 |
  • S -> 0 S 1 | 0 1
  • 31 |
  • S -> + S S | * S S | a
  • 32 |
  • S -> S ( S ) S | ϵ
  • 33 |
  • S -> S + S | S S | ( S ) | S * | a
  • 34 |
  • S -> ( L ) | a L -> L , S | S
  • 35 |
  • S -> a S b S | b S a S | ϵ
  • 36 |
  • 37 | bexpr -> bexpr or bterm | bterm
    38 | bterm -> bterm and bfactor | bfactor
    39 | bfactor -> not bfactor | ( bexpr ) | true | false 40 |
  • 41 |
42 |
43 |
44 |
45 | 46 |
47 |
48 | 49 |
50 | 55 |
56 |
57 |
58 |
59 |
60 | 61 |
62 |
63 | 68 |
69 |
70 | 71 | 72 | 73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 | 82 |
83 | 84 |
85 |
86 |
87 | 88 | 89 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /parts/lr1.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
5 | 6 |
7 |

Introduction

8 |
9 |

10 | Construct automaton and parsing table for LR(1) grammars. 11 |

12 |
13 |
14 | 15 |
16 |

Supported grammars

17 |
    18 |
  • A -> A c | A a d | b d | ϵ
    (All tokens must be separated by space characters)
  • 19 |
  • A -> A c
       | A a d
       | b d
       | ϵ
  • 20 |
  • S -> A a | b
    A -> A c | S d | ϵ
  • 21 |
  • (Copy ϵ to input if needed)
  • 22 |
23 |
24 |
25 | 26 |
27 |

Examples

28 |
    29 |
  • S -> S S + | S S * | a
  • 30 |
  • S -> 0 S 1 | 0 1
  • 31 |
  • S -> + S S | * S S | a
  • 32 |
  • S -> S ( S ) S | ϵ
  • 33 |
  • S -> S + S | S S | ( S ) | S * | a
  • 34 |
  • S -> ( L ) | a L -> L , S | S
  • 35 |
  • S -> a S b S | b S a S | ϵ
  • 36 |
  • 37 | bexpr -> bexpr or bterm | bterm
    38 | bterm -> bterm and bfactor | bfactor
    39 | bfactor -> not bfactor | ( bexpr ) | true | false 40 |
  • 41 |
42 |
43 |
44 |
45 | 46 |
47 |
48 | 49 |
50 | 54 |
55 |
56 |
57 |
58 |
59 | 60 |
61 |
62 | 67 |
68 |
69 | 70 | 71 | 72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 | 81 |
82 | 83 |
84 |
85 |
86 | 87 | 88 | 89 | 90 | 91 | -------------------------------------------------------------------------------- /parts/min_dfa.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
5 | 6 |
7 |

Introduction

8 |
9 |

10 | Convert simple regular expressions to minimum deterministic finite automaton. (Regex => NFA => DFA => Min-DFA) 11 |

12 |
13 |
14 | 15 |
16 |

Supported grammars

17 |
    18 |
  • r = (s)
  • 19 |
  • r = st
  • 20 |
  • r = s|t
  • 21 |
  • r = s*
  • 22 |
  • r = s+
  • 23 |
  • r = s?
  • 24 |
  • r = ϵ
    (Copy this character to input if needed)
  • 25 |
26 |
27 |
28 | 29 |
30 |

Examples

31 |
    32 |
  • (a|b)*
  • 33 |
  • (a*|b*)*
  • 34 |
  • ((ϵ|a)b*)*
  • 35 |
  • (a|b)*abb(a|b)*
  • 36 |
37 |
38 |
39 |
40 | 41 |
42 |
43 | 44 |
45 | 46 |
47 |
48 |
49 |
50 |
51 | 52 |
53 |
54 | 59 | 60 |
61 |
62 |
63 |
64 |
65 |
66 | 67 | 68 | 69 |
70 |
71 |
72 |
73 | 74 |
75 | 76 |
77 |
78 |
79 | 80 | 81 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /parts/nfa2dfa.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
5 | 6 |
7 |

Introduction

8 |
9 |

10 | Convert simple regular expressions to deterministic finite automaton. (Regex => NFA => DFA) 11 |

12 |
13 |
14 | 15 |
16 |

Supported grammars

17 |
    18 |
  • r = (s)
  • 19 |
  • r = st
  • 20 |
  • r = s|t
  • 21 |
  • r = s*
  • 22 |
  • r = s+
  • 23 |
  • r = s?
  • 24 |
  • r = ϵ
    (Copy this character to input if needed)
  • 25 |
26 |
27 |
28 | 29 |
30 |

Examples

31 |
    32 |
  • (a|b)*
  • 33 |
  • (a*|b*)*
  • 34 |
  • ((ϵ|a)b*)*
  • 35 |
  • (a|b)*abb(a|b)*
  • 36 |
37 |
38 |
39 |
40 | 41 |
42 |
43 | 44 |
45 | 46 |
47 |
48 |
49 |
50 |
51 | 52 |
53 |
54 | 59 | 60 | 61 |
62 |
63 |
64 |
65 |
66 |
67 | 68 | 69 | 70 |
71 |
72 |
73 |
74 | 75 |
76 | 77 |
78 |
79 |
80 | 81 | 82 | 83 | 84 | 85 | -------------------------------------------------------------------------------- /parts/punch_card.html: -------------------------------------------------------------------------------- 1 | 2 |
3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 |
17 | 18 | 19 | 20 |
21 |
22 | 23 | Unauthenticated requests will be limited to 60 per hour. 24 | 25 |
26 |
27 | 28 | 29 | 30 |
31 | -------------------------------------------------------------------------------- /parts/random_hex.html: -------------------------------------------------------------------------------- 1 | 2 |
3 | -------------------------------------------------------------------------------- /parts/regex2nfa.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
5 | 6 |
7 |

Introduction

8 |
9 |

10 | Convert simple regular expressions to nondeterministic finite automaton. 11 |

12 |
13 |
14 | 15 |
16 |

Supported grammars

17 |
    18 |
  • r = (s)
  • 19 |
  • r = st
  • 20 |
  • r = s|t
  • 21 |
  • r = s*
  • 22 |
  • r = s+
  • 23 |
  • r = s?
  • 24 |
  • r = ϵ
    (Copy this character to input if needed)
  • 25 |
26 |
27 |
28 | 29 |
30 |

Examples

31 |
    32 |
  • (a|b)*
  • 33 |
  • (a*|b*)*
  • 34 |
  • ((ϵ|a)b*)*
  • 35 |
  • (a|b)*abb(a|b)*
  • 36 |
37 |
38 |
39 |
40 | 41 |
42 |
43 | 44 |
45 | 46 |
47 |
48 |
49 |
50 |
51 | 52 |
53 |
54 | 59 | 60 |
61 |
62 | 63 | 64 | 65 |
66 |
67 |
68 |
69 | 70 |
71 | 72 |
73 |
74 |
75 | 76 | 77 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /parts/url_encode.html: -------------------------------------------------------------------------------- 1 | 2 |
3 | 4 |

Source:

5 |
6 |
7 |
8 | 9 | 10 | 11 |
12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 |
21 | 22 |

Target:

23 |
24 |
25 |
26 | 27 | 28 | 29 |
30 | -------------------------------------------------------------------------------- /punch_card.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Punch Card 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 68 | 69 |
70 | 71 |
72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 |
85 |
86 | 87 | 88 | 89 |
90 |
91 | 92 | Unauthenticated requests will be limited to 60 per hour. 93 | 94 |
95 |
96 | 97 | 98 | 99 |
100 | 101 | 102 |
103 | 104 | 105 | 106 | 107 | 108 | 109 | 114 | 115 | 116 | 125 | 126 | 127 | 128 | -------------------------------------------------------------------------------- /random_hex.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Random HEX 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 68 | 69 |
70 | 71 |
72 | 73 | 74 |
75 | 76 | 77 | 78 | 79 | 80 | 81 | 86 | 87 | 88 | 97 | 98 | 99 | 100 | -------------------------------------------------------------------------------- /regex2nfa.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Regex => NFA 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 68 | 69 |
70 | 71 | 72 | 73 |
74 | 75 |
76 |

Introduction

77 |
78 |

79 | Convert simple regular expressions to nondeterministic finite automaton. 80 |

81 |
82 |
83 | 84 |
85 |

Supported grammars

86 |
    87 |
  • r = (s)
  • 88 |
  • r = st
  • 89 |
  • r = s|t
  • 90 |
  • r = s*
  • 91 |
  • r = s+
  • 92 |
  • r = s?
  • 93 |
  • r = ϵ
    (Copy this character to input if needed)
  • 94 |
95 |
96 |
97 | 98 |
99 |

Examples

100 |
    101 |
  • (a|b)*
  • 102 |
  • (a*|b*)*
  • 103 |
  • ((ϵ|a)b*)*
  • 104 |
  • (a|b)*abb(a|b)*
  • 105 |
106 |
107 |
108 |
109 | 110 |
111 |
112 | 113 |
114 | 115 |
116 |
117 |
118 |
119 |
120 | 121 |
122 |
123 | 128 | 129 |
130 |
131 | 132 | 133 | 134 |
135 |
136 |
137 |
138 | 139 |
140 | 141 |
142 |
143 |
144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 |
152 | 153 | 154 | 155 | 156 | 157 | 158 | 163 | 164 | 165 | 174 | 175 | 176 | 177 | -------------------------------------------------------------------------------- /robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Disallow: /parts/ 3 | Disallow: /toolbox/parts/ 4 | -------------------------------------------------------------------------------- /sitemap.txt: -------------------------------------------------------------------------------- 1 | https://cyberzhg.github.io/toolbox/ 2 | https://cyberzhg.github.io/toolbox/ascii 3 | https://cyberzhg.github.io/toolbox/url_encode 4 | https://cyberzhg.github.io/toolbox/base64_encode 5 | https://cyberzhg.github.io/toolbox/punch_card 6 | https://cyberzhg.github.io/toolbox/index 7 | https://cyberzhg.github.io/toolbox/lalr 8 | https://cyberzhg.github.io/toolbox/cfg2ll 9 | https://cyberzhg.github.io/toolbox/cfg2cnf 10 | https://cyberzhg.github.io/toolbox/nfa2dfa 11 | https://cyberzhg.github.io/toolbox/first_follow 12 | https://cyberzhg.github.io/toolbox/lr0 13 | https://cyberzhg.github.io/toolbox/lr1 14 | https://cyberzhg.github.io/toolbox/regex2nfa 15 | https://cyberzhg.github.io/toolbox/cyk 16 | https://cyberzhg.github.io/toolbox/left_fact 17 | https://cyberzhg.github.io/toolbox/left_rec 18 | https://cyberzhg.github.io/toolbox/ll1 19 | https://cyberzhg.github.io/toolbox/min_dfa 20 | https://cyberzhg.github.io/toolbox/random_hex 21 | -------------------------------------------------------------------------------- /template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | FC32C705 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 68 | 69 |
70 | 71 | 75CAF6CF 72 | 73 |
74 | 75 | 76 | 77 | 78 | 79 | 80 | 85 | 86 | 87 | 96 | 97 | 98 | 99 | -------------------------------------------------------------------------------- /test/test_lexical_min_dfa.js: -------------------------------------------------------------------------------- 1 | /*jslint node: true */ 2 | /*global describe, it */ 3 | 'use strict'; 4 | var assert = require('assert'); 5 | var lexical = require('../js/lexical'); 6 | 7 | describe('Lexical', function () { 8 | describe('#minDfa', function () { 9 | it('ϵ', function () { 10 | var nfa = lexical.regexToNfa('ϵ'), 11 | dfa = lexical.nfaToDfa(nfa), 12 | minDfa = lexical.minDfa(dfa); 13 | assert.equal(minDfa.key, 'A'); 14 | assert.equal(minDfa.edges.length, 0); 15 | }); 16 | 17 | it('(a|b)*', function () { 18 | var nfa = lexical.regexToNfa('(a|b)*'), 19 | dfa = lexical.nfaToDfa(nfa), 20 | minDfa = lexical.minDfa(dfa); 21 | assert.equal(minDfa.key, 'A,B,C'); 22 | assert.equal(minDfa.edges.length, 1); 23 | assert.equal(minDfa.trans['a,b'].key, 'A,B,C'); 24 | }); 25 | 26 | it('(a|b)+', function () { 27 | var nfa = lexical.regexToNfa('(a|b)+'), 28 | dfa = lexical.nfaToDfa(nfa), 29 | minDfa = lexical.minDfa(dfa); 30 | assert.equal(minDfa.key, 'A'); 31 | assert.equal(minDfa.edges.length, 1); 32 | assert.equal(minDfa.trans['a,b'].key, 'B,C,D,E'); 33 | assert.equal(minDfa.trans['a,b'].edges.length, 1); 34 | assert.equal(minDfa.trans['a,b'].trans['a,b'].key, 'B,C,D,E'); 35 | }); 36 | 37 | it('a(b|c)*', function () { 38 | var nfa = lexical.regexToNfa('a(b|c)*'), 39 | dfa = lexical.nfaToDfa(nfa), 40 | minDfa = lexical.minDfa(dfa); 41 | assert.equal(minDfa.key, 'A'); 42 | assert.equal(minDfa.edges.length, 1); 43 | assert.equal(minDfa.trans.a.key, 'B,C,D'); 44 | assert.equal(minDfa.trans.a.edges.length, 1); 45 | assert.equal(minDfa.trans.a.trans['b,c'].key, 'B,C,D'); 46 | }); 47 | 48 | it('(a|b)*(c|d)*', function () { 49 | var nfa = lexical.regexToNfa('(a|b)*(c|d)*'), 50 | dfa = lexical.nfaToDfa(nfa), 51 | minDfa = lexical.minDfa(dfa); 52 | assert.equal(minDfa.key, 'A,B,C'); 53 | assert.equal(minDfa.edges.length, 2); 54 | assert.equal(minDfa.trans['a,b'].key, 'A,B,C'); 55 | assert.equal(minDfa.trans['c,d'].key, 'D,E'); 56 | assert.equal(minDfa.trans['c,d'].edges.length, 1); 57 | assert.equal(minDfa.trans['c,d'].trans['c,d'].key, 'D,E'); 58 | }); 59 | 60 | it('ab|b', function () { 61 | var nfa = lexical.regexToNfa('ab|b'), 62 | dfa = lexical.nfaToDfa(nfa), 63 | minDfa = lexical.minDfa(dfa); 64 | assert.equal(minDfa.key, 'A'); 65 | assert.equal(minDfa.edges.length, 2); 66 | assert.equal(minDfa.trans.a.key, 'B'); 67 | assert.equal(minDfa.trans.b.key, 'C,D'); 68 | assert.equal(minDfa.trans.a.edges.length, 1); 69 | assert.equal(minDfa.trans.a.trans.b.key, 'C,D'); 70 | }); 71 | 72 | }); 73 | }); 74 | -------------------------------------------------------------------------------- /test/test_syntax_first_follow.js: -------------------------------------------------------------------------------- 1 | /*jslint node: true */ 2 | /*global describe, it */ 3 | 'use strict'; 4 | var assert = require('assert'); 5 | var syntax = require('../js/syntax'); 6 | 7 | describe('Syntax', function () { 8 | describe('#first&follow', function () { 9 | it('Grammar 4.28', function () { 10 | var grammar = syntax.parseGrammar( 11 | "E -> T E'\n" + 12 | "T -> F T'\n" + 13 | "E' -> + T E' | ϵ\n" + 14 | "T' -> * F T' | ϵ\n" + 15 | "F -> ( E ) | id\n" 16 | ), 17 | keys = Object.keys(grammar), 18 | nullables = syntax.calcNullables(grammar), 19 | firsts = syntax.calcFirsts(grammar, nullables), 20 | follows = syntax.calcFollows(grammar, nullables, firsts), 21 | expectFirsts = { 22 | E: ['(', 'id'], 23 | T: ['(', 'id'], 24 | F: ['(', 'id'], 25 | 'E\'': ['+', 'ϵ'], 26 | 'T\'': ['*', 'ϵ'] 27 | }, 28 | expectFollows = { 29 | E: ['$', ')'], 30 | 'E\'': ['$', ')'], 31 | T: ['$', ')', '+'], 32 | 'T\'': ['$', ')', '+'], 33 | F: ['$', ')', '*', '+'] 34 | }; 35 | keys.forEach(function (key) { 36 | assert.deepEqual(expectFirsts[key], firsts[key]); 37 | }); 38 | assert.deepEqual(expectFollows, follows); 39 | }); 40 | 41 | it('#11', function () { 42 | var grammar = syntax.parseGrammar( 43 | "S -> A B C D\n" + 44 | "A -> b | ϵ\n" + 45 | "B -> c\n" + 46 | "C -> d\n" + 47 | "D -> e\n" 48 | ), 49 | keys = Object.keys(grammar), 50 | nullables = syntax.calcNullables(grammar), 51 | firsts = syntax.calcFirsts(grammar, nullables), 52 | follows = syntax.calcFollows(grammar, nullables, firsts), 53 | expectFirsts = { 54 | S: ['b', 'c'], 55 | A: ['b', 'ϵ'], 56 | B: ['c'], 57 | C: ['d'], 58 | D: ['e'] 59 | }, 60 | expectFollows = { 61 | S: ['$'], 62 | A: ['c'], 63 | B: ['d'], 64 | C: ['e'], 65 | D: ['$'] 66 | }; 67 | keys.forEach(function (key) { 68 | assert.deepEqual(expectFirsts[key], firsts[key]); 69 | }); 70 | assert.deepEqual(expectFollows, follows); 71 | }); 72 | 73 | }); 74 | }); 75 | -------------------------------------------------------------------------------- /test/test_syntax_left_factoring.js: -------------------------------------------------------------------------------- 1 | /*jslint node: true */ 2 | /*global describe, it */ 3 | 'use strict'; 4 | var assert = require('assert'); 5 | var syntax = require('../js/syntax'); 6 | 7 | describe('Syntax', function () { 8 | describe('#leftFactoring', function () { 9 | it('Example', function () { 10 | var actual = syntax.leftFactoring(syntax.parseGrammar('S -> i E t S | i E t S e S | a E -> b')), 11 | expected = { 12 | S: [ 13 | ['i', 'E', 't', 'S', 'S\''], 14 | [ 'a' ] 15 | ], 16 | E: [ 17 | ['b'] 18 | ], 19 | 'S\'': [ 20 | ['ϵ'], 21 | ['e', 'S'] 22 | ] 23 | }; 24 | assert.deepEqual(expected, actual); 25 | }); 26 | 27 | it('Example 4.2.1', function () { 28 | var actual = syntax.leftFactoring(syntax.parseGrammar('S -> S S + | S S * | a')), 29 | expected = { 30 | S: [ 31 | ['S', 'S', 'S\''], 32 | ['a'] 33 | ], 34 | 'S\'': [ 35 | ['+'], 36 | ['*'] 37 | ] 38 | }; 39 | assert.deepEqual(expected, actual); 40 | }); 41 | 42 | it('Example 4.2.2 (a)', function () { 43 | var actual = syntax.leftFactoring(syntax.parseGrammar('S -> 0 S 1 | 0 1')), 44 | expected = { 45 | S: [ 46 | ['0', 'S\''] 47 | ], 48 | 'S\'': [ 49 | ['S', '1'], 50 | ['1'] 51 | ] 52 | }; 53 | assert.deepEqual(expected, actual); 54 | }); 55 | 56 | it('Example 4.2.2 (b)', function () { 57 | var actual = syntax.leftFactoring(syntax.parseGrammar('S -> + S S | * S S | a')), 58 | expected = { 59 | S: [ 60 | ['+', 'S', 'S'], 61 | ['*', 'S', 'S'], 62 | ['a'] 63 | ] 64 | }; 65 | assert.deepEqual(expected, actual); 66 | }); 67 | 68 | it('Example 4.2.2 (c)', function () { 69 | var actual = syntax.leftFactoring(syntax.parseGrammar('S -> S ( S ) S | ϵ')), 70 | expected = { 71 | S: [ 72 | ['S', '(', 'S', ')', 'S'], 73 | ['ϵ'] 74 | ] 75 | }; 76 | assert.deepEqual(expected, actual); 77 | }); 78 | 79 | it('Example 4.2.2 (d)', function () { 80 | var actual = syntax.leftFactoring(syntax.parseGrammar('S -> S + S | S S | ( S ) | S * | a')), 81 | expected = { 82 | S: [ 83 | ['S', 'S\''], 84 | ['(', 'S', ')'], 85 | ['a'] 86 | ], 87 | 'S\'': [ 88 | ['+', 'S'], 89 | ['S'], 90 | ['*'] 91 | ] 92 | }; 93 | assert.deepEqual(expected, actual); 94 | }); 95 | 96 | it('Example 4.2.2 (e)', function () { 97 | var actual = syntax.leftFactoring(syntax.parseGrammar('S -> ( L ) | a L -> L , S | S')), 98 | expected = { 99 | S: [ 100 | ['(', 'L', ')'], 101 | ['a'] 102 | ], 103 | L: [ 104 | ['L', ',', 'S'], 105 | ['S'] 106 | ] 107 | }; 108 | assert.deepEqual(expected, actual); 109 | }); 110 | 111 | it('Example 4.2.2 (f)', function () { 112 | var actual = syntax.leftFactoring(syntax.parseGrammar('S -> a S b S | b S a S | ϵ')), 113 | expected = { 114 | S: [ 115 | ['a', 'S', 'b', 'S'], 116 | ['b', 'S', 'a', 'S'], 117 | ['ϵ'] 118 | ] 119 | }; 120 | assert.deepEqual(expected, actual); 121 | }); 122 | 123 | it('Example 4.2.2 (g)', function () { 124 | var actual = syntax.leftFactoring(syntax.parseGrammar( 125 | 'bexpr -> bexpr or bterm | bterm\n' + 126 | 'bterm -> bterm and bfactor | bfactor\n' + 127 | 'bfactor -> not bfactor | ( bexpr ) | true | false' 128 | )), 129 | expected = { 130 | bexpr: [ 131 | ['bexpr', 'or', 'bterm'], 132 | ['bterm'] 133 | ], 134 | bterm: [ 135 | ['bterm', 'and', 'bfactor'], 136 | ['bfactor'] 137 | ], 138 | bfactor: [ 139 | ['not', 'bfactor'], 140 | ['(', 'bexpr', ')'], 141 | ['true'], 142 | ['false'] 143 | ] 144 | }; 145 | assert.deepEqual(expected, actual); 146 | }); 147 | 148 | }); 149 | }); 150 | -------------------------------------------------------------------------------- /test/test_syntax_left_recursion.js: -------------------------------------------------------------------------------- 1 | /*jslint node: true */ 2 | /*global describe, it */ 3 | 'use strict'; 4 | var assert = require('assert'); 5 | var syntax = require('../js/syntax'); 6 | 7 | describe('Syntax', function () { 8 | describe('#eliminateLeftRecursion', function () { 9 | it('Example', function () { 10 | var actual = syntax.eliminateLeftRecursion(syntax.parseGrammar('S -> A a | b A -> A c | S d | ϵ')), 11 | expected = { 12 | S: [ 13 | ['A', 'a'], 14 | ['b'] 15 | ], 16 | A: [ 17 | ['b', 'd', "A'"], 18 | ["A'"] 19 | ], 20 | "A'": [ 21 | ['c', "A'"], 22 | ['a', 'd', "A'"], 23 | ['ϵ'] 24 | ] 25 | }; 26 | assert.deepEqual(expected, actual); 27 | }); 28 | 29 | it('Example 4.2.1', function () { 30 | var actual = syntax.eliminateLeftRecursion(syntax.parseGrammar('S -> S S + | S S * | a')), 31 | expected = { 32 | S: [ 33 | ['a', 'S\''] 34 | ], 35 | 'S\'': [ 36 | ['S', '+', 'S\''], 37 | ['S', '*', 'S\''], 38 | ['ϵ'] 39 | ] 40 | }; 41 | assert.deepEqual(expected, actual); 42 | }); 43 | 44 | it('Example 4.2.2 (a)', function () { 45 | var actual = syntax.eliminateLeftRecursion(syntax.parseGrammar('S -> 0 S 1 | 0 1')), 46 | expected = { 47 | S: [ 48 | ['0', 'S', '1'], 49 | ['0', '1'] 50 | ] 51 | }; 52 | assert.deepEqual(expected, actual); 53 | }); 54 | 55 | it('Example 4.2.2 (b)', function () { 56 | var actual = syntax.eliminateLeftRecursion(syntax.parseGrammar('S -> + S S | * S S | a')), 57 | expected = { 58 | S: [ 59 | ['+', 'S', 'S'], 60 | ['*', 'S', 'S'], 61 | ['a'] 62 | ] 63 | }; 64 | assert.deepEqual(expected, actual); 65 | }); 66 | 67 | it('Example 4.2.2 (c)', function () { 68 | var actual = syntax.eliminateLeftRecursion(syntax.parseGrammar('S -> S ( S ) S | ϵ')), 69 | expected = { 70 | S: [ 71 | ['S\''] 72 | ], 73 | 'S\'': [ 74 | ['(', 'S', ')', 'S', 'S\''], 75 | ['ϵ'] 76 | ] 77 | }; 78 | assert.deepEqual(expected, actual); 79 | }); 80 | 81 | it('Example 4.2.2 (d)', function () { 82 | var actual = syntax.eliminateLeftRecursion(syntax.parseGrammar('S -> S + S | S S | ( S ) | S * | a')), 83 | expected = { 84 | S: [ 85 | ['(', 'S', ')', 'S\''], 86 | ['a', 'S\''] 87 | ], 88 | 'S\'': [ 89 | ['+', 'S', 'S\''], 90 | ['S', 'S\''], 91 | ['*', 'S\''], 92 | ['ϵ'] 93 | ] 94 | }; 95 | assert.deepEqual(expected, actual); 96 | }); 97 | 98 | it('Example 4.2.2 (e)', function () { 99 | var actual = syntax.eliminateLeftRecursion(syntax.parseGrammar('S -> ( L ) | a L -> L , S | S')), 100 | expected = { 101 | S: [ 102 | ['(', 'L', ')'], 103 | ['a'] 104 | ], 105 | L: [ 106 | ['(', 'L', ')', 'L\''], 107 | ['a', 'L\''] 108 | ], 109 | 'L\'': [ 110 | [',', 'S', 'L\''], 111 | ['ϵ'] 112 | ] 113 | }; 114 | assert.deepEqual(expected, actual); 115 | }); 116 | 117 | it('Example 4.2.2 (f)', function () { 118 | var actual = syntax.eliminateLeftRecursion(syntax.parseGrammar('S -> a S b S | b S a S | ϵ')), 119 | expected = { 120 | S: [ 121 | ['a', 'S', 'b', 'S'], 122 | ['b', 'S', 'a', 'S'], 123 | ['ϵ'] 124 | ] 125 | }; 126 | assert.deepEqual(expected, actual); 127 | }); 128 | 129 | it('Example 4.2.2 (g)', function () { 130 | var actual = syntax.eliminateLeftRecursion(syntax.parseGrammar( 131 | 'bexpr -> bexpr or bterm | bterm\n' + 132 | 'bterm -> bterm and bfactor | bfactor\n' + 133 | 'bfactor -> not bfactor | ( bexpr ) | true | false' 134 | )), 135 | expected = { 136 | bexpr: [ 137 | ['bterm', 'bexpr\''] 138 | ], 139 | bterm: [ 140 | ['bfactor', 'bterm\''] 141 | ], 142 | bfactor: [ 143 | ['not', 'bfactor'], 144 | ['(', 'bexpr', ')'], 145 | ['true'], 146 | ['false'] 147 | ], 148 | 'bexpr\'': [ 149 | ['or', 'bterm', 'bexpr\''], 150 | ['ϵ'] 151 | ], 152 | 'bterm\'': [ 153 | ['and', 'bfactor', 'bterm\''], ['ϵ'] 154 | ] 155 | }; 156 | assert.deepEqual(expected, actual); 157 | }); 158 | 159 | }); 160 | }); 161 | -------------------------------------------------------------------------------- /test/test_syntax_parse_grammar.js: -------------------------------------------------------------------------------- 1 | /*jslint node: true */ 2 | /*global describe, it */ 3 | 'use strict'; 4 | var assert = require('assert'); 5 | var syntax = require('../js/syntax'); 6 | 7 | describe('Syntax', function () { 8 | describe('#parseGrammar', function () { 9 | it('Example 4.2.1', function () { 10 | var actual = syntax.parseGrammar('S -> S S + | S S * | a'), 11 | expected = { 12 | S: [ 13 | ['S', 'S', '+'], 14 | ['S', 'S', '*'], 15 | ['a'] 16 | ] 17 | }; 18 | assert.deepEqual(expected, actual); 19 | }); 20 | 21 | it('Example 4.2.2 (a)', function () { 22 | var actual = syntax.parseGrammar('S -> 0 S 1 | 0 1'), 23 | expected = { 24 | S: [ 25 | ['0', 'S', '1'], 26 | ['0', '1'] 27 | ] 28 | }; 29 | assert.deepEqual(expected, actual); 30 | }); 31 | 32 | it('Example 4.2.2 (b)', function () { 33 | var actual = syntax.parseGrammar('S -> + S S | * S S | a'), 34 | expected = { 35 | S: [ 36 | ['+', 'S', 'S'], 37 | ['*', 'S', 'S'], 38 | ['a'] 39 | ] 40 | }; 41 | assert.deepEqual(expected, actual); 42 | }); 43 | 44 | it('Example 4.2.2 (c)', function () { 45 | var actual = syntax.parseGrammar('S -> S ( S ) S | ϵ'), 46 | expected = { 47 | S: [ 48 | ['S', '(', 'S', ')', 'S'], 49 | ['ϵ'] 50 | ] 51 | }; 52 | assert.deepEqual(expected, actual); 53 | }); 54 | 55 | it('Example 4.2.2 (d)', function () { 56 | var actual = syntax.parseGrammar('S -> S + S | S S | ( S ) | S * | a'), 57 | expected = { 58 | S: [ 59 | ['S', '+', 'S'], 60 | ['S', 'S'], 61 | ['(', 'S', ')'], 62 | ['S', '*'], 63 | ['a'] 64 | ] 65 | }; 66 | assert.deepEqual(expected, actual); 67 | }); 68 | 69 | it('Example 4.2.2 (e)', function () { 70 | var actual = syntax.parseGrammar('S -> ( L ) | a L -> L , S | S'), 71 | expected = { 72 | S: [ 73 | ['(', 'L', ')'], 74 | ['a'] 75 | ], 76 | L: [ 77 | ['L', ',', 'S'], 78 | ['S'] 79 | ] 80 | }; 81 | assert.deepEqual(expected, actual); 82 | }); 83 | 84 | it('Example 4.2.2 (f)', function () { 85 | var actual = syntax.parseGrammar('S -> a S b S | b S a S | ϵ'), 86 | expected = { 87 | S: [ 88 | ['a', 'S', 'b', 'S'], 89 | ['b', 'S', 'a', 'S'], 90 | ['ϵ'] 91 | ] 92 | }; 93 | assert.deepEqual(expected, actual); 94 | }); 95 | 96 | it('Example 4.2.2 (g)', function () { 97 | var actual = syntax.parseGrammar( 98 | 'bexpr -> bexpr or bterm | bterm\n' + 99 | 'bterm -> bterm and bfactor | bfactor\n' + 100 | 'bfactor -> not bfactor | ( bexpr ) | true | false' 101 | ), 102 | expected = { 103 | bexpr: [ 104 | ['bexpr', 'or', 'bterm'], 105 | ['bterm'] 106 | ], 107 | bterm: [ 108 | ['bterm', 'and', 'bfactor'], 109 | ['bfactor'] 110 | ], 111 | bfactor: [ 112 | ['not', 'bfactor'], 113 | ['(', 'bexpr', ')'], 114 | ['true'], 115 | ['false'] 116 | ] 117 | }; 118 | assert.deepEqual(expected, actual); 119 | }); 120 | 121 | }); 122 | }); 123 | -------------------------------------------------------------------------------- /test/test_syntax_table_ll1.js: -------------------------------------------------------------------------------- 1 | /*jslint node: true */ 2 | /*global describe, it */ 3 | 'use strict'; 4 | var assert = require('assert'); 5 | var syntax = require('../js/syntax'); 6 | 7 | describe('Syntax', function () { 8 | describe('#LL(1) Parsing Table', function () { 9 | it('Example', function () { 10 | var grammar = syntax.parseGrammar( 11 | "E -> T E'\n" + 12 | "T -> F T'\n" + 13 | "E' -> + T E' | ϵ\n" + 14 | "T' -> * F T' | ϵ\n" + 15 | "F -> ( E ) | id\n" 16 | ), 17 | actual = syntax.constructLL1ParsingTable(grammar), 18 | expect = { 19 | 'E': { 20 | '(': [ 21 | ['T', 'E\''] 22 | ], 23 | 'id': [ 24 | ['T', 'E\''] 25 | ] 26 | }, 27 | 'E\'': { 28 | '$': [ 29 | ['ϵ'] 30 | ], 31 | ')': [ 32 | ['ϵ'] 33 | ], 34 | '+': [ 35 | ['+', 'T', 'E\''] 36 | ] 37 | }, 38 | 'F': { 39 | '(': [ 40 | ['(', 'E', ')'] 41 | ], 42 | 'id': [ 43 | ['id'] 44 | ] 45 | }, 46 | 'T': { 47 | '(': [ 48 | ['F', 'T\''] 49 | ], 50 | 'id': [ 51 | ['F', 'T\''] 52 | ], 53 | }, 54 | 'T\'': { 55 | '$': [ 56 | ['ϵ'] 57 | ], 58 | ')': [ 59 | ['ϵ'] 60 | ], 61 | '*': [ 62 | ['*', 'F', 'T\''] 63 | ], 64 | '+': [ 65 | ['ϵ'] 66 | ], 67 | } 68 | }; 69 | assert.deepEqual(expect, actual); 70 | }); 71 | 72 | it('Example', function () { 73 | var grammar = syntax.parseGrammar( 74 | "S -> i E t S S' | a\n" + 75 | "S' -> e S | ϵ\n" + 76 | "E -> b\n" 77 | ), 78 | actual = syntax.constructLL1ParsingTable(grammar), 79 | expect = { 80 | 'E': { 81 | 'b': [ 82 | ['b'] 83 | ] 84 | }, 85 | 'S': { 86 | 'a': [ 87 | ['a'] 88 | ], 89 | 'i': [ 90 | ['i', 'E', 't', 'S', 'S\''] 91 | ] 92 | }, 93 | 'S\'': { 94 | '$': [ 95 | ['ϵ'] 96 | ], 97 | 'e': [ 98 | ['e', 'S'], 99 | ['ϵ'] 100 | ] 101 | } 102 | }; 103 | assert.deepEqual(expect, actual); 104 | }); 105 | 106 | }); 107 | }); 108 | -------------------------------------------------------------------------------- /url_encode.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | URL Encode/Decode 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 68 | 69 |
70 | 71 |
72 | 73 |

Source:

74 |
75 |
76 |
77 | 78 | 79 | 80 |
81 |
82 | 83 | 84 | 85 | 86 | 87 | 88 |
89 |
90 | 91 |

Target:

92 |
93 |
94 |
95 | 96 | 97 | 98 |
99 | 100 | 101 |
102 | 103 | 104 | 105 | 106 | 107 | 108 | 113 | 114 | 115 | 124 | 125 | 126 | 127 | --------------------------------------------------------------------------------