Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 28 additions & 28 deletions src/ast/types/ast.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { CompilationUnit } from "./packages-and-modules";
import { CompilationUnit } from './packages-and-modules'
import {
Assignment,
Block,
Expand All @@ -8,44 +8,44 @@ import {
Expression,
ExpressionStatement,
MethodInvocation,
ReturnStatement,
} from "./blocks-and-statements";
ReturnStatement
} from './blocks-and-statements'
import {
ConstructorDeclaration,
FieldDeclaration,
MethodDeclaration,
NormalClassDeclaration,
} from "./classes";
NormalClassDeclaration
} from './classes'

interface NodeMap {
CompilationUnit: CompilationUnit;
MethodDeclaration: MethodDeclaration;
FieldDeclaration: FieldDeclaration;
Block: Block;
BlockStatement: BlockStatement;
Expression: Expression;
Assignment: Assignment;
ExpressionStatement: ExpressionStatement;
MethodInvocation: MethodInvocation;
ReturnStatement: ReturnStatement;
NormalClassDeclaration: NormalClassDeclaration;
ClassInstanceCreationExpression: ClassInstanceCreationExpression;
ConstructorDeclaration: ConstructorDeclaration;
ExplicitConstructorInvocation: ExplicitConstructorInvocation;
CompilationUnit: CompilationUnit
MethodDeclaration: MethodDeclaration
FieldDeclaration: FieldDeclaration
Block: Block
BlockStatement: BlockStatement
Expression: Expression
Assignment: Assignment
ExpressionStatement: ExpressionStatement
MethodInvocation: MethodInvocation
ReturnStatement: ReturnStatement
NormalClassDeclaration: NormalClassDeclaration
ClassInstanceCreationExpression: ClassInstanceCreationExpression
ConstructorDeclaration: ConstructorDeclaration
ExplicitConstructorInvocation: ExplicitConstructorInvocation
}

export type Node = NodeMap[keyof NodeMap];
export type Node = NodeMap[keyof NodeMap]

export interface Location {
startOffset: number;
startLine: number;
startColumn?: number;
endOffset?: number;
endLine?: number;
endColumn?: number;
startOffset: number
startLine: number
startColumn?: number
endOffset?: number
endLine?: number
endColumn?: number
}

export interface BaseNode {
kind: string;
location?: Location;
kind: string
location?: Location
}
216 changes: 127 additions & 89 deletions src/ast/utils/astToString.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Node } from '../types/ast';
import { NativeDeclaration } from '../../ec-evaluator'
import { Node } from '../types/ast'
import {
Assignment,
BinaryExpression,
Expand All @@ -10,122 +11,159 @@ import {
Literal,
LocalVariableDeclarationStatement,
MethodInvocation,
ReturnStatement,
} from '../types/blocks-and-statements';
ReturnStatement
} from '../types/blocks-and-statements'
import {
ConstructorDeclaration,
FieldDeclaration,
MethodDeclaration,
NormalClassDeclaration,
} from '../types/classes';
NormalClassDeclaration
} from '../types/classes'

const newline = (line: string): string => {
return `${line}\n`;
return `${line}\n`
}

const indentLine = (lvl: number, line: string): string => {
return `${' '.repeat(lvl)}${line}`;
return `${' '.repeat(lvl)}${line}`
}

const INDENT_SPACES = 2;
const INDENT_SPACES = 2

export const astToString = (node: Node, indent: number = 0): string => {
export const astToString = (node: Node | NativeDeclaration, indent: number = 0): string => {
switch (node.kind) {
case "NormalClassDeclaration":
const c = node as NormalClassDeclaration;
const cModifier = c.classModifier.length > 0 ? c.classModifier.join(" ") + " " : "";
const cSuperclass = c.sclass ? " extends " + c.sclass : "";
return newline(indentLine(indent, `${cModifier}class ${c.typeIdentifier}${cSuperclass} {`))
+ `${c.classBody.map(b => newline(astToString(b, indent + INDENT_SPACES))).join("")}`
+ `${indentLine(indent, "}")}`;

case "Block":
const block = node as Block;
return `${newline(indentLine(indent, "{"))}`
+ `${block.blockStatements.map(s => newline(astToString(s, indent + INDENT_SPACES))).join("")}`
+ `${indentLine(indent, "}")}`;

case "ConstructorDeclaration":
const con = node as ConstructorDeclaration;
const conModifier = con.constructorModifier.length > 0
? con.constructorModifier.join(" ") + " "
: "";
const conIdentifier = con.constructorDeclarator.identifier;
const conParams = con.constructorDeclarator.formalParameterList.map(p => `${p.unannType} ${p.identifier}`).join(", ");
return newline(indentLine(indent, `${conModifier}${conIdentifier}(${conParams}) {`))
+ `${con.constructorBody.blockStatements.map(s => newline(astToString(s, indent + INDENT_SPACES))).join("")}`
+ `${indentLine(indent, "}")}`;

case "MethodDeclaration":
const mtd = node as MethodDeclaration;
const mtdModifier = mtd.methodModifier.length > 0 ? mtd.methodModifier.join(" ") + " " : "";
const mtdRes = mtd.methodHeader.result;
const mtdIdentifier = mtd.methodHeader.identifier;
const mtdParams = mtd.methodHeader.formalParameterList.map(p => `${p.unannType} ${p.identifier}`).join(", ");
return newline(indentLine(indent, `${mtdModifier}${mtdRes} ${mtdIdentifier}(${mtdParams}) {`))
+ `${mtd.methodBody.blockStatements.map(s => newline(astToString(s, indent + INDENT_SPACES))).join("")}`
+ `${indentLine(indent, "}")}`;

case "FieldDeclaration":
const field = node as FieldDeclaration;
const fieldModifier = field.fieldModifier.length > 0 ? field.fieldModifier.join(" ") + " " : "";
const fieldType = field.fieldType;
const fieldIdentifier = field.variableDeclaratorList[0].variableDeclaratorId;
case 'NormalClassDeclaration':
const c = node as NormalClassDeclaration
const cModifier = c.classModifier.length > 0 ? c.classModifier.join(' ') + ' ' : ''
const cSuperclass = c.sclass ? ' extends ' + c.sclass : ''
return (
newline(indentLine(indent, `${cModifier}class ${c.typeIdentifier}${cSuperclass} {`)) +
`${c.classBody.map(b => newline(astToString(b, indent + INDENT_SPACES))).join('')}` +
`${indentLine(indent, '}')}`
)

case 'Block':
const block = node as Block
return (
`${newline(indentLine(indent, '{'))}` +
`${block.blockStatements.map(s => newline(astToString(s, indent + INDENT_SPACES))).join('')}` +
`${indentLine(indent, '}')}`
)

case 'ConstructorDeclaration':
const con = node as ConstructorDeclaration
const conModifier =
con.constructorModifier.length > 0 ? con.constructorModifier.join(' ') + ' ' : ''
const conIdentifier = con.constructorDeclarator.identifier
const conParams = con.constructorDeclarator.formalParameterList
.map(p => `${p.unannType} ${p.identifier}`)
.join(', ')
return (
newline(indentLine(indent, `${conModifier}${conIdentifier}(${conParams}) {`)) +
`${con.constructorBody.blockStatements.map(s => newline(astToString(s, indent + INDENT_SPACES))).join('')}` +
`${indentLine(indent, '}')}`
)

case 'MethodDeclaration':
const normalMtd = node as MethodDeclaration
const normalMtdModifier =
normalMtd.methodModifier.length > 0 ? normalMtd.methodModifier.join(' ') + ' ' : ''
const normalMtdRes = normalMtd.methodHeader.result
const normalMtdIdentifier = normalMtd.methodHeader.identifier
const normalMtdParams = normalMtd.methodHeader.formalParameterList
.map(p => `${p.unannType} ${p.identifier}`)
.join(', ')
return (
newline(
indentLine(
indent,
`${normalMtdModifier}${normalMtdRes} ${normalMtdIdentifier}(${normalMtdParams}) {`
)
) +
`${normalMtd.methodBody.blockStatements.map(s => newline(astToString(s, indent + INDENT_SPACES))).join('')}` +
`${indentLine(indent, '}')}`
)

case 'NativeDeclaration':
const nativeMtd = node as NativeDeclaration
const nativeMtdModifier =
nativeMtd.methodModifier.length > 0 ? nativeMtd.methodModifier.join(' ') + ' ' : ''
const nativeMtdRes = nativeMtd.methodHeader.result
const nativeMtdIdentifier = nativeMtd.methodHeader.identifier
const nativeMtdParams = nativeMtd.methodHeader.formalParameterList
.map(p => `${p.unannType} ${p.identifier}`)
.join(', ')
return newline(
indentLine(
indent,
`${nativeMtdModifier}${nativeMtdRes} ${nativeMtdIdentifier}(${nativeMtdParams});`
)
)

case 'FieldDeclaration':
const field = node as FieldDeclaration
const fieldModifier =
field.fieldModifier.length > 0 ? field.fieldModifier.join(' ') + ' ' : ''
const fieldType = field.fieldType
const fieldIdentifier = field.variableDeclaratorList[0].variableDeclaratorId
const fieldInit = field.variableDeclaratorList[0].variableInitializer
? ` = ${astToString(field.variableDeclaratorList[0].variableInitializer! as ExpressionName)}`
: "";
return indentLine(indent, `${fieldModifier}${fieldType} ${fieldIdentifier}${fieldInit};`);
: ''
return indentLine(indent, `${fieldModifier}${fieldType} ${fieldIdentifier}${fieldInit};`)

case "LocalVariableDeclarationStatement":
const localVar = node as LocalVariableDeclarationStatement;
const localVarType = localVar.localVariableType;
const localVarIdentifier = localVar.variableDeclaratorList[0].variableDeclaratorId;
case 'LocalVariableDeclarationStatement':
const localVar = node as LocalVariableDeclarationStatement
const localVarType = localVar.localVariableType
const localVarIdentifier = localVar.variableDeclaratorList[0].variableDeclaratorId
const localVarInit = localVar.variableDeclaratorList[0].variableInitializer
? ` = ${astToString(localVar.variableDeclaratorList[0].variableInitializer! as ExpressionName)}`
: "";
return indentLine(indent, `${localVarType} ${localVarIdentifier}${localVarInit};`);
: ''
return indentLine(indent, `${localVarType} ${localVarIdentifier}${localVarInit};`)

case "ReturnStatement":
const returnStmt = node as ReturnStatement;
const returnExp = returnStmt.exp.kind === "Void" ? "" : ` ${astToString(returnStmt.exp)}`;
return indentLine(indent, `return${returnExp};`);
case 'ReturnStatement':
const returnStmt = node as ReturnStatement
const returnExp = returnStmt.exp.kind === 'Void' ? '' : ` ${astToString(returnStmt.exp)}`
return indentLine(indent, `return${returnExp};`)

case "ExpressionStatement":
const expStmt = node as ExpressionStatement;
return indentLine(indent, `${astToString(expStmt.stmtExp)};`);
case 'ExpressionStatement':
const expStmt = node as ExpressionStatement
return indentLine(indent, `${astToString(expStmt.stmtExp)};`)

case "Assignment":
const assmt = node as Assignment;
return `${(assmt.left as ExpressionName).name} = ${astToString(assmt.right)}`;
case 'Assignment':
const assmt = node as Assignment
return `${(assmt.left as ExpressionName).name} = ${astToString(assmt.right)}`

case "MethodInvocation":
const mtdInv = node as MethodInvocation;
return `${mtdInv.identifier}(${mtdInv.argumentList.map(a => astToString(a)).join(", ")})`
case 'MethodInvocation':
const mtdInv = node as MethodInvocation
return `${mtdInv.identifier}(${mtdInv.argumentList.map(a => astToString(a)).join(', ')})`

case "ClassInstanceCreationExpression":
const classInstanceCreationExp = node as ClassInstanceCreationExpression;
return `new ${classInstanceCreationExp.identifier}(${classInstanceCreationExp.argumentList.map(a => astToString(a))})`;
case 'ClassInstanceCreationExpression':
const classInstanceCreationExp = node as ClassInstanceCreationExpression
return `new ${classInstanceCreationExp.identifier}(${classInstanceCreationExp.argumentList.map(a => astToString(a))})`

case "ExplicitConstructorInvocation":
const expConInv = node as ExplicitConstructorInvocation;
return indentLine(indent, `${expConInv.thisOrSuper}(${expConInv.argumentList.map(a => astToString(a))});`);
case 'ExplicitConstructorInvocation':
const expConInv = node as ExplicitConstructorInvocation
return indentLine(
indent,
`${expConInv.thisOrSuper}(${expConInv.argumentList.map(a => astToString(a))});`
)

case "BinaryExpression":
const bin = node as BinaryExpression;
return `${astToString(bin.left)} ${bin.operator} ${astToString(bin.right)}`;
case 'BinaryExpression':
const bin = node as BinaryExpression
return `${astToString(bin.left)} ${bin.operator} ${astToString(bin.right)}`

case "ExpressionName":
const exp = node as ExpressionName;
return exp.name;
case 'ExpressionName':
const exp = node as ExpressionName
return exp.name

case "Literal":
const literal = node as Literal;
return `${literal.literalType.value}`;
case 'Literal':
const literal = node as Literal
return `${literal.literalType.value}`

case "Void":
return "void";
case 'Void':
return 'void'

default:
return node.kind;
return node.kind
}
}
}
Loading
Loading