Initial commit
This commit is contained in:
commit
b7defdf5d8
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
**/.DS_Store
|
||||||
|
**/main.js
|
||||||
|
**/node_modules
|
190
Home/.stylelintrc
Normal file
190
Home/.stylelintrc
Normal file
@ -0,0 +1,190 @@
|
|||||||
|
{
|
||||||
|
"extends": "/usr/local/lib/node_modules/stylelint-config-standard",
|
||||||
|
"plugins": [
|
||||||
|
"/usr/local/lib/node_modules/stylelint-order"
|
||||||
|
],
|
||||||
|
"rules": {
|
||||||
|
"at-rule-no-vendor-prefix": true,
|
||||||
|
"media-feature-name-no-vendor-prefix": true,
|
||||||
|
"property-no-vendor-prefix": true,
|
||||||
|
"selector-no-vendor-prefix": true,
|
||||||
|
"value-no-vendor-prefix": true,
|
||||||
|
"order/properties-order": [
|
||||||
|
[
|
||||||
|
"font",
|
||||||
|
"font-family",
|
||||||
|
"font-size",
|
||||||
|
"font-weight",
|
||||||
|
"font-style",
|
||||||
|
"font-variant",
|
||||||
|
"font-size-adjust",
|
||||||
|
"font-stretch",
|
||||||
|
"font-effect",
|
||||||
|
"font-emphasize",
|
||||||
|
"font-emphasize-position",
|
||||||
|
"font-emphasize-style",
|
||||||
|
"font-smooth",
|
||||||
|
"line-height",
|
||||||
|
"position",
|
||||||
|
"z-index",
|
||||||
|
"top",
|
||||||
|
"right",
|
||||||
|
"bottom",
|
||||||
|
"left",
|
||||||
|
"display",
|
||||||
|
"visibility",
|
||||||
|
"float",
|
||||||
|
"clear",
|
||||||
|
"overflow",
|
||||||
|
"overflow-x",
|
||||||
|
"overflow-y",
|
||||||
|
"clip",
|
||||||
|
"zoom",
|
||||||
|
"align-content",
|
||||||
|
"align-items",
|
||||||
|
"align-self",
|
||||||
|
"flex",
|
||||||
|
"flex-flow",
|
||||||
|
"flex-basis",
|
||||||
|
"flex-direction",
|
||||||
|
"flex-grow",
|
||||||
|
"flex-shrink",
|
||||||
|
"flex-wrap",
|
||||||
|
"justify-content",
|
||||||
|
"order",
|
||||||
|
"box-sizing",
|
||||||
|
"width",
|
||||||
|
"min-width",
|
||||||
|
"max-width",
|
||||||
|
"height",
|
||||||
|
"min-height",
|
||||||
|
"max-height",
|
||||||
|
"margin",
|
||||||
|
"margin-top",
|
||||||
|
"margin-right",
|
||||||
|
"margin-bottom",
|
||||||
|
"margin-left",
|
||||||
|
"padding",
|
||||||
|
"padding-top",
|
||||||
|
"padding-right",
|
||||||
|
"padding-bottom",
|
||||||
|
"padding-left",
|
||||||
|
"table-layout",
|
||||||
|
"empty-cells",
|
||||||
|
"caption-side",
|
||||||
|
"border-spacing",
|
||||||
|
"border-collapse",
|
||||||
|
"list-style",
|
||||||
|
"list-style-position",
|
||||||
|
"list-style-type",
|
||||||
|
"list-style-image",
|
||||||
|
"content",
|
||||||
|
"quotes",
|
||||||
|
"counter-reset",
|
||||||
|
"counter-increment",
|
||||||
|
"resize",
|
||||||
|
"cursor",
|
||||||
|
"user-select",
|
||||||
|
"nav-index",
|
||||||
|
"nav-up",
|
||||||
|
"nav-right",
|
||||||
|
"nav-down",
|
||||||
|
"nav-left",
|
||||||
|
"transition",
|
||||||
|
"transition-delay",
|
||||||
|
"transition-timing-function",
|
||||||
|
"transition-duration",
|
||||||
|
"transition-property",
|
||||||
|
"transform",
|
||||||
|
"transform-origin",
|
||||||
|
"animation",
|
||||||
|
"animation-name",
|
||||||
|
"animation-duration",
|
||||||
|
"animation-play-state",
|
||||||
|
"animation-timing-function",
|
||||||
|
"animation-delay",
|
||||||
|
"animation-iteration-count",
|
||||||
|
"animation-direction",
|
||||||
|
"text-align",
|
||||||
|
"text-align-last",
|
||||||
|
"vertical-align",
|
||||||
|
"white-space",
|
||||||
|
"text-decoration",
|
||||||
|
"text-emphasis",
|
||||||
|
"text-emphasis-color",
|
||||||
|
"text-emphasis-style",
|
||||||
|
"text-emphasis-position",
|
||||||
|
"text-indent",
|
||||||
|
"text-justify",
|
||||||
|
"letter-spacing",
|
||||||
|
"word-spacing",
|
||||||
|
"text-outline",
|
||||||
|
"text-transform",
|
||||||
|
"text-wrap",
|
||||||
|
"text-overflow",
|
||||||
|
"text-overflow-ellipsis",
|
||||||
|
"text-overflow-mode",
|
||||||
|
"word-wrap",
|
||||||
|
"word-break",
|
||||||
|
"tab-size",
|
||||||
|
"hyphens",
|
||||||
|
"pointer-events",
|
||||||
|
"opacity",
|
||||||
|
"color",
|
||||||
|
"border",
|
||||||
|
"border-width",
|
||||||
|
"border-style",
|
||||||
|
"border-color",
|
||||||
|
"border-top",
|
||||||
|
"border-top-width",
|
||||||
|
"border-top-style",
|
||||||
|
"border-top-color",
|
||||||
|
"border-right",
|
||||||
|
"border-right-width",
|
||||||
|
"border-right-style",
|
||||||
|
"border-right-color",
|
||||||
|
"border-bottom",
|
||||||
|
"border-bottom-width",
|
||||||
|
"border-bottom-style",
|
||||||
|
"border-bottom-color",
|
||||||
|
"border-left",
|
||||||
|
"border-left-width",
|
||||||
|
"border-left-style",
|
||||||
|
"border-left-color",
|
||||||
|
"border-radius",
|
||||||
|
"border-top-left-radius",
|
||||||
|
"border-top-right-radius",
|
||||||
|
"border-bottom-right-radius",
|
||||||
|
"border-bottom-left-radius",
|
||||||
|
"border-image",
|
||||||
|
"border-image-source",
|
||||||
|
"border-image-slice",
|
||||||
|
"border-image-width",
|
||||||
|
"border-image-outset",
|
||||||
|
"border-image-repeat",
|
||||||
|
"outline",
|
||||||
|
"outline-width",
|
||||||
|
"outline-style",
|
||||||
|
"outline-color",
|
||||||
|
"outline-offset",
|
||||||
|
"background",
|
||||||
|
"background-color",
|
||||||
|
"background-image",
|
||||||
|
"background-repeat",
|
||||||
|
"background-attachment",
|
||||||
|
"background-position",
|
||||||
|
"background-position-x",
|
||||||
|
"background-position-y",
|
||||||
|
"background-clip",
|
||||||
|
"background-origin",
|
||||||
|
"background-size",
|
||||||
|
"box-decoration-break",
|
||||||
|
"box-shadow",
|
||||||
|
"text-shadow"
|
||||||
|
],
|
||||||
|
{
|
||||||
|
"unspecified": "bottomAlphabetical"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
3
Home/Compiler/.babelrc
Normal file
3
Home/Compiler/.babelrc
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"presets": ["@babel/preset-env"]
|
||||||
|
}
|
1
Home/Compiler/.npmrc
Normal file
1
Home/Compiler/.npmrc
Normal file
@ -0,0 +1 @@
|
|||||||
|
package-lock=false
|
190
Home/Compiler/.stylelintrc
Normal file
190
Home/Compiler/.stylelintrc
Normal file
@ -0,0 +1,190 @@
|
|||||||
|
{
|
||||||
|
"extends": "/usr/local/lib/node_modules/stylelint-config-standard",
|
||||||
|
"plugins": [
|
||||||
|
"/usr/local/lib/node_modules/stylelint-order"
|
||||||
|
],
|
||||||
|
"rules": {
|
||||||
|
"at-rule-no-vendor-prefix": true,
|
||||||
|
"media-feature-name-no-vendor-prefix": true,
|
||||||
|
"property-no-vendor-prefix": true,
|
||||||
|
"selector-no-vendor-prefix": true,
|
||||||
|
"value-no-vendor-prefix": true,
|
||||||
|
"order/properties-order": [
|
||||||
|
[
|
||||||
|
"font",
|
||||||
|
"font-family",
|
||||||
|
"font-size",
|
||||||
|
"font-weight",
|
||||||
|
"font-style",
|
||||||
|
"font-variant",
|
||||||
|
"font-size-adjust",
|
||||||
|
"font-stretch",
|
||||||
|
"font-effect",
|
||||||
|
"font-emphasize",
|
||||||
|
"font-emphasize-position",
|
||||||
|
"font-emphasize-style",
|
||||||
|
"font-smooth",
|
||||||
|
"line-height",
|
||||||
|
"position",
|
||||||
|
"z-index",
|
||||||
|
"top",
|
||||||
|
"right",
|
||||||
|
"bottom",
|
||||||
|
"left",
|
||||||
|
"display",
|
||||||
|
"visibility",
|
||||||
|
"float",
|
||||||
|
"clear",
|
||||||
|
"overflow",
|
||||||
|
"overflow-x",
|
||||||
|
"overflow-y",
|
||||||
|
"clip",
|
||||||
|
"zoom",
|
||||||
|
"align-content",
|
||||||
|
"align-items",
|
||||||
|
"align-self",
|
||||||
|
"flex",
|
||||||
|
"flex-flow",
|
||||||
|
"flex-basis",
|
||||||
|
"flex-direction",
|
||||||
|
"flex-grow",
|
||||||
|
"flex-shrink",
|
||||||
|
"flex-wrap",
|
||||||
|
"justify-content",
|
||||||
|
"order",
|
||||||
|
"box-sizing",
|
||||||
|
"width",
|
||||||
|
"min-width",
|
||||||
|
"max-width",
|
||||||
|
"height",
|
||||||
|
"min-height",
|
||||||
|
"max-height",
|
||||||
|
"margin",
|
||||||
|
"margin-top",
|
||||||
|
"margin-right",
|
||||||
|
"margin-bottom",
|
||||||
|
"margin-left",
|
||||||
|
"padding",
|
||||||
|
"padding-top",
|
||||||
|
"padding-right",
|
||||||
|
"padding-bottom",
|
||||||
|
"padding-left",
|
||||||
|
"table-layout",
|
||||||
|
"empty-cells",
|
||||||
|
"caption-side",
|
||||||
|
"border-spacing",
|
||||||
|
"border-collapse",
|
||||||
|
"list-style",
|
||||||
|
"list-style-position",
|
||||||
|
"list-style-type",
|
||||||
|
"list-style-image",
|
||||||
|
"content",
|
||||||
|
"quotes",
|
||||||
|
"counter-reset",
|
||||||
|
"counter-increment",
|
||||||
|
"resize",
|
||||||
|
"cursor",
|
||||||
|
"user-select",
|
||||||
|
"nav-index",
|
||||||
|
"nav-up",
|
||||||
|
"nav-right",
|
||||||
|
"nav-down",
|
||||||
|
"nav-left",
|
||||||
|
"transition",
|
||||||
|
"transition-delay",
|
||||||
|
"transition-timing-function",
|
||||||
|
"transition-duration",
|
||||||
|
"transition-property",
|
||||||
|
"transform",
|
||||||
|
"transform-origin",
|
||||||
|
"animation",
|
||||||
|
"animation-name",
|
||||||
|
"animation-duration",
|
||||||
|
"animation-play-state",
|
||||||
|
"animation-timing-function",
|
||||||
|
"animation-delay",
|
||||||
|
"animation-iteration-count",
|
||||||
|
"animation-direction",
|
||||||
|
"text-align",
|
||||||
|
"text-align-last",
|
||||||
|
"vertical-align",
|
||||||
|
"white-space",
|
||||||
|
"text-decoration",
|
||||||
|
"text-emphasis",
|
||||||
|
"text-emphasis-color",
|
||||||
|
"text-emphasis-style",
|
||||||
|
"text-emphasis-position",
|
||||||
|
"text-indent",
|
||||||
|
"text-justify",
|
||||||
|
"letter-spacing",
|
||||||
|
"word-spacing",
|
||||||
|
"text-outline",
|
||||||
|
"text-transform",
|
||||||
|
"text-wrap",
|
||||||
|
"text-overflow",
|
||||||
|
"text-overflow-ellipsis",
|
||||||
|
"text-overflow-mode",
|
||||||
|
"word-wrap",
|
||||||
|
"word-break",
|
||||||
|
"tab-size",
|
||||||
|
"hyphens",
|
||||||
|
"pointer-events",
|
||||||
|
"opacity",
|
||||||
|
"color",
|
||||||
|
"border",
|
||||||
|
"border-width",
|
||||||
|
"border-style",
|
||||||
|
"border-color",
|
||||||
|
"border-top",
|
||||||
|
"border-top-width",
|
||||||
|
"border-top-style",
|
||||||
|
"border-top-color",
|
||||||
|
"border-right",
|
||||||
|
"border-right-width",
|
||||||
|
"border-right-style",
|
||||||
|
"border-right-color",
|
||||||
|
"border-bottom",
|
||||||
|
"border-bottom-width",
|
||||||
|
"border-bottom-style",
|
||||||
|
"border-bottom-color",
|
||||||
|
"border-left",
|
||||||
|
"border-left-width",
|
||||||
|
"border-left-style",
|
||||||
|
"border-left-color",
|
||||||
|
"border-radius",
|
||||||
|
"border-top-left-radius",
|
||||||
|
"border-top-right-radius",
|
||||||
|
"border-bottom-right-radius",
|
||||||
|
"border-bottom-left-radius",
|
||||||
|
"border-image",
|
||||||
|
"border-image-source",
|
||||||
|
"border-image-slice",
|
||||||
|
"border-image-width",
|
||||||
|
"border-image-outset",
|
||||||
|
"border-image-repeat",
|
||||||
|
"outline",
|
||||||
|
"outline-width",
|
||||||
|
"outline-style",
|
||||||
|
"outline-color",
|
||||||
|
"outline-offset",
|
||||||
|
"background",
|
||||||
|
"background-color",
|
||||||
|
"background-image",
|
||||||
|
"background-repeat",
|
||||||
|
"background-attachment",
|
||||||
|
"background-position",
|
||||||
|
"background-position-x",
|
||||||
|
"background-position-y",
|
||||||
|
"background-clip",
|
||||||
|
"background-origin",
|
||||||
|
"background-size",
|
||||||
|
"box-decoration-break",
|
||||||
|
"box-shadow",
|
||||||
|
"text-shadow"
|
||||||
|
],
|
||||||
|
{
|
||||||
|
"unspecified": "bottomAlphabetical"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
24
Home/Compiler/LICENSE
Normal file
24
Home/Compiler/LICENSE
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2011-2019 Twitter, Inc.
|
||||||
|
Copyright (c) 2011-2019 The Bootstrap Authors
|
||||||
|
Copyright (C) 2017 by Marijn Haverbeke <marijnh@gmail.com> and others
|
||||||
|
Copyright (c) 2013-present, Yuxi (Evan) You
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
22
Home/Compiler/README.md
Normal file
22
Home/Compiler/README.md
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
# Requirements
|
||||||
|
|
||||||
|
- node.js
|
||||||
|
- npm
|
||||||
|
|
||||||
|
# Install Dependencies
|
||||||
|
|
||||||
|
```
|
||||||
|
$ npm install
|
||||||
|
```
|
||||||
|
|
||||||
|
# Generate main.js
|
||||||
|
|
||||||
|
```
|
||||||
|
$ npm run build
|
||||||
|
```
|
||||||
|
|
||||||
|
# Watch for changes
|
||||||
|
|
||||||
|
```
|
||||||
|
$ npm run watch
|
||||||
|
```
|
75
Home/Compiler/index.html
Normal file
75
Home/Compiler/index.html
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Assignment</title>
|
||||||
|
<link rel="stylesheet" href="lib/bootstrap.min.css">
|
||||||
|
<link rel="stylesheet" href="lib/codemirror.min.css">
|
||||||
|
<link rel="stylesheet" href="main.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="root" class="container">
|
||||||
|
<h1>Lexical, Syntax & Semantic Analysis</h1>
|
||||||
|
<dl class="row mt-5">
|
||||||
|
<dt class="col-sm-2">Requirements: </dt>
|
||||||
|
<dd class="col-sm-10">
|
||||||
|
<pre>
|
||||||
|
# 保留字或運算子:begin, for, end, if, then, else, while, int
|
||||||
|
# 運算子:+, -, *, /, =
|
||||||
|
# 判斷子:<, >, <=, >=, ==, and, or
|
||||||
|
# 若有詞法或語法錯誤,請印出並說明
|
||||||
|
# 請印出所有變數最後的狀態
|
||||||
|
# 自定義文法,使得以下範例成立:
|
||||||
|
|
||||||
|
begin
|
||||||
|
int x=0, zzz=5;
|
||||||
|
int i, j=1;
|
||||||
|
# 進行迴圈
|
||||||
|
for, i=1, i<=50, j; # j爲i每次遞增的值
|
||||||
|
x=x+1;
|
||||||
|
end
|
||||||
|
if ((x>5) and (j<=8)) then
|
||||||
|
x=1;
|
||||||
|
else
|
||||||
|
for, i=1, i<=50, j+1;
|
||||||
|
x=x+1;
|
||||||
|
end
|
||||||
|
while (i<11)
|
||||||
|
yy=x;
|
||||||
|
i=i+1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
</pre>
|
||||||
|
</dd>
|
||||||
|
<dt class="col-sm-2">Source Code: </dt>
|
||||||
|
<dd class="col-sm-10">
|
||||||
|
<div class="custom-file">
|
||||||
|
<input type="file" id="file" class="custom-file-input" @change="fileHandler">
|
||||||
|
<label class="custom-file-label" for="file">{{ file ? file.name : 'Choose file' }}</label>
|
||||||
|
<button type="button" class="btn btn-secondary" @click="fileHandler">Reload</button>
|
||||||
|
</div>
|
||||||
|
<div id="editor" class="editor"></div>
|
||||||
|
</dd>
|
||||||
|
<dt class="col-sm-2"></dt>
|
||||||
|
<dd class="col-sm-10">
|
||||||
|
<button type="button" class="btn btn-info" @click="lexer">Lex</button>
|
||||||
|
<button type="button" class="btn btn-info" @click="parser">Parse</button>
|
||||||
|
<button type="button" class="btn btn-primary" @click="run">Run</button>
|
||||||
|
<button type="button" class="btn btn-secondary" @click="reset">Clear</button>
|
||||||
|
</dd>
|
||||||
|
<hr>
|
||||||
|
<dt class="col-sm-2">Console: </dt>
|
||||||
|
<dd class="col-sm-10">
|
||||||
|
<pre class="error" v-if="error" v-text="error"></pre>
|
||||||
|
<pre v-if="!error && ids.length" v-for="(v, i) in ids">{{ v }}: {{ vars[i] }}</pre>
|
||||||
|
<p v-if="!error && lex.length" v-for="(l, i) in lex">{{ l }}</p>
|
||||||
|
<pre v-if="!error && json" v-text="json"></pre>
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
</div>
|
||||||
|
<script src="lib/codemirror.min.js"></script>
|
||||||
|
<script src="lib/vue-2.6.0.min.js"></script>
|
||||||
|
<script src="main.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
7
Home/Compiler/lib/bootstrap.min.css
vendored
Normal file
7
Home/Compiler/lib/bootstrap.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
8
Home/Compiler/lib/codemirror.min.css
vendored
Normal file
8
Home/Compiler/lib/codemirror.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
8
Home/Compiler/lib/codemirror.min.js
vendored
Normal file
8
Home/Compiler/lib/codemirror.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
6
Home/Compiler/lib/vue-2.6.0.min.js
vendored
Normal file
6
Home/Compiler/lib/vue-2.6.0.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
30
Home/Compiler/main.css
Normal file
30
Home/Compiler/main.css
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
h1 {
|
||||||
|
margin-top: 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
font-family: "Menlo", "Consolas", monospace;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre.error {
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-file {
|
||||||
|
width: 250px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-file button {
|
||||||
|
position: relative;
|
||||||
|
top: -38px;
|
||||||
|
left: 255px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.editor {
|
||||||
|
margin: 20px 0;
|
||||||
|
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
|
||||||
|
}
|
20
Home/Compiler/package.json
Normal file
20
Home/Compiler/package.json
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"name": "Compiler",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "",
|
||||||
|
"main": "main.js",
|
||||||
|
"scripts": {
|
||||||
|
"build": "webpack",
|
||||||
|
"watch": "npm run build -- --watch"
|
||||||
|
},
|
||||||
|
"keywords": [],
|
||||||
|
"author": "",
|
||||||
|
"license": "ISC",
|
||||||
|
"devDependencies": {
|
||||||
|
"@babel/core": "^7.7.2",
|
||||||
|
"@babel/preset-env": "^7.7.1",
|
||||||
|
"babel-loader": "^8.0.6",
|
||||||
|
"webpack": "^4.41.2",
|
||||||
|
"webpack-cli": "^3.3.10"
|
||||||
|
}
|
||||||
|
}
|
6
Home/Compiler/sandbox.html
Normal file
6
Home/Compiler/sandbox.html
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<head>
|
||||||
|
<title>sandbox</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
</body>
|
571
Home/Compiler/src/main.dev.js
Normal file
571
Home/Compiler/src/main.dev.js
Normal file
@ -0,0 +1,571 @@
|
|||||||
|
/* global Vue FileReader CodeMirror */
|
||||||
|
Vue.config.devtools = true
|
||||||
|
|
||||||
|
window.app = new Vue({
|
||||||
|
el: '#root',
|
||||||
|
data: {
|
||||||
|
ast: {},
|
||||||
|
editor: {},
|
||||||
|
error: '',
|
||||||
|
fileReader: new FileReader(),
|
||||||
|
file: '',
|
||||||
|
ids: [],
|
||||||
|
js: '',
|
||||||
|
json: '',
|
||||||
|
lex: [],
|
||||||
|
vars: [] // the value of ids
|
||||||
|
},
|
||||||
|
mounted () {
|
||||||
|
this.editor = CodeMirror(document.querySelector('#editor'), {
|
||||||
|
lineNumbers: true,
|
||||||
|
tabSize: 2,
|
||||||
|
extraKeys: {
|
||||||
|
Tab: cm => {
|
||||||
|
const spaces = Array(cm.getOption('indentUnit') + 1).join(' ')
|
||||||
|
cm.replaceSelection(spaces)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
this.fileReader.onload = e => {
|
||||||
|
this.editor.setValue(this.fileReader.result)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
fileHandler () {
|
||||||
|
const file = document.querySelector('#file').files[0]
|
||||||
|
if (file) this.file = file
|
||||||
|
this.fileReader.readAsText(this.file)
|
||||||
|
},
|
||||||
|
reset () {
|
||||||
|
this.error = ''
|
||||||
|
this.ids = []
|
||||||
|
this.vars = []
|
||||||
|
this.lex = []
|
||||||
|
this.json = ''
|
||||||
|
},
|
||||||
|
run () {
|
||||||
|
try {
|
||||||
|
this.reset()
|
||||||
|
this.ast = parse(TokenStream(InputStream(this.editor.getValue())))
|
||||||
|
this.js = '(function () { "use strict"; try { ' + makeJS(this.ast)
|
||||||
|
this.ids = [...new Set(this.ids)]
|
||||||
|
this.js +=
|
||||||
|
' parent.app.vars = [' +
|
||||||
|
this.ids.join(', ') +
|
||||||
|
']; } catch (e) { parent.app.error = "Runtime Error: " + e.message; }}());'
|
||||||
|
// recreate an iframe sandbox if it already exist
|
||||||
|
// , then run the transpiled js in it
|
||||||
|
const sb = document.querySelector('#sandbox')
|
||||||
|
if (sb) sb.remove()
|
||||||
|
const iframe = document.createElement('iframe')
|
||||||
|
iframe.id = 'sandbox'
|
||||||
|
iframe.style.display = 'none'
|
||||||
|
iframe.src = 'sandbox.html'
|
||||||
|
document.body.appendChild(iframe)
|
||||||
|
const script = document.createElement('script')
|
||||||
|
script.textContent = this.js
|
||||||
|
document
|
||||||
|
.querySelector('#sandbox')
|
||||||
|
.contentDocument.body.appendChild(script)
|
||||||
|
} catch (e) {
|
||||||
|
this.error = e.message
|
||||||
|
}
|
||||||
|
},
|
||||||
|
lexer () {
|
||||||
|
try {
|
||||||
|
this.reset()
|
||||||
|
const tokens = TokenStream(InputStream(this.editor.getValue()))
|
||||||
|
while (!tokens.eof()) {
|
||||||
|
this.lex.push(tokens.next())
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
this.error = e.message
|
||||||
|
}
|
||||||
|
},
|
||||||
|
parser () {
|
||||||
|
try {
|
||||||
|
this.reset()
|
||||||
|
this.ast = parse(TokenStream(InputStream(this.editor.getValue())))
|
||||||
|
this.json = JSON.stringify(this.ast, null, 2)
|
||||||
|
} catch (e) {
|
||||||
|
this.error = e.message
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
function InputStream (input) {
|
||||||
|
let pos = 0
|
||||||
|
let line = 1
|
||||||
|
let col = 0
|
||||||
|
return {
|
||||||
|
next: next,
|
||||||
|
peek: peek,
|
||||||
|
eof: eof,
|
||||||
|
croak: croak
|
||||||
|
}
|
||||||
|
function next () {
|
||||||
|
const ch = input.charAt(pos++)
|
||||||
|
if (ch === '\n') {
|
||||||
|
line++
|
||||||
|
col = 0
|
||||||
|
} else col++
|
||||||
|
return ch
|
||||||
|
}
|
||||||
|
function peek () {
|
||||||
|
return input.charAt(pos)
|
||||||
|
}
|
||||||
|
function eof () {
|
||||||
|
return peek() === ''
|
||||||
|
}
|
||||||
|
function croak (msg, type = 'Syntax') {
|
||||||
|
throw new Error(type + ' Error: ' + msg + ' (' + line + ':' + col + ')')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function TokenStream (input) {
|
||||||
|
let current = null
|
||||||
|
const reserved =
|
||||||
|
' abstract arguments boolean break byte case catch char class const continue' +
|
||||||
|
' debugger default delete do double else enum eval export extends false final' +
|
||||||
|
' finally float for function goto if implements import in instanceof int' +
|
||||||
|
' interface let long native new null package private protected public return' +
|
||||||
|
' short static super switch synchronized this throw throws transient true try' +
|
||||||
|
' typeof var void volatile while with yield '
|
||||||
|
const keywords = ' begin for end if then else while int '
|
||||||
|
const ops = ' + - * / = == != > < >= <= and or '
|
||||||
|
return {
|
||||||
|
next: next,
|
||||||
|
peek: peek,
|
||||||
|
eof: eof,
|
||||||
|
croak: input.croak
|
||||||
|
}
|
||||||
|
function isKeyword (x) {
|
||||||
|
return keywords.indexOf(' ' + x + ' ') >= 0
|
||||||
|
}
|
||||||
|
function isReservedWord (x) {
|
||||||
|
return reserved.indexOf(' ' + x + ' ') >= 0
|
||||||
|
}
|
||||||
|
function isDigit (ch) {
|
||||||
|
return /[0-9]/i.test(ch)
|
||||||
|
}
|
||||||
|
function isIdStart (ch) {
|
||||||
|
return /[a-z_]/i.test(ch)
|
||||||
|
}
|
||||||
|
function isId (ch) {
|
||||||
|
return isIdStart(ch) || '_0123456789'.indexOf(ch) >= 0
|
||||||
|
}
|
||||||
|
function isOpChar (ch, prev, prev2) {
|
||||||
|
if (!prev) return '+-*/=!<>'.indexOf(ch) >= 0
|
||||||
|
else if (
|
||||||
|
(prev === '=' && !prev2) ||
|
||||||
|
prev === '!' ||
|
||||||
|
prev === '<' ||
|
||||||
|
prev === '>'
|
||||||
|
) {
|
||||||
|
return ch === '='
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
function isOp (x) {
|
||||||
|
return ops.indexOf(' ' + x + ' ') >= 0
|
||||||
|
}
|
||||||
|
function isPunc (ch) {
|
||||||
|
return ',;()'.indexOf(ch) >= 0
|
||||||
|
}
|
||||||
|
function isWhitespace (ch) {
|
||||||
|
return ' \t\n'.indexOf(ch) >= 0
|
||||||
|
}
|
||||||
|
function readWhile (predicate) {
|
||||||
|
let str = ''
|
||||||
|
while (
|
||||||
|
!input.eof() &&
|
||||||
|
predicate(input.peek(), str[str.length - 1], str[str.length - 2])
|
||||||
|
) {
|
||||||
|
str += input.next()
|
||||||
|
}
|
||||||
|
return str
|
||||||
|
}
|
||||||
|
function readNumber () {
|
||||||
|
const number = readWhile(isDigit)
|
||||||
|
return { type: 'num', value: parseInt(number, 10) }
|
||||||
|
}
|
||||||
|
function readIdent () {
|
||||||
|
const id = readWhile(isId)
|
||||||
|
if (!isKeyword(id) && isReservedWord(id)) {
|
||||||
|
input.croak('Variable name "' + id + '" is not allowed', 'Lexical')
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
type: isKeyword(id) ? 'kw' : isOp(id) ? 'op' : 'var',
|
||||||
|
value: id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function readOp () {
|
||||||
|
const id = readWhile(isOpChar)
|
||||||
|
return {
|
||||||
|
type: isOp(id) ? 'op' : input.croak('Unknown symbol: ' + id, 'Lexical'),
|
||||||
|
value: id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function skipComment () {
|
||||||
|
readWhile(function (ch) {
|
||||||
|
return ch !== '\n'
|
||||||
|
})
|
||||||
|
input.next()
|
||||||
|
}
|
||||||
|
function readNext () {
|
||||||
|
readWhile(isWhitespace)
|
||||||
|
if (input.eof()) return null
|
||||||
|
const ch = input.peek()
|
||||||
|
if (ch === '#') {
|
||||||
|
skipComment()
|
||||||
|
return readNext()
|
||||||
|
}
|
||||||
|
if (isDigit(ch)) return readNumber()
|
||||||
|
if (isPunc(ch)) {
|
||||||
|
return {
|
||||||
|
type: 'punc',
|
||||||
|
value: input.next()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isOpChar(ch)) return readOp()
|
||||||
|
if (isIdStart(ch)) return readIdent()
|
||||||
|
input.croak('Invalid symbol: ' + ch, 'Lexical')
|
||||||
|
}
|
||||||
|
function peek () {
|
||||||
|
return current || (current = readNext())
|
||||||
|
}
|
||||||
|
function next () {
|
||||||
|
const tok = current
|
||||||
|
current = null
|
||||||
|
return tok || readNext()
|
||||||
|
}
|
||||||
|
function eof () {
|
||||||
|
return peek() === null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function parse (input) {
|
||||||
|
const PRECEDENCE = {
|
||||||
|
'=': 1,
|
||||||
|
or: 2,
|
||||||
|
and: 3,
|
||||||
|
'<': 7,
|
||||||
|
'>': 7,
|
||||||
|
'<=': 7,
|
||||||
|
'>=': 7,
|
||||||
|
'==': 7,
|
||||||
|
'!=': 7,
|
||||||
|
'+': 10,
|
||||||
|
'-': 10,
|
||||||
|
'*': 20,
|
||||||
|
'/': 20
|
||||||
|
}
|
||||||
|
return parseToplevel()
|
||||||
|
function parseToplevel () {
|
||||||
|
const prog = []
|
||||||
|
while (!input.eof()) {
|
||||||
|
prog.push(parseExpression())
|
||||||
|
const last = prog.slice(-1)[0]
|
||||||
|
if (requireSemicolon(last)) skipPunc(';')
|
||||||
|
}
|
||||||
|
return { type: 'prog', prog: prog }
|
||||||
|
}
|
||||||
|
function parseBlock () {
|
||||||
|
const body = []
|
||||||
|
while (!input.eof() && !isKw('else') && !isKw('end')) {
|
||||||
|
body.push(parseExpression())
|
||||||
|
const last = body.slice(-1)[0]
|
||||||
|
if (requireSemicolon(last)) skipPunc(';')
|
||||||
|
}
|
||||||
|
return { type: 'block', body: body }
|
||||||
|
}
|
||||||
|
function parseExpression () {
|
||||||
|
if (input.eof()) input.croak('Expecting an expression but reached EOF')
|
||||||
|
return maybeBinary(parseAtom(), 0)
|
||||||
|
}
|
||||||
|
function parseAtom () {
|
||||||
|
if (isPunc('(')) {
|
||||||
|
input.next()
|
||||||
|
const exp = parseExpression()
|
||||||
|
skipPunc(')')
|
||||||
|
return exp
|
||||||
|
}
|
||||||
|
if (isKw('begin')) return parseBegin()
|
||||||
|
if (isKw('int')) return parseInit()
|
||||||
|
if (isKw('for')) return parseFor()
|
||||||
|
if (isKw('while')) return parseWhile()
|
||||||
|
if (isKw('if')) return parseIf()
|
||||||
|
if (isOp('-')) return parseUnary('-')
|
||||||
|
if (isOp('+')) return parseUnary('+')
|
||||||
|
const tok = input.next()
|
||||||
|
if (tok.type === 'var' || tok.type === 'num') {
|
||||||
|
return tok
|
||||||
|
}
|
||||||
|
input.croak('Unexpected token ' + tok.value)
|
||||||
|
}
|
||||||
|
function parseBegin () {
|
||||||
|
skipKw('begin')
|
||||||
|
const block = parseBlock()
|
||||||
|
skipKw('end')
|
||||||
|
return { type: 'begin', body: block.body }
|
||||||
|
}
|
||||||
|
function parseInit () {
|
||||||
|
const vars = []
|
||||||
|
let first = true
|
||||||
|
skipKw('int')
|
||||||
|
while (!input.eof()) {
|
||||||
|
if (isPunc(';')) break
|
||||||
|
if (first) first = false
|
||||||
|
else skipPunc(',')
|
||||||
|
if (isPunc(';')) break // the last "," can be missing
|
||||||
|
const tok = parseExpression()
|
||||||
|
if (tok.type !== 'var' && tok.type !== 'assign') {
|
||||||
|
input.croak('Unexpected token ' + tok.type)
|
||||||
|
}
|
||||||
|
vars.push(tok)
|
||||||
|
}
|
||||||
|
skipPunc(';')
|
||||||
|
return {
|
||||||
|
type: 'init',
|
||||||
|
vars: vars
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function parseFor () {
|
||||||
|
skipKw('for')
|
||||||
|
skipPunc(',')
|
||||||
|
const init = parseExpression()
|
||||||
|
if (init.type !== 'assign') {
|
||||||
|
input.croak('Unexpected token ' + init.type)
|
||||||
|
}
|
||||||
|
skipPunc(',')
|
||||||
|
const cond = parseExpression()
|
||||||
|
isRval(cond)
|
||||||
|
skipPunc(',')
|
||||||
|
const inc = parseExpression()
|
||||||
|
isRval(inc)
|
||||||
|
skipPunc(';')
|
||||||
|
const body = parseBlock()
|
||||||
|
skipKw('end')
|
||||||
|
return {
|
||||||
|
type: 'for',
|
||||||
|
init: init,
|
||||||
|
cond: cond,
|
||||||
|
inc: inc,
|
||||||
|
body: body
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function parseWhile () {
|
||||||
|
skipKw('while')
|
||||||
|
skipPunc('(')
|
||||||
|
const cond = parseExpression()
|
||||||
|
isRval(cond)
|
||||||
|
skipPunc(')')
|
||||||
|
const body = parseBlock()
|
||||||
|
skipKw('end')
|
||||||
|
return { type: 'while', cond: cond, body: body }
|
||||||
|
}
|
||||||
|
function parseIf () {
|
||||||
|
skipKw('if')
|
||||||
|
skipPunc('(')
|
||||||
|
const cond = parseExpression()
|
||||||
|
isRval(cond)
|
||||||
|
skipPunc(')')
|
||||||
|
skipKw('then')
|
||||||
|
const then = parseBlock()
|
||||||
|
const ret = { type: 'if', cond: cond, then: then }
|
||||||
|
if (isKw('else')) {
|
||||||
|
input.next()
|
||||||
|
ret.else = parseBlock()
|
||||||
|
}
|
||||||
|
skipKw('end')
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
function parseUnary (op) {
|
||||||
|
skipOp(op)
|
||||||
|
const right = parseAtom()
|
||||||
|
isRval(right)
|
||||||
|
return { type: 'unary', operator: op, right: right }
|
||||||
|
}
|
||||||
|
function maybeBinary (left, myPrec) {
|
||||||
|
if (left.type === 'assign' && left.left.type !== 'var') {
|
||||||
|
input.croak('Invalid left-hand side in assignment')
|
||||||
|
}
|
||||||
|
const tok = isOp()
|
||||||
|
if (tok) {
|
||||||
|
const hisPrec = PRECEDENCE[tok.value]
|
||||||
|
if (hisPrec > myPrec) {
|
||||||
|
input.next()
|
||||||
|
const right = maybeBinary(parseAtom(), hisPrec)
|
||||||
|
isRval(left)
|
||||||
|
isRval(right)
|
||||||
|
return maybeBinary(
|
||||||
|
{
|
||||||
|
type: tok.value === '=' ? 'assign' : 'binary',
|
||||||
|
operator: tok.value,
|
||||||
|
left: left,
|
||||||
|
right: right
|
||||||
|
},
|
||||||
|
myPrec
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return left
|
||||||
|
}
|
||||||
|
function isPunc (ch) {
|
||||||
|
var tok = input.peek()
|
||||||
|
return tok && tok.type === 'punc' && (!ch || tok.value === ch) && tok
|
||||||
|
}
|
||||||
|
function isKw (kw) {
|
||||||
|
var tok = input.peek()
|
||||||
|
return tok && tok.type === 'kw' && (!kw || tok.value === kw) && tok
|
||||||
|
}
|
||||||
|
function isOp (op) {
|
||||||
|
var tok = input.peek()
|
||||||
|
return tok && tok.type === 'op' && (!op || tok.value === op) && tok
|
||||||
|
}
|
||||||
|
function isRval (tok) {
|
||||||
|
if (
|
||||||
|
tok.type !== 'var' &&
|
||||||
|
tok.type !== 'num' &&
|
||||||
|
tok.type !== 'unary' &&
|
||||||
|
tok.type !== 'binary'
|
||||||
|
) {
|
||||||
|
input.croak('Unexpected token ' + tok.type)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function skipOp (ch) {
|
||||||
|
if (isOp(ch)) input.next()
|
||||||
|
else if (!input.eof()) {
|
||||||
|
input.croak('Expecting ' + ch + ' but got ' + input.peek().value)
|
||||||
|
} else {
|
||||||
|
input.croak('Expecting ' + ch + ' but reached EOF')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function skipPunc (ch) {
|
||||||
|
if (isPunc(ch)) input.next()
|
||||||
|
else if (!input.eof()) {
|
||||||
|
input.croak('Expecting ' + ch + ' but got ' + input.peek().value)
|
||||||
|
} else {
|
||||||
|
input.croak('Expecting ' + ch + ' but reached EOF')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function skipKw (kw) {
|
||||||
|
if (isKw(kw)) input.next()
|
||||||
|
else if (!input.eof()) {
|
||||||
|
input.croak('Expecting ' + kw + ' but got ' + input.peek().value)
|
||||||
|
} else {
|
||||||
|
input.croak('Expecting ' + kw + ' but reached EOF')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function isBlock (tok) {
|
||||||
|
return (
|
||||||
|
tok.type === 'begin' ||
|
||||||
|
tok.type === 'for' ||
|
||||||
|
tok.type === 'while' ||
|
||||||
|
tok.type === 'if'
|
||||||
|
)
|
||||||
|
}
|
||||||
|
function requireSemicolon (tok) {
|
||||||
|
return !isBlock(tok) && tok.type !== 'init'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function makeJS (ast) {
|
||||||
|
return js(ast)
|
||||||
|
function js (ast) {
|
||||||
|
const cases = [
|
||||||
|
'js_num',
|
||||||
|
'js_var',
|
||||||
|
'js_unary',
|
||||||
|
'js_binary',
|
||||||
|
'js_assign',
|
||||||
|
'js_init',
|
||||||
|
'js_begin',
|
||||||
|
'js_block',
|
||||||
|
'js_prog',
|
||||||
|
'js_for',
|
||||||
|
'js_while',
|
||||||
|
'js_if'
|
||||||
|
]
|
||||||
|
const handler = {
|
||||||
|
js_num (ast) {
|
||||||
|
return JSON.stringify(ast.value)
|
||||||
|
},
|
||||||
|
js_var (ast) {
|
||||||
|
window.app.ids.push(ast.value)
|
||||||
|
return ast.value
|
||||||
|
},
|
||||||
|
js_unary (ast) {
|
||||||
|
const op = ast.operator
|
||||||
|
return '( ' + op + js(ast.right) + ' )'
|
||||||
|
},
|
||||||
|
js_binary (ast) {
|
||||||
|
let op = ' ' + ast.operator + ' '
|
||||||
|
if (op === ' and ') op = ' && '
|
||||||
|
if (op === ' or ') op = ' || '
|
||||||
|
if (op === ' / ') {
|
||||||
|
return 'Math.trunc(' + js(ast.left) + op + js(ast.right) + ')'
|
||||||
|
}
|
||||||
|
return '( ' + js(ast.left) + op + js(ast.right) + ' )'
|
||||||
|
},
|
||||||
|
js_assign (ast) {
|
||||||
|
return js(ast.left) + ' = ' + js(ast.right)
|
||||||
|
},
|
||||||
|
js_init (ast) {
|
||||||
|
const vars = []
|
||||||
|
for (let i = 0; i < ast.vars.length; i += 1) {
|
||||||
|
vars.push(js(ast.vars[i]))
|
||||||
|
}
|
||||||
|
return 'var ' + vars.join(', ')
|
||||||
|
},
|
||||||
|
js_prog (ast) {
|
||||||
|
const prog = []
|
||||||
|
for (let i = 0; i < ast.prog.length; i += 1) {
|
||||||
|
prog.push(js(ast.prog[i]))
|
||||||
|
}
|
||||||
|
return prog.join('; ') + ';'
|
||||||
|
},
|
||||||
|
js_block (ast) {
|
||||||
|
const body = []
|
||||||
|
for (let i = 0; i < ast.body.length; i += 1) {
|
||||||
|
body.push(js(ast.body[i]))
|
||||||
|
}
|
||||||
|
return body.join('; ') + ';'
|
||||||
|
},
|
||||||
|
js_begin (ast) {
|
||||||
|
return this.js_block(ast)
|
||||||
|
},
|
||||||
|
js_for (ast) {
|
||||||
|
return (
|
||||||
|
'for (' +
|
||||||
|
js(ast.init) +
|
||||||
|
'; ' +
|
||||||
|
js(ast.cond) +
|
||||||
|
'; ' +
|
||||||
|
js(ast.init.left) +
|
||||||
|
' += ' +
|
||||||
|
js(ast.inc) +
|
||||||
|
') { ' +
|
||||||
|
js(ast.body) +
|
||||||
|
' }'
|
||||||
|
)
|
||||||
|
},
|
||||||
|
js_while (ast) {
|
||||||
|
return 'while (' + js(ast.cond) + ') { ' + js(ast.body) + ' }'
|
||||||
|
},
|
||||||
|
js_if (ast) {
|
||||||
|
let str = 'if (' + js(ast.cond) + ') { ' + js(ast.then) + ' }'
|
||||||
|
if (ast.else) {
|
||||||
|
str += ' else { ' + js(ast.else) + ' }'
|
||||||
|
}
|
||||||
|
return str
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (let i = 0; i < cases.length; i += 1) {
|
||||||
|
if ('js_' + ast.type === cases[i]) {
|
||||||
|
return handler[cases[i]](ast)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
24
Home/Compiler/test.big5.txt
Normal file
24
Home/Compiler/test.big5.txt
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
begin
|
||||||
|
int x=0, zzz = 5;
|
||||||
|
int i, j = 1;
|
||||||
|
|
||||||
|
# 進行迴圈計算
|
||||||
|
for, i=1, i<=50, j; # j是i每次增加的數值
|
||||||
|
x=x+1;
|
||||||
|
end # for
|
||||||
|
|
||||||
|
if ((x>5) and (j<=8)) then
|
||||||
|
x=1;
|
||||||
|
else
|
||||||
|
for, i=1, i<=50, j+1;
|
||||||
|
x=x+1;
|
||||||
|
end
|
||||||
|
|
||||||
|
while (i < 11)
|
||||||
|
yy = x;
|
||||||
|
i = i + 1;
|
||||||
|
end
|
||||||
|
|
||||||
|
end # if
|
||||||
|
|
||||||
|
end
|
24
Home/Compiler/test.utf8.txt
Normal file
24
Home/Compiler/test.utf8.txt
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
begin
|
||||||
|
int x=0, zzz = 5;
|
||||||
|
int i, j = 1;
|
||||||
|
|
||||||
|
# 進行迴圈計算
|
||||||
|
for, i=1, i<=50, j; # j是i每次增加的數值
|
||||||
|
x=x+1;
|
||||||
|
end # for
|
||||||
|
|
||||||
|
if ((x>5) and (j<=8)) then
|
||||||
|
x=1;
|
||||||
|
else
|
||||||
|
for, i=1, i<=50, j+1;
|
||||||
|
x=x+1;
|
||||||
|
end
|
||||||
|
|
||||||
|
while (i < 11)
|
||||||
|
yy = x;
|
||||||
|
i = i + 1;
|
||||||
|
end
|
||||||
|
|
||||||
|
end # if
|
||||||
|
|
||||||
|
end
|
13
Home/Compiler/webpack.config.js
Normal file
13
Home/Compiler/webpack.config.js
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
const path = require('path')
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
mode: 'none',
|
||||||
|
entry: './src/main.dev.js',
|
||||||
|
output: {
|
||||||
|
path: path.resolve(__dirname, './'),
|
||||||
|
filename: 'main.js'
|
||||||
|
},
|
||||||
|
module: {
|
||||||
|
rules: [{ test: /\.js$/, exclude: /node_modules/, loader: 'babel-loader' }]
|
||||||
|
}
|
||||||
|
}
|
BIN
Home/LTI/asset/clap.mp3
Normal file
BIN
Home/LTI/asset/clap.mp3
Normal file
Binary file not shown.
BIN
Home/LTI/asset/sample.mp3
Normal file
BIN
Home/LTI/asset/sample.mp3
Normal file
Binary file not shown.
BIN
Home/LTI/asset/wavform-clap.png
Normal file
BIN
Home/LTI/asset/wavform-clap.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 7.4 KiB |
BIN
Home/LTI/asset/wavform-sample.png
Normal file
BIN
Home/LTI/asset/wavform-sample.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 8.1 KiB |
201
Home/LTI/index.html
Normal file
201
Home/LTI/index.html
Normal file
@ -0,0 +1,201 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>LTI System Analysis</title>
|
||||||
|
<link rel="stylesheet" href="lib/bootstrap.min.css">
|
||||||
|
<link rel="stylesheet" href="main.css">
|
||||||
|
<script src="lib/plotlyjs.min.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="root" class="container">
|
||||||
|
<h1 class="mt-3">LTI System Analysis</h1>
|
||||||
|
<h3 class="code mt-5">
|
||||||
|
<span class="coef">a<sub>0</sub></span>y[n] +
|
||||||
|
<span class="coef">a<sub>1</sub></span>y[n-1] +
|
||||||
|
<span class="coef">a<sub>2</sub></span>y[n-2] + ... +
|
||||||
|
<span class="coef">a<sub>p</sub></span>y[n-<span class="deg">p</span>] =
|
||||||
|
</h3>
|
||||||
|
<h3 class="code text-right">
|
||||||
|
<span class="coef">b<sub>0</sub></span>x[n] +
|
||||||
|
<span class="coef">b<sub>1</sub></span>x[n-1] +
|
||||||
|
<span class="coef">b<sub>2</sub></span>x[n-2] + ... +
|
||||||
|
<span class="coef">b<sub>q</sub></span>x[n-<span class="deg">q</span>]
|
||||||
|
</h3>
|
||||||
|
<dl class="row mt-5">
|
||||||
|
<dt class="col-sm-2">JSON data:</dt>
|
||||||
|
<dd class="col-sm-10">
|
||||||
|
<div class="custom-file">
|
||||||
|
<input type="file" id="systemFile" class="custom-file-input" @change="systemFileHandler">
|
||||||
|
<label class="custom-file-label" for="systemFile">{{ systemFile ? systemFile.name : 'Choose file' }}</label>
|
||||||
|
<button type="button" class="btn btn-secondary" @click="systemFileHandler">Reload</button>
|
||||||
|
</div>
|
||||||
|
</dd>
|
||||||
|
<dd class="col-sm-12 maxheight">
|
||||||
|
<dl class="row mt-0 mb-0">
|
||||||
|
<dt class="col-sm-2">Orders:</dt>
|
||||||
|
<dd class="code col-sm-5">
|
||||||
|
<label>p<sub> </sub> =</label>
|
||||||
|
<input type="number" min="0" v-model.number="p" @change="system('a')">
|
||||||
|
</dd>
|
||||||
|
<dd class="code col-sm-5">
|
||||||
|
<label>q<sub> </sub> =</label>
|
||||||
|
<input type="number" min="0" v-model.number="q" @change="system('b')">
|
||||||
|
</dd>
|
||||||
|
<dt class="col-sm-2">Coefficients:</dt>
|
||||||
|
<dd class="code col-sm-5">
|
||||||
|
<p v-for="(c, i) in a">
|
||||||
|
<label>a<sub>{{ i }}</sub> =</label>
|
||||||
|
<input type="number" v-model.number="a[i]" @change="output">
|
||||||
|
</p>
|
||||||
|
</dd>
|
||||||
|
<dd class="code col-sm-5">
|
||||||
|
<p v-for="(c, i) in b">
|
||||||
|
<label>b<sub>{{ i }}</sub> =</label>
|
||||||
|
<input type="number" v-model.number="b[i]" @change="output">
|
||||||
|
</p>
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
</dd>
|
||||||
|
<dt class="col-sm-2">System:</dt>
|
||||||
|
<dd class="code col-sm-10">
|
||||||
|
<span v-for="(c, i) in a">
|
||||||
|
<span v-if="!firstTerm(a, i) && c > 0">+</span>
|
||||||
|
<span v-else-if="c < 0">-</span>
|
||||||
|
<span v-if="c == 1 || c == -1">
|
||||||
|
y[n{{ i ? '-' + i : '' }}]
|
||||||
|
</span>
|
||||||
|
<span v-else-if="c > 0">
|
||||||
|
{{ c }}y[n{{ i ? '-' + i : '' }}]
|
||||||
|
</span>
|
||||||
|
<span v-else-if="c < 0">
|
||||||
|
{{ Math.abs(c) }}y[n{{ i ? '-' + i : '' }}]
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
<span v-if="allZero(a)">0</span>
|
||||||
|
=
|
||||||
|
<span v-for="(c, i) in b">
|
||||||
|
<span v-if="!firstTerm(b, i) && c > 0">+</span>
|
||||||
|
<span v-else-if="c < 0">-</span>
|
||||||
|
<span v-if="c == 1 || c == -1">
|
||||||
|
x[n{{ i ? '-' + i : '' }}]
|
||||||
|
</span>
|
||||||
|
<span v-else-if="c > 0">
|
||||||
|
{{ c }}x[n{{ i ? '-' + i : '' }}]
|
||||||
|
</span>
|
||||||
|
<span v-else-if="c < 0">
|
||||||
|
{{ Math.abs(c) }}x[n{{ i ? '-' + i : '' }}]
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
<span v-if="allZero(b)">0</span>
|
||||||
|
</dd>
|
||||||
|
<hr class="divider">
|
||||||
|
<dt class="col-sm-12 mb-4"><h5>Time Response Simulation:</h5></dt>
|
||||||
|
<dt class="col-sm-2">Plot mode:</dt>
|
||||||
|
<dd class="col-sm-10">
|
||||||
|
<input id="stem" type="checkbox" v-model="stem" @change="output">
|
||||||
|
<label for="stem">stem</label>
|
||||||
|
</dd>
|
||||||
|
<dt class="col-sm-2">Input preset:</dt>
|
||||||
|
<dd class="code col-sm-3">
|
||||||
|
<select v-model="preset" @change="presetHandler">
|
||||||
|
<option value="d">δ[n]</option>
|
||||||
|
<option value="u">u[n]</option>
|
||||||
|
<option value="sin">Asin[Ωn+Φ]</option>
|
||||||
|
<option value="cos">Acos[Ωn+Φ]</option>
|
||||||
|
<option value="exp">exp[n]</option>
|
||||||
|
<option value="log">log[n+1]</option>
|
||||||
|
<option value="n">n</option>
|
||||||
|
<option value="c">custom</option>
|
||||||
|
</select>
|
||||||
|
</dd>
|
||||||
|
<dt class="col-sm-2">Input length: </dt>
|
||||||
|
<dd class="code col-sm-5">
|
||||||
|
<input type="number" min="1" v-model.number="length" @change="lengthHandler">
|
||||||
|
</dd>
|
||||||
|
<dt v-if="isTrig" class="col-sm-2">A:</dt>
|
||||||
|
<dd v-if="isTrig" class="code col-sm-10">
|
||||||
|
<input type="number" v-model.number="A" @change="trigHandler">
|
||||||
|
</dd>
|
||||||
|
<dt v-if="isTrig" class="col-sm-2">Ω:</dt>
|
||||||
|
<dd v-if="isTrig" class="code col-sm-10">
|
||||||
|
2π / <input type="number" min="1" v-model.number="T" @change="trigHandler">
|
||||||
|
</dd>
|
||||||
|
<dt v-if="isTrig" class="col-sm-2">Φ:</dt>
|
||||||
|
<dd v-if="isTrig" class="code col-sm-10">
|
||||||
|
Ω × <input type="number" v-model.number="tao" @change="trigHandler">
|
||||||
|
</dd>
|
||||||
|
<dt class="col-sm-2">Input scaler:</dt>
|
||||||
|
<dd class="code col-sm-3">
|
||||||
|
<input type="number" v-model.number="scaler" @change="output" :disabled="!readonly">
|
||||||
|
</dd>
|
||||||
|
<dt class="col-sm-3">Raise scaler to the power of n: </dt>
|
||||||
|
<dd class="col-sm-4">
|
||||||
|
<input type="checkbox" v-model="toPower" @change="output" :disabled="!readonly">
|
||||||
|
</dd>
|
||||||
|
<dt class="col-sm-2"></dt>
|
||||||
|
<dd class="col-sm-3"></dd>
|
||||||
|
<dt class="col-sm-3">Reverse: </dt>
|
||||||
|
<dd class="col-sm-4">
|
||||||
|
<input type="checkbox" v-model="reverse" @change="output">
|
||||||
|
</dd>
|
||||||
|
<dt class="col-sm-2"></dt>
|
||||||
|
<dd class="code col-sm-10"></dd>
|
||||||
|
<dt class="col-sm-2">Input:</dt>
|
||||||
|
<dd class="code col-sm-10">
|
||||||
|
<input style="width: 100%" v-model="x" @change="inputHandler" :readonly="readonly">
|
||||||
|
</dd>
|
||||||
|
<div id="input"></div>
|
||||||
|
<hr class="divider">
|
||||||
|
<dt class="col-sm-2">Output:</dt>
|
||||||
|
<dd class="code col-sm-10">
|
||||||
|
<p class="nowrap" v-text="y.join(',')"></p>
|
||||||
|
</dd>
|
||||||
|
<div id="output"></div>
|
||||||
|
<hr class="divider">
|
||||||
|
<dt class="col-sm-10 mb-3"><h5>Frequency Response Analysis:</h5></dt>
|
||||||
|
<dd class="col-sm-2">
|
||||||
|
<button class="btn btn-success float-right" @click="redrawFR">Replot</button>
|
||||||
|
</dd>
|
||||||
|
<div id="magnitude"></div>
|
||||||
|
<div id="phase"></div>
|
||||||
|
<hr class="divider">
|
||||||
|
<dt class="col-sm-10 mb-3"><h5>Convolution Reverb Demo:</h5></dt>
|
||||||
|
<dd class="col-sm-2"></dd>
|
||||||
|
<dt class="col-sm-2">Clap response:</dt>
|
||||||
|
<dd class="col-sm-10">
|
||||||
|
<div>
|
||||||
|
<iframe width="480" height="270" src="https://www.youtube.com/embed/W3hsOFazEz4?rel=0" frameborder="0"></iframe>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<img src="asset/wavform-clap.png" alt="clap">
|
||||||
|
</div>
|
||||||
|
<audio controls>
|
||||||
|
<source src="asset/clap.mp3" type="audio/mpeg">
|
||||||
|
Your browser does not support the audio tag.
|
||||||
|
</audio>
|
||||||
|
</dd>
|
||||||
|
<dt class="col-sm-2">Sample input:</dt>
|
||||||
|
<dd class="col-sm-10">
|
||||||
|
<div>
|
||||||
|
<img src="asset/wavform-sample.png" alt="sample">
|
||||||
|
</div>
|
||||||
|
<audio controls>
|
||||||
|
<source src="asset/sample.mp3" type="audio/mpeg">
|
||||||
|
Your browser does not support the audio tag.
|
||||||
|
</audio>
|
||||||
|
</dd>
|
||||||
|
<dt class="col-sm-2">Result:</dt>
|
||||||
|
<dd class="col-sm-10">
|
||||||
|
<div>
|
||||||
|
<canvas id="waveform3" width="480" height="100"></canvas>
|
||||||
|
</div>
|
||||||
|
<button class="btn btn-primary" @click="reverb">Reverb</button>
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
</div>
|
||||||
|
<script src="lib/math.min.js"></script>
|
||||||
|
<script src="lib/vue.min.js"></script>
|
||||||
|
<script src="main.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
7
Home/LTI/lib/bootstrap.min.css
vendored
Normal file
7
Home/LTI/lib/bootstrap.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
43
Home/LTI/lib/math.min.js
vendored
Normal file
43
Home/LTI/lib/math.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
24
Home/LTI/lib/plotlyjs.min.js
vendored
Normal file
24
Home/LTI/lib/plotlyjs.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
6
Home/LTI/lib/vue.min.js
vendored
Normal file
6
Home/LTI/lib/vue.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
49
Home/LTI/main.css
Normal file
49
Home/LTI/main.css
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
input {
|
||||||
|
padding: 0 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.deg {
|
||||||
|
color: rgb(192, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
.coef {
|
||||||
|
color: rgb(0, 0, 192);
|
||||||
|
}
|
||||||
|
|
||||||
|
.code {
|
||||||
|
font-family: "Menlo", "Consolas", monospace;
|
||||||
|
}
|
||||||
|
|
||||||
|
.code p {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nowrap {
|
||||||
|
overflow: auto;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.divider {
|
||||||
|
width: 100%;
|
||||||
|
margin-bottom: 1.8rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-file {
|
||||||
|
width: 300px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-file button {
|
||||||
|
position: relative;
|
||||||
|
top: -38px;
|
||||||
|
left: 305px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.maxheight {
|
||||||
|
overflow-y: auto;
|
||||||
|
width: 100%;
|
||||||
|
max-height: 300px;
|
||||||
|
}
|
||||||
|
|
||||||
|
audio:focus {
|
||||||
|
outline: none;
|
||||||
|
}
|
20
Home/LTI/package.json
Normal file
20
Home/LTI/package.json
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"name": "LTI",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "",
|
||||||
|
"main": "main.js",
|
||||||
|
"scripts": {
|
||||||
|
"build": "webpack",
|
||||||
|
"watch": "npm run build -- --watch"
|
||||||
|
},
|
||||||
|
"keywords": [],
|
||||||
|
"author": "",
|
||||||
|
"license": "ISC",
|
||||||
|
"devDependencies": {
|
||||||
|
"@babel/core": "^7.7.2",
|
||||||
|
"@babel/preset-env": "^7.7.1",
|
||||||
|
"babel-loader": "^8.0.6",
|
||||||
|
"webpack": "^4.41.2",
|
||||||
|
"webpack-cli": "^3.3.10"
|
||||||
|
}
|
||||||
|
}
|
706
Home/LTI/src/main.dev.js
Normal file
706
Home/LTI/src/main.dev.js
Normal file
@ -0,0 +1,706 @@
|
|||||||
|
/* global
|
||||||
|
Audio,
|
||||||
|
AudioContext,
|
||||||
|
FileReader,
|
||||||
|
Plotly,
|
||||||
|
Vue,
|
||||||
|
cancelAnimationFrame,
|
||||||
|
fetch,
|
||||||
|
math,
|
||||||
|
requestAnimationFrame
|
||||||
|
*/
|
||||||
|
Vue.config.devtools = true
|
||||||
|
|
||||||
|
const figureIn = {
|
||||||
|
data: [
|
||||||
|
{
|
||||||
|
line: {
|
||||||
|
dash: 'solid',
|
||||||
|
color: 'rgb(0,113.985,188.955)',
|
||||||
|
width: 1
|
||||||
|
},
|
||||||
|
mode: 'lines+markers',
|
||||||
|
name: '',
|
||||||
|
type: 'scatter',
|
||||||
|
x: [],
|
||||||
|
y: [],
|
||||||
|
xaxis: 'x',
|
||||||
|
yaxis: 'y',
|
||||||
|
marker: {
|
||||||
|
line: {
|
||||||
|
width: 1,
|
||||||
|
color: []
|
||||||
|
},
|
||||||
|
size: 8,
|
||||||
|
symbol: 'circle',
|
||||||
|
color: []
|
||||||
|
},
|
||||||
|
visible: true,
|
||||||
|
showlegend: true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
layout: {
|
||||||
|
title: '',
|
||||||
|
width: 840,
|
||||||
|
xaxis: {
|
||||||
|
side: 'bottom',
|
||||||
|
type: 'linear',
|
||||||
|
range: [],
|
||||||
|
ticks: 'inside',
|
||||||
|
anchor: 'y',
|
||||||
|
domain: [0.13, 0.905],
|
||||||
|
mirror: 'ticks',
|
||||||
|
nticks: 9,
|
||||||
|
ticklen: 6.51,
|
||||||
|
showgrid: false,
|
||||||
|
showline: true,
|
||||||
|
tickfont: {
|
||||||
|
size: 10,
|
||||||
|
color: 'rgb(38.25,38.25,38.25)',
|
||||||
|
family: 'Arial, sans-serif'
|
||||||
|
},
|
||||||
|
tickmode: 'auto',
|
||||||
|
zeroline: false,
|
||||||
|
autorange: true,
|
||||||
|
gridcolor: 'rgb(38.25,38.25,38.25)',
|
||||||
|
gridwidth: 1,
|
||||||
|
linecolor: 'rgb(38.25,38.25,38.25)',
|
||||||
|
linewidth: 1,
|
||||||
|
tickcolor: 'rgb(38.25,38.25,38.25)',
|
||||||
|
tickwidth: 1,
|
||||||
|
titlefont: {
|
||||||
|
size: 11,
|
||||||
|
color: 'rgb(38.25,38.25,38.25)',
|
||||||
|
family: 'Arial, sans-serif'
|
||||||
|
},
|
||||||
|
exponentformat: 'none'
|
||||||
|
},
|
||||||
|
yaxis: {
|
||||||
|
side: 'left',
|
||||||
|
type: 'linear',
|
||||||
|
range: [],
|
||||||
|
ticks: 'inside',
|
||||||
|
anchor: 'x',
|
||||||
|
domain: [0.11, 0.925],
|
||||||
|
mirror: 'ticks',
|
||||||
|
nticks: 12,
|
||||||
|
ticklen: 6.51,
|
||||||
|
showgrid: false,
|
||||||
|
showline: true,
|
||||||
|
tickfont: {
|
||||||
|
size: 10,
|
||||||
|
color: 'rgb(38.25,38.25,38.25)',
|
||||||
|
family: 'Arial, sans-serif'
|
||||||
|
},
|
||||||
|
tickmode: 'auto',
|
||||||
|
zeroline: true,
|
||||||
|
autorange: false,
|
||||||
|
gridcolor: 'rgb(38.25,38.25,38.25)',
|
||||||
|
gridwidth: 1,
|
||||||
|
linecolor: 'rgb(38.25,38.25,38.25)',
|
||||||
|
linewidth: 1,
|
||||||
|
tickcolor: 'rgb(38.25,38.25,38.25)',
|
||||||
|
tickwidth: 1,
|
||||||
|
titlefont: {
|
||||||
|
size: 11,
|
||||||
|
color: 'rgb(38.25,38.25,38.25)',
|
||||||
|
family: 'Arial, sans-serif'
|
||||||
|
},
|
||||||
|
exponentformat: 'none',
|
||||||
|
showticklabels: true
|
||||||
|
},
|
||||||
|
height: 480,
|
||||||
|
margin: {
|
||||||
|
b: 0,
|
||||||
|
l: 0,
|
||||||
|
r: 0,
|
||||||
|
t: 0,
|
||||||
|
pad: 0
|
||||||
|
},
|
||||||
|
autosize: false,
|
||||||
|
hovermode: 'closest',
|
||||||
|
titlefont: {
|
||||||
|
color: 'rgba(0,0,0,0)'
|
||||||
|
},
|
||||||
|
showlegend: false,
|
||||||
|
annotations: [
|
||||||
|
{
|
||||||
|
x: 0.5175,
|
||||||
|
y: 0.935,
|
||||||
|
font: {
|
||||||
|
size: 11,
|
||||||
|
color: 'rgb(0,0,0)',
|
||||||
|
family: 'Arial, sans-serif'
|
||||||
|
},
|
||||||
|
text: '',
|
||||||
|
xref: 'paper',
|
||||||
|
yref: 'paper',
|
||||||
|
align: 'center',
|
||||||
|
xanchor: 'center',
|
||||||
|
yanchor: 'bottom',
|
||||||
|
borderpad: 3,
|
||||||
|
showarrow: false,
|
||||||
|
textangle: 0,
|
||||||
|
bordercolor: 'rgba(0,0,0,0)',
|
||||||
|
borderwidth: 0.5
|
||||||
|
}
|
||||||
|
],
|
||||||
|
plot_bgcolor: 'rgba(0,0,0,0)',
|
||||||
|
paper_bgcolor: 'rgb(255,255,255)'
|
||||||
|
},
|
||||||
|
frames: []
|
||||||
|
}
|
||||||
|
|
||||||
|
const figureMag = {
|
||||||
|
data: [
|
||||||
|
{
|
||||||
|
line: {
|
||||||
|
dash: 'solid',
|
||||||
|
color: 'rgb(0,113.985,188.955)',
|
||||||
|
width: 1
|
||||||
|
},
|
||||||
|
mode: 'lines',
|
||||||
|
name: '',
|
||||||
|
type: 'scatter',
|
||||||
|
x: [],
|
||||||
|
y: [],
|
||||||
|
xaxis: 'x',
|
||||||
|
yaxis: 'y',
|
||||||
|
marker: {
|
||||||
|
line: {
|
||||||
|
width: 1,
|
||||||
|
color: []
|
||||||
|
},
|
||||||
|
size: 8,
|
||||||
|
symbol: 'circle',
|
||||||
|
color: []
|
||||||
|
},
|
||||||
|
visible: true,
|
||||||
|
showlegend: true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
layout: {
|
||||||
|
title: '',
|
||||||
|
width: 840,
|
||||||
|
xaxis: {
|
||||||
|
title: 'Normalized Frequency (× π rad/sample)',
|
||||||
|
side: 'bottom',
|
||||||
|
type: 'linear',
|
||||||
|
range: [0, 2],
|
||||||
|
ticks: 'inside',
|
||||||
|
anchor: 'y',
|
||||||
|
domain: [0.13, 0.905],
|
||||||
|
mirror: 'ticks',
|
||||||
|
nticks: 9,
|
||||||
|
ticklen: 6.51,
|
||||||
|
showgrid: true,
|
||||||
|
showline: true,
|
||||||
|
tickfont: {
|
||||||
|
size: 10,
|
||||||
|
color: 'rgb(38.25,38.25,38.25)',
|
||||||
|
family: 'Arial, sans-serif'
|
||||||
|
},
|
||||||
|
tickmode: 'array',
|
||||||
|
tickvals: [0, 0.2, 0.4, 0.6, 0.8, 1, 1.2, 1.4, 1.6, 1.8, 2],
|
||||||
|
zeroline: false,
|
||||||
|
autorange: true,
|
||||||
|
gridcolor: 'rgba(38.25,38.25,38.25,0.25)',
|
||||||
|
gridwidth: 1,
|
||||||
|
linecolor: 'rgb(38.25,38.25,38.25)',
|
||||||
|
linewidth: 1,
|
||||||
|
tickcolor: 'rgb(38.25,38.25,38.25)',
|
||||||
|
tickwidth: 1,
|
||||||
|
titlefont: {
|
||||||
|
size: 18,
|
||||||
|
color: 'rgb(38.25,38.25,38.25)',
|
||||||
|
family: 'serif'
|
||||||
|
},
|
||||||
|
exponentformat: 'none'
|
||||||
|
},
|
||||||
|
yaxis: {
|
||||||
|
title: 'Magnitude (dB)',
|
||||||
|
side: 'left',
|
||||||
|
type: 'linear',
|
||||||
|
range: [],
|
||||||
|
ticks: 'inside',
|
||||||
|
anchor: 'x',
|
||||||
|
domain: [0.11, 0.925],
|
||||||
|
mirror: 'ticks',
|
||||||
|
nticks: 12,
|
||||||
|
ticklen: 6.51,
|
||||||
|
showgrid: true,
|
||||||
|
showline: true,
|
||||||
|
tickfont: {
|
||||||
|
size: 10,
|
||||||
|
color: 'rgb(38.25,38.25,38.25)',
|
||||||
|
family: 'Arial, sans-serif'
|
||||||
|
},
|
||||||
|
tickmode: 'auto',
|
||||||
|
zeroline: false,
|
||||||
|
autorange: true,
|
||||||
|
gridcolor: 'rgba(38.25,38.25,38.25,0.25)',
|
||||||
|
gridwidth: 1,
|
||||||
|
linecolor: 'rgb(38.25,38.25,38.25)',
|
||||||
|
linewidth: 1,
|
||||||
|
tickcolor: 'rgb(38.25,38.25,38.25)',
|
||||||
|
tickwidth: 1,
|
||||||
|
titlefont: {
|
||||||
|
size: 18,
|
||||||
|
color: 'rgb(38.25,38.25,38.25)',
|
||||||
|
family: 'serif'
|
||||||
|
},
|
||||||
|
exponentformat: 'none',
|
||||||
|
showticklabels: true
|
||||||
|
},
|
||||||
|
height: 480,
|
||||||
|
margin: {
|
||||||
|
b: 0,
|
||||||
|
l: 0,
|
||||||
|
r: 0,
|
||||||
|
t: 0,
|
||||||
|
pad: 0
|
||||||
|
},
|
||||||
|
autosize: false,
|
||||||
|
hovermode: 'closest',
|
||||||
|
titlefont: {
|
||||||
|
color: 'rgba(38.25,38.25,38.25,1)'
|
||||||
|
},
|
||||||
|
showlegend: false,
|
||||||
|
annotations: [
|
||||||
|
{
|
||||||
|
x: 0.5175,
|
||||||
|
y: 0.935,
|
||||||
|
font: {
|
||||||
|
size: 11,
|
||||||
|
color: 'rgb(0,0,0)',
|
||||||
|
family: 'Arial, sans-serif'
|
||||||
|
},
|
||||||
|
text: '',
|
||||||
|
xref: 'paper',
|
||||||
|
yref: 'paper',
|
||||||
|
align: 'center',
|
||||||
|
xanchor: 'center',
|
||||||
|
yanchor: 'bottom',
|
||||||
|
borderpad: 3,
|
||||||
|
showarrow: false,
|
||||||
|
textangle: 0,
|
||||||
|
bordercolor: 'rgba(0,0,0,0)',
|
||||||
|
borderwidth: 0.5
|
||||||
|
}
|
||||||
|
],
|
||||||
|
plot_bgcolor: 'rgba(0,0,0,0)',
|
||||||
|
paper_bgcolor: 'rgb(255,255,255)'
|
||||||
|
},
|
||||||
|
frames: []
|
||||||
|
}
|
||||||
|
|
||||||
|
const figureOut = JSON.parse(JSON.stringify(figureIn))
|
||||||
|
const figurePhase = JSON.parse(JSON.stringify(figureMag))
|
||||||
|
|
||||||
|
window.app = new Vue({
|
||||||
|
el: '#root',
|
||||||
|
data: {
|
||||||
|
figureIn: figureIn,
|
||||||
|
figureOut: figureOut,
|
||||||
|
figureMag: figureMag,
|
||||||
|
figurePhase: figurePhase,
|
||||||
|
p: 0,
|
||||||
|
q: 0,
|
||||||
|
a: [1],
|
||||||
|
b: [1],
|
||||||
|
w: [],
|
||||||
|
x: [1].concat(Array(19).fill(0)),
|
||||||
|
y: [1].concat(Array(19).fill(0)),
|
||||||
|
z: [],
|
||||||
|
preset: 'd',
|
||||||
|
length: 20,
|
||||||
|
isTrig: false,
|
||||||
|
A: 1,
|
||||||
|
T: 19,
|
||||||
|
tao: 0,
|
||||||
|
scaler: 1,
|
||||||
|
reverse: false,
|
||||||
|
toPower: false,
|
||||||
|
readonly: true,
|
||||||
|
stem: true,
|
||||||
|
systemFile: '',
|
||||||
|
fileReader: new FileReader()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
systemFileHandler () {
|
||||||
|
const file = document.querySelector('#systemFile').files[0]
|
||||||
|
if (file) {
|
||||||
|
this.systemFile = file
|
||||||
|
this.fileReader.readAsText(this.systemFile)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
getDegreeKey (s) {
|
||||||
|
// convert 'a' -> 'p', 'b' -> 'q'
|
||||||
|
// 'p' - 'a' == 15
|
||||||
|
return String.fromCharCode(s.charCodeAt(0) + 15)
|
||||||
|
},
|
||||||
|
system (s) {
|
||||||
|
this.truncate()
|
||||||
|
const old = this[s].slice(0)
|
||||||
|
const len = this[this.getDegreeKey(s)] + 1
|
||||||
|
if (len > old.length) {
|
||||||
|
this[s] = Array(len).fill(1)
|
||||||
|
Array.prototype.splice.apply(this[s], [0, old.length].concat(old))
|
||||||
|
} else {
|
||||||
|
this[s] = old.slice(0, len)
|
||||||
|
}
|
||||||
|
this.output()
|
||||||
|
},
|
||||||
|
input (name, length) {
|
||||||
|
const omega = (2 * Math.PI) / this.T
|
||||||
|
const fn = {
|
||||||
|
d: [1].concat(Array(length - 1).fill(0)),
|
||||||
|
u: Array(length).fill(1),
|
||||||
|
sin: [...Array(length).keys()].map(
|
||||||
|
x => this.A * Math.sin(omega * (x + this.tao))
|
||||||
|
),
|
||||||
|
cos: [...Array(length).keys()].map(
|
||||||
|
x => this.A * Math.cos(omega * (x + this.tao))
|
||||||
|
),
|
||||||
|
exp: [...Array(length).keys()].map(x => Math.exp(x)),
|
||||||
|
log: [...Array(length).keys()].map(x => Math.log(x + 1)),
|
||||||
|
n: [...Array(length).keys()],
|
||||||
|
c: this.x
|
||||||
|
}
|
||||||
|
return fn[name]
|
||||||
|
},
|
||||||
|
output () {
|
||||||
|
const d = this.input('d', this.length)
|
||||||
|
const h = this.filter(this.b, this.a, d)
|
||||||
|
const x = this.input(this.preset, this.length)
|
||||||
|
this.x = x.map((x, n) => this.scale(x, n))
|
||||||
|
if (this.reverse) this.x = this.x.reverse()
|
||||||
|
this.y = this.conv(this.x, h).slice(0, this.length)
|
||||||
|
this.redrawIO(this.x, this.figureIn)
|
||||||
|
this.redrawIO(this.y, this.figureOut)
|
||||||
|
},
|
||||||
|
scale (x, n) {
|
||||||
|
const s = Math.pow(this.scaler, this.toPower ? n : 1)
|
||||||
|
return s * x
|
||||||
|
},
|
||||||
|
presetHandler () {
|
||||||
|
const s = this.preset
|
||||||
|
if (s === 'c') {
|
||||||
|
this.scaler = 1
|
||||||
|
this.toPower = false
|
||||||
|
this.readonly = false
|
||||||
|
} else {
|
||||||
|
this.length = 20
|
||||||
|
this.x = this.input(s, this.length)
|
||||||
|
this.readonly = true
|
||||||
|
if (s === 'sin' || s === 'cos') {
|
||||||
|
this.isTrig = true
|
||||||
|
} else {
|
||||||
|
this.isTrig = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.output()
|
||||||
|
},
|
||||||
|
lengthHandler () {
|
||||||
|
this.truncate()
|
||||||
|
if (this.length > this.x.length) {
|
||||||
|
const s = this.preset
|
||||||
|
if (s === 'c') {
|
||||||
|
const diff = this.length - this.x.length
|
||||||
|
this.x = this.x.concat(Array(diff).fill(0))
|
||||||
|
} else {
|
||||||
|
this.x = this.input(s, this.length)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.x.length = this.length
|
||||||
|
}
|
||||||
|
this.output()
|
||||||
|
},
|
||||||
|
inputHandler () {
|
||||||
|
this.x = this.x.split(',')
|
||||||
|
this.length = this.x.length
|
||||||
|
this.output()
|
||||||
|
},
|
||||||
|
trigHandler () {
|
||||||
|
this.truncate()
|
||||||
|
this.output()
|
||||||
|
},
|
||||||
|
truncate () {
|
||||||
|
const keys = ['p', 'q', 'length', 'T', 'tao']
|
||||||
|
keys.forEach(key => {
|
||||||
|
this[key] = Math.trunc(this[key])
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// view helper function
|
||||||
|
firstTerm (a, i) {
|
||||||
|
for (let j = 0; j < i; j += 1) {
|
||||||
|
if (a[j] !== 0) return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
},
|
||||||
|
// view helper function
|
||||||
|
allZero (a) {
|
||||||
|
for (const i of a) {
|
||||||
|
if (i !== 0) return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
},
|
||||||
|
filter (b, a, x) {
|
||||||
|
if (a[0] !== 0) {
|
||||||
|
const n = a.length - 1
|
||||||
|
const m = b.length - 1
|
||||||
|
const y = []
|
||||||
|
for (let i = 0; i < x.length; i += 1) {
|
||||||
|
let lhs = 0
|
||||||
|
let rhs = 0
|
||||||
|
for (let j = 1; j <= n && j <= i; j += 1) {
|
||||||
|
lhs = lhs + a[j] * y[i - j]
|
||||||
|
}
|
||||||
|
for (let j = 0; j <= m && j <= i; j += 1) {
|
||||||
|
rhs = rhs + b[j] * x[i - j]
|
||||||
|
}
|
||||||
|
y[i] = (rhs - lhs) / a[0]
|
||||||
|
}
|
||||||
|
return y
|
||||||
|
}
|
||||||
|
return x
|
||||||
|
},
|
||||||
|
conv (x, h) {
|
||||||
|
let disp = 0
|
||||||
|
const y = []
|
||||||
|
for (let k = 0; k < h.length; k += 1) {
|
||||||
|
y.push(x[0] * h[k])
|
||||||
|
}
|
||||||
|
disp = disp + 1
|
||||||
|
for (let j = 1; j < x.length; j += 1) {
|
||||||
|
for (let k = 0; k < h.length; k += 1) {
|
||||||
|
if (disp + k !== y.length) {
|
||||||
|
y[disp + k] = y[disp + k] + x[j] * h[k]
|
||||||
|
} else {
|
||||||
|
y.push(x[j] * h[k])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
disp = disp + 1
|
||||||
|
}
|
||||||
|
return y
|
||||||
|
},
|
||||||
|
redrawIO (data, figure) {
|
||||||
|
const x = figure.data[0].x
|
||||||
|
const y = figure.data[0].y
|
||||||
|
const lineColor = figure.data[0].marker.line.color
|
||||||
|
const color = figure.data[0].marker.color
|
||||||
|
x.length = 0
|
||||||
|
y.length = 0
|
||||||
|
lineColor.length = 0
|
||||||
|
color.length = 0
|
||||||
|
for (let i = 0; i < this.length; i += 1) {
|
||||||
|
if (this.stem) {
|
||||||
|
figure.data[0].mode = 'lines+markers'
|
||||||
|
x.push(i, i, null)
|
||||||
|
y.push(0, data[i], null)
|
||||||
|
lineColor.push(
|
||||||
|
'rgba(0,0,0,0)',
|
||||||
|
'rgb(0,113.985,188.955)',
|
||||||
|
'rgba(0,0,0,0)'
|
||||||
|
)
|
||||||
|
color.push('rgba(0,0,0,0)', 'rgba(0,0,0,0)', 'rgba(0,0,0,0)')
|
||||||
|
} else {
|
||||||
|
figure.data[0].mode = 'lines'
|
||||||
|
x.push(i)
|
||||||
|
y.push(data[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Plotly.redraw(document.getElementById('input'))
|
||||||
|
Plotly.redraw(document.getElementById('output'))
|
||||||
|
},
|
||||||
|
freqz (ob, oa, oz) {
|
||||||
|
let b = ob.slice()
|
||||||
|
let a = oa.slice()
|
||||||
|
if (b.length > a.length) {
|
||||||
|
a = a.slice().concat(Array(b.length - a.length).fill(0))
|
||||||
|
} else if (b.length < a.length) {
|
||||||
|
b = b.slice().concat(Array(a.length - b.length).fill(0))
|
||||||
|
}
|
||||||
|
const H = []
|
||||||
|
for (let i = 0; i < oz.length; i += 1) {
|
||||||
|
const z = math.conj(oz[i])
|
||||||
|
let B = math.complex(0, 0)
|
||||||
|
let A = math.complex(0, 0)
|
||||||
|
for (let i = 0; i < b.length; i += 1) {
|
||||||
|
B = math.add(B, math.multiply(b[i], math.pow(z, i)))
|
||||||
|
A = math.add(A, math.multiply(a[i], math.pow(z, i)))
|
||||||
|
}
|
||||||
|
H.push(math.round(math.divide(B, A), 5))
|
||||||
|
}
|
||||||
|
return H
|
||||||
|
},
|
||||||
|
unwrap (op) {
|
||||||
|
const p = op.slice()
|
||||||
|
const dp = []
|
||||||
|
const dps = []
|
||||||
|
const dpcorr = []
|
||||||
|
const cumsum = []
|
||||||
|
const cutoff = Math.PI
|
||||||
|
for (let i = 0; i < p.length - 1; i += 1) {
|
||||||
|
dp[i] = p[i + 1] - p[i]
|
||||||
|
}
|
||||||
|
for (let i = 0; i < p.length - 1; i += 1) {
|
||||||
|
dps[i] =
|
||||||
|
dp[i] +
|
||||||
|
Math.PI -
|
||||||
|
Math.floor((dp[i] + Math.PI) / (2 * Math.PI)) * (2 * Math.PI) -
|
||||||
|
Math.PI
|
||||||
|
}
|
||||||
|
for (let i = 0; i < p.length - 1; i += 1) {
|
||||||
|
if (dps[i] === -Math.PI && dp[i] > 0) {
|
||||||
|
dps[i] = Math.PI
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (let i = 0; i < p.length - 1; i += 1) {
|
||||||
|
dpcorr[i] = dps[i] - dp[i]
|
||||||
|
}
|
||||||
|
for (let i = 0; i < p.length - 1; i += 1) {
|
||||||
|
if (Math.abs(dp[i]) < cutoff) {
|
||||||
|
dpcorr[i] = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cumsum[0] = dpcorr[0]
|
||||||
|
for (let i = 1; i < p.length - 1; i += 1) {
|
||||||
|
cumsum[i] = cumsum[i - 1] + dpcorr[i]
|
||||||
|
}
|
||||||
|
for (let i = 1; i < p.length; i += 1) {
|
||||||
|
p[i] += cumsum[i - 1]
|
||||||
|
}
|
||||||
|
return p
|
||||||
|
},
|
||||||
|
redrawFR () {
|
||||||
|
const mags1 = []
|
||||||
|
const mags2 = []
|
||||||
|
const phases1 = []
|
||||||
|
const phases2 = []
|
||||||
|
const H = this.freqz(this.b, this.a, this.z)
|
||||||
|
for (let i = 0; i < H.length; i += 1) {
|
||||||
|
const mag = Math.sqrt(Math.pow(H[i].re, 2) + Math.pow(H[i].im, 2))
|
||||||
|
const phase = atan2(H[i].im, H[i].re)
|
||||||
|
if (i < 512) {
|
||||||
|
mags1.push(20 * Math.log10(mag))
|
||||||
|
phases1.push(phase)
|
||||||
|
} else {
|
||||||
|
mags2.push(20 * Math.log10(mag))
|
||||||
|
phases2.push(phase)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const unwrap1 = this.unwrap(phases1).map(x => (x * 180) / Math.PI)
|
||||||
|
const unwrap2 = this.unwrap(phases2).map(x => (x * 180) / Math.PI)
|
||||||
|
mags1[511] = null
|
||||||
|
unwrap1[511] = null
|
||||||
|
mags2[0] = null
|
||||||
|
unwrap2[0] = null
|
||||||
|
figureMag.data[0].y = mags1.concat(mags2)
|
||||||
|
figurePhase.data[0].y = unwrap1.concat(unwrap2)
|
||||||
|
Plotly.redraw(document.getElementById('magnitude'))
|
||||||
|
Plotly.redraw(document.getElementById('phase'))
|
||||||
|
function atan2 (im, re) {
|
||||||
|
if (im === 0 && re === 0) {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return Math.atan2(im, re)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
drawBuffer (width, height, context, buffer) {
|
||||||
|
context.clearRect(0, 0, width, height)
|
||||||
|
const data = buffer
|
||||||
|
const step = Math.ceil(data.length / width)
|
||||||
|
const amp = height / 2
|
||||||
|
for (let i = 0; i < width; i++) {
|
||||||
|
let min = 1.0
|
||||||
|
let max = -1.0
|
||||||
|
for (let j = 0; j < step; j++) {
|
||||||
|
const datum = data[i * step + j]
|
||||||
|
if (datum < min) min = datum
|
||||||
|
if (datum > max) max = datum
|
||||||
|
}
|
||||||
|
context.fillStyle = '#0072BD'
|
||||||
|
context.fillRect(i, (1 + min) * amp, 1, Math.max(1, (max - min) * amp))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
reverb () {
|
||||||
|
const canvas = document.getElementById('waveform3')
|
||||||
|
const audioSource = new Audio('asset/sample.mp3')
|
||||||
|
const audioCtx = new AudioContext()
|
||||||
|
const audioInput = audioCtx.createMediaElementSource(audioSource)
|
||||||
|
const convolver = audioCtx.createConvolver()
|
||||||
|
const gain = audioCtx.createGain()
|
||||||
|
const analyser = audioCtx.createAnalyser()
|
||||||
|
const waveform = new Float32Array(analyser.frequencyBinCount)
|
||||||
|
let request
|
||||||
|
let chunks = new Float32Array(0)
|
||||||
|
gain.gain.value = 3.5
|
||||||
|
audioSource.onended = e => {
|
||||||
|
cancelAnimationFrame(request)
|
||||||
|
audioCtx.close()
|
||||||
|
this.drawBuffer(
|
||||||
|
canvas.width,
|
||||||
|
canvas.height,
|
||||||
|
canvas.getContext('2d'),
|
||||||
|
chunks
|
||||||
|
)
|
||||||
|
}
|
||||||
|
fetch('asset/clap.mp3')
|
||||||
|
.then(response => response.arrayBuffer())
|
||||||
|
.then(arrayBuffer => audioCtx.decodeAudioData(arrayBuffer))
|
||||||
|
.then(buffer => {
|
||||||
|
convolver.buffer = buffer
|
||||||
|
audioInput
|
||||||
|
.connect(convolver)
|
||||||
|
.connect(gain)
|
||||||
|
.connect(analyser)
|
||||||
|
.connect(audioCtx.destination)
|
||||||
|
audioSource.play()
|
||||||
|
updateWaveform()
|
||||||
|
})
|
||||||
|
function updateWaveform () {
|
||||||
|
request = requestAnimationFrame(updateWaveform)
|
||||||
|
analyser.getFloatTimeDomainData(waveform)
|
||||||
|
chunks = Float32Concat(chunks, waveform)
|
||||||
|
}
|
||||||
|
function Float32Concat (first, second) {
|
||||||
|
const firstLength = first.length
|
||||||
|
const result = new Float32Array(firstLength + second.length)
|
||||||
|
result.set(first)
|
||||||
|
result.set(second, firstLength)
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted () {
|
||||||
|
const input = document.getElementById('input')
|
||||||
|
const output = document.getElementById('output')
|
||||||
|
const magnitude = document.getElementById('magnitude')
|
||||||
|
const phase = document.getElementById('phase')
|
||||||
|
|
||||||
|
for (let i = 0; i <= 1023; i += 1) {
|
||||||
|
this.w.push((i * (2 * Math.PI)) / 1023)
|
||||||
|
this.z.push(math.exp(math.complex(0, this.w[i])))
|
||||||
|
}
|
||||||
|
|
||||||
|
figurePhase.layout.yaxis.title = 'Phase (degrees)'
|
||||||
|
figureMag.data[0].x = this.w.map(x => x / Math.PI)
|
||||||
|
figurePhase.data[0].x = this.w.map(x => x / Math.PI)
|
||||||
|
Plotly.plot(input, { data: figureIn.data, layout: figureIn.layout })
|
||||||
|
Plotly.plot(output, { data: figureOut.data, layout: figureOut.layout })
|
||||||
|
Plotly.plot(magnitude, { data: figureMag.data, layout: figureMag.layout })
|
||||||
|
Plotly.plot(phase, { data: figurePhase.data, layout: figurePhase.layout })
|
||||||
|
this.redrawIO(this.x, this.figureIn)
|
||||||
|
this.redrawIO(this.y, this.figureOut)
|
||||||
|
this.redrawFR()
|
||||||
|
this.fileReader.onload = e => {
|
||||||
|
const json = JSON.parse(this.fileReader.result)
|
||||||
|
this.a = json.a
|
||||||
|
this.b = json.b
|
||||||
|
this.p = this.a.length - 1
|
||||||
|
this.q = this.b.length - 1
|
||||||
|
this.output()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
13
Home/LTI/webpack.config.js
Normal file
13
Home/LTI/webpack.config.js
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
const path = require('path')
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
mode: 'none',
|
||||||
|
entry: './src/main.dev.js',
|
||||||
|
output: {
|
||||||
|
path: path.resolve(__dirname, './'),
|
||||||
|
filename: 'main.js'
|
||||||
|
},
|
||||||
|
module: {
|
||||||
|
rules: [{ test: /\.js$/, exclude: /node_modules/, loader: 'babel-loader' }]
|
||||||
|
}
|
||||||
|
}
|
BIN
Home/image/bg.jpg
Normal file
BIN
Home/image/bg.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 84 KiB |
47
Home/index.html
Normal file
47
Home/index.html
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>S10659043</title>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
font-family: "Times New Roman", serif;
|
||||||
|
font-size: 14pt;
|
||||||
|
background: url(image/bg.jpg) no-repeat center center fixed;
|
||||||
|
background-size: cover;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
width: 80%;
|
||||||
|
height: 20rem;
|
||||||
|
margin: 5rem auto;
|
||||||
|
padding: 0.1rem 2rem;
|
||||||
|
border-radius: 1rem;
|
||||||
|
background-color: rgba(255, 255, 255, 0.7);
|
||||||
|
}
|
||||||
|
|
||||||
|
li {
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul a {
|
||||||
|
color: rgb(55, 55, 55);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="container">
|
||||||
|
<h1>My projects</h1>
|
||||||
|
<ul>
|
||||||
|
<li>Signals & Systems</li>
|
||||||
|
<ol>
|
||||||
|
<li><a href="LTI">LTI system: Time & Freqency Response Analysis</a></li>
|
||||||
|
<li><a href="LTI/ppt">Presentation</a></li>
|
||||||
|
</ol>
|
||||||
|
<li>Concepts of Programming Languages</li>
|
||||||
|
<ol>
|
||||||
|
<li><a href="Compiler">Lexical, Syntax & Semantic Analysis</a></li>
|
||||||
|
</ol>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
2
Home/robots.txt
Normal file
2
Home/robots.txt
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
User-agent: *
|
||||||
|
Disallow: /
|
Loading…
Reference in New Issue
Block a user