Skip to content

Commit b79b5bb

Browse files
committed
complex
1 parent ea03644 commit b79b5bb

File tree

5 files changed

+115
-21
lines changed

5 files changed

+115
-21
lines changed

packages/jsmasm/.vscode/launch.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
"<node_internals>/**"
2121
],
2222
"program": "${workspaceFolder}\\dist\\app.js",
23-
"preLaunchTask": "tsc: build - tsconfig.json",
23+
"preLaunchTask": "tsc: watch - tsconfig.json",
2424
"outFiles": [
2525
"${workspaceFolder}/dist/**/*.js"
2626
]

packages/jsmasm/src/app.ts

+5-5
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,11 @@ END BEG
2424
`; // Replace with your file path
2525
let lexer = new Lexer(input);
2626

27-
// let token: Token;
28-
// while ((token = lexer.nextToken()).type !== TokenType.EOF) {
29-
// console.log(token);
30-
// }
31-
// lexer = new Lexer(input);
27+
let token: Token;
28+
while ((token = lexer.nextToken()).type !== TokenType.EOF) {
29+
console.log(token);
30+
}
31+
lexer = new Lexer(input);
3232

3333
const parser = new Parser(lexer);
3434
const ast = parser.parse();

packages/jsmasm/src/ast.ts

+25-1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ export interface Location {
3030
| ProcedureDeclaration
3131
| ProcedureEnd
3232
| DataDeclaration
33+
| AssumeDirective
3334
| IncludeDirective;
3435

3536
// 段声明
@@ -100,6 +101,24 @@ export interface Location {
100101
type: "ExpressionOperand";
101102
expression: Expression;
102103
}
104+
105+
export type DataExpression={
106+
type:"DataExpression",
107+
value:string
108+
| NumericLiteralExpression
109+
| DupExpression,
110+
location:Location
111+
}
112+
113+
export type DupExpression={
114+
type:"DupExpression",
115+
value:NumericLiteralExpression[]|string|DupQuestionMark
116+
times:number
117+
}
118+
119+
export type DupQuestionMark={
120+
type:"DupQuestionMark"
121+
}
103122

104123
// 表达式类型
105124
export type Expression =
@@ -187,7 +206,7 @@ export interface Location {
187206
type: "DataDeclaration";
188207
name: string;
189208
dataType: string; // DB, DW, DD, ...
190-
initialValue: Expression | string; // 可以是表达式或字符串
209+
value: DataExpression[]; // 可以是表达式或字符串
191210
}
192211

193212
// 指令
@@ -201,4 +220,9 @@ export interface Location {
201220
export interface IncludeDirective extends ASTNode {
202221
type: "IncludeDirective";
203222
filename: string;
223+
}
224+
225+
export interface AssumeDirective extends ASTNode{
226+
type:"AssumeDirective"
227+
pair:{register:string,segment:string}[]
204228
}

packages/jsmasm/src/lexer.ts

+11-8
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,13 @@ export class Lexer {
6666
this.input = input;
6767
}
6868

69-
peek(): string {
69+
private peek(): string {
7070
return this.input[this.position];
7171
}
72+
73+
public nextchar():string{
74+
return this.input[this.position+1];
75+
}
7276

7377
private advance(): string {
7478
const char = this.peek();
@@ -87,15 +91,15 @@ export class Lexer {
8791
}
8892

8993
private isDigit(char: string): boolean {
90-
return /[0-9]/.test(char);
94+
return /[0-9A-Fa-fHBhb]/.test(char);
9195
}
9296

9397
private isAlphanumeric(char: string): boolean {
9498
return this.isAlpha(char) || this.isDigit(char);
9599
}
96100

97101
private isWhitespace(char: string): boolean {
98-
return /\s/.test(char);
102+
return /[\s]/.test(char);
99103
}
100104

101105
private skipWhitespace(): void {
@@ -105,6 +109,10 @@ export class Lexer {
105109
}
106110

107111
public nextToken(): Token {
112+
if (this.peek() === "\n") {
113+
this.advance();
114+
return {type: TokenType.NEWLINE, value: "\n", location: {line:this.line, column:this.column}}
115+
}
108116
this.skipWhitespace();
109117

110118
if (this.position >= this.input.length) {
@@ -223,11 +231,6 @@ export class Lexer {
223231
}
224232
}
225233

226-
if (char === "\n") {
227-
this.advance();
228-
return {type: TokenType.NEWLINE, value: "\n", location: {line, column}}
229-
}
230-
231234
return { type: TokenType.ERROR, value: this.advance(), location: { line, column } };
232235
}
233236
}

packages/jsmasm/src/parser.ts

+73-6
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@
22
import { Lexer, Token, TokenType } from "./lexer";
33
import * as AST from "./ast";
44

5+
6+
function parseNumber(input: string) {
7+
return parseInt(input)
8+
}
9+
510
export class Parser {
611
private lexer: Lexer;
712
private currentToken: Token;
@@ -11,12 +16,12 @@ export class Parser {
1116
constructor(lexer: Lexer) {
1217
this.lexer = lexer;
1318
this.currentToken = this.lexer.nextToken();
14-
this.nextToken=this.lexer.nextToken();
19+
this.nextToken = this.lexer.nextToken();
1520
}
1621

17-
public next(){
18-
this.currentToken=this.nextToken;
19-
this.nextToken=this.lexer.nextToken();
22+
public next() {
23+
this.currentToken = this.nextToken;
24+
this.nextToken = this.lexer.nextToken();
2025
return this.currentToken
2126
}
2227

@@ -54,6 +59,45 @@ export class Parser {
5459
};
5560
}
5661

62+
private parseDataDeclaration(): AST.DataDeclaration {
63+
const name = this.eat(TokenType.IDENTIFIER).value;
64+
const dataType = this.eat(this.currentToken.type).value;
65+
let value: AST.DataExpression[] = []
66+
while (this.currentToken.type !== TokenType.NEWLINE) {
67+
if (this.currentToken.type === TokenType.COMMA) {
68+
this.eat(TokenType.COMMA)
69+
continue
70+
}
71+
if (this.currentToken.type === TokenType.STRING) {
72+
let a: AST.DataExpression = {
73+
type: "DataExpression",
74+
value: this.eat(TokenType.STRING).value,
75+
location: this.currentToken.location
76+
}
77+
value.push(a)
78+
}
79+
if (this.currentToken.type === TokenType.NUMBER) {
80+
let a: AST.DataExpression = {
81+
type: "DataExpression",
82+
value: {
83+
"type": "NumericLiteralExpression",
84+
value: parseNumber(this.eat(TokenType.NUMBER).value),
85+
location: this.currentToken.location
86+
},
87+
location: this.currentToken.location
88+
}
89+
value.push(a)
90+
}
91+
}
92+
return {
93+
type: "DataDeclaration",
94+
name,
95+
dataType,
96+
value,
97+
location: this.currentToken.location,
98+
};
99+
}
100+
57101
private parseSegmentEnd(): AST.SegmentEnd {
58102
const name = this.eat(TokenType.IDENTIFIER).value;
59103
this.eat(TokenType.ENDS);
@@ -76,6 +120,22 @@ export class Parser {
76120
return { type: "Instruction", mnemonic, operands, location: this.currentToken.location };
77121
}
78122

123+
private parseAssume(): AST.AssumeDirective {
124+
let out: AST.AssumeDirective = {
125+
"type": "AssumeDirective",
126+
"pair": [],
127+
"location": this.currentToken.location
128+
};
129+
this.eat(this.currentToken.type)
130+
while(this.currentToken.type!==TokenType.NEWLINE){
131+
const register=this.eat(this.currentToken.type).value;
132+
this.eat(TokenType.COLON)
133+
const segment=this.eat(this.currentToken.type).value
134+
out.pair.push({register,segment})
135+
}
136+
return out
137+
}
138+
79139
private parseOperand(): AST.Operand {
80140
if (this.currentToken.type === TokenType.IDENTIFIER) {
81141
if (this.nextToken.value === ":") {
@@ -131,7 +191,7 @@ export class Parser {
131191
const name = this.eat(TokenType.DIRECTIVE).value;
132192
const args: AST.Expression[] = [];
133193
if (this.currentToken.type === TokenType.STRING) {
134-
args.push({type: "StringLiteralExpression", name:"debug!!!!",value: this.eat(TokenType.STRING).value, location: this.currentToken.location});
194+
args.push({ type: "StringLiteralExpression", name: "debug!!!!", value: this.eat(TokenType.STRING).value, location: this.currentToken.location });
135195
}
136196

137197
return { type: "Directive", name, arguments: args, location: this.currentToken.location };
@@ -151,7 +211,12 @@ export class Parser {
151211
if (this.currentToken.type === TokenType.IDENTIFIER) {
152212
if (this.nextToken.value === "SEGMENT") {
153213
return this.parseSegmentDeclaration();
154-
} else if (this.nextToken.value === "ENDS") {
214+
}
215+
else if ([TokenType.DB, TokenType.DW, TokenType.DD].some(a => a === this.nextToken.type)) {
216+
return this.parseDataDeclaration();
217+
}
218+
219+
else if (this.nextToken.value === "ENDS") {
155220
return this.parseSegmentEnd();
156221
} else if (this.nextToken.value === ":") {
157222
return this.parseLabel();
@@ -164,6 +229,8 @@ export class Parser {
164229
} else {
165230
return this.parseDirective();
166231
}
232+
}else if(this.currentToken.type===TokenType.ASSUME){
233+
return this.parseAssume()
167234
}
168235
return null;
169236
}

0 commit comments

Comments
 (0)