Skip to content

Commit

Permalink
Otimização de desempenho da análise semântica
Browse files Browse the repository at this point in the history
  • Loading branch information
dgadelha committed Mar 10, 2024
1 parent 4619cce commit 5c5293d
Show file tree
Hide file tree
Showing 79 changed files with 618 additions and 1,011 deletions.
65 changes: 24 additions & 41 deletions packages/antlr/src/PortugolErrorListener.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,21 +50,10 @@ export class PortugolCodeError extends Error {

const possibleSymbol = ctx.getPayload() as Token | ParseTree | ParserRuleContext | undefined;

if (
possibleSymbol &&
possibleSymbol.hasOwnProperty("column") &&
possibleSymbol.hasOwnProperty("line")
) {
if (possibleSymbol && possibleSymbol.hasOwnProperty("column") && possibleSymbol.hasOwnProperty("line")) {
const { line, column } = possibleSymbol as unknown as Token;

return new PortugolCodeError(
message,
ctx,
line,
column,
line,
column + ctx.getText().length,
);
return new PortugolCodeError(message, ctx, line, column, line, column + ctx.getText().length);
}

return new PortugolCodeError(message, ctx, 1, 1, 1, 2 + ctx.getText().length);
Expand Down Expand Up @@ -99,36 +88,30 @@ export class PortugolErrorListener implements ANTLRErrorListener {
}

reportAmbiguity(
recognizer: Parser,
dfa: DFA,
startIndex: number,
stopIndex: number,
exact: boolean,
ambigAlts: BitSet | undefined,
configs: ATNConfigSet,
) {
console.debug("reportAmbiguity", { recognizer, dfa, startIndex, stopIndex, exact, ambigAlts, configs });
}
_recognizer: Parser,
_dfa: DFA,
_startIndex: number,
_stopIndex: number,
_exact: boolean,
_ambigAlts: BitSet | undefined,
_configs: ATNConfigSet,
) {}

reportAttemptingFullContext(
recognizer: Parser,
dfa: DFA,
startIndex: number,
stopIndex: number,
conflictingAlts: BitSet | undefined,
configs: ATNConfigSet,
) {
console.debug("reportAttemptingFullContext", { recognizer, dfa, startIndex, stopIndex, conflictingAlts, configs });
}
_recognizer: Parser,
_dfa: DFA,
_startIndex: number,
_stopIndex: number,
_conflictingAlts: BitSet | undefined,
_configs: ATNConfigSet,
) {}

reportContextSensitivity(
recognizer: Parser,
dfa: DFA,
startIndex: number,
stopIndex: number,
prediction: number,
configs: ATNConfigSet,
) {
console.debug("reportContextSensitivity", { recognizer, dfa, startIndex, stopIndex, prediction, configs });
}
_recognizer: Parser,
_dfa: DFA,
_startIndex: number,
_stopIndex: number,
_prediction: number,
_configs: ATNConfigSet,
) {}
}
2 changes: 1 addition & 1 deletion packages/ide/src/app/tab-start/tab-start.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,9 @@
<hr />

<h4>📰&nbsp;&nbsp;Novidades</h4>
<p><strong>10/03/2024:</strong> Otimização de desempenho na análise semântica</p>
<p><strong>09/03/2024:</strong> Novo domínio: <strong>portugol.dev</strong> e experimento com propagandas</p>
<p><strong>08/03/2024:</strong> Melhorias de performance na interface da plataforma</p>
<p><strong>17/01/2024:</strong> Melhorias nas verificações de erros (comparação lógica e bibliotecas)</p>
</section>

<ins
Expand Down
3 changes: 1 addition & 2 deletions packages/parser/src/PortugolErrorChecker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import { CharStream, CommonTokenStream } from "antlr4ng";

import errorCheckers from "./errors/index.js";
import { ParseError } from "./helpers/ParseError.js";
import { Arquivo } from "./nodes/index.js";
import { PortugolNode } from "./PortugolNode.js";

export class PortugolErrorChecker {
Expand All @@ -32,7 +31,7 @@ export class PortugolErrorChecker {
this.errorListener.reset();

try {
const arquivo = this.portugolNode.visit(tree) as Arquivo;
const arquivo = this.portugolNode.visit(tree);
const errors: PortugolCodeError[] = [];

for (const checker of errorCheckers) {
Expand Down
56 changes: 32 additions & 24 deletions packages/parser/src/PortugolNode.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { PortugolVisitor } from "@portugol-webstudio/antlr";
import { ParserRuleContext, ParseTree, AbstractParseTreeVisitor } from "antlr4ng";
import { ArquivoContext, PortugolVisitor } from "@portugol-webstudio/antlr";
import { ParseTree, AbstractParseTreeVisitor } from "antlr4ng";

import { Bypass, UnhandledNode, Node, ContextNodeMap } from "./nodes/index.js";
import { Node, Arquivo, ContextNodeObj, UnhandledNode, Bypass } from "./nodes/index.js";

export interface Empty {}

Expand All @@ -14,38 +14,46 @@ export class PortugolNode extends AbstractParseTreeVisitor<Empty> implements Por
throw new Error("Shouldn't need to aggregate results");
}

visitChildrenArray(node: ParseTree): Node[] {
const result: Array<Node | undefined> = [];
const n = node.getChildCount();
visitChildrenFromParent(ctx: ParseTree, parent: Node) {
for (let i = 0; i < ctx.getChildCount(); i++) {
const child = ctx.getChild(i);

for (let i = 0; i < n; i++) {
const c = node.getChild(i);
const childResult = this.visit(c!);

// Vírgulas
if (childResult instanceof UnhandledNode && childResult.type === "TerminalNode") {
if (!child || child.constructor.name === "TerminalNode") {
continue;
}

if (childResult instanceof Bypass) {
result.push(...this.visitChildrenArray(childResult.ctx as ParseTree));
continue;
}
this.visitFromParent(child, parent);
}
}

visitFromParent(ctx: ParseTree, parent: Node) {
const ctor = ContextNodeObj[ctx.constructor.name];
let obj;

result.push(childResult);
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
if (ctor) {
obj = new ctor(ctx);
} else {
obj = new UnhandledNode(ctx, ctx.constructor.name);
}

return result.map(x => x!);
if (obj instanceof Bypass) {
this.visitChildrenFromParent(ctx, parent);
} else {
parent.addChild(obj);
this.visitChildrenFromParent(ctx, obj);
}
}

visit(ctx: ParseTree) {
const children = this.visitChildrenArray(ctx);
const ctor = ContextNodeMap.get(ctx.constructor as new (...args: any[]) => ParserRuleContext);

if (ctor) {
return new ctor(ctx, children);
if (ctx.constructor.name !== "ArquivoContext") {
throw new Error("O algoritmo Portugol deve-se iniciar com um contexto de arquivo (palavra-chave 'programa')");
}

return new UnhandledNode(ctx, ctx.constructor.name, ctx.getText(), children);
const arquivo = new Arquivo(ctx as ArquivoContext);

this.visitChildrenFromParent(ctx, arquivo);

return arquivo;
}
}
8 changes: 5 additions & 3 deletions packages/parser/src/helpers/Tipo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,18 @@ export function parseTipoPrimitivo(tipo: TerminalNode | null): TipoPrimitivo {
return TipoPrimitivo.VAZIO;
}

switch (tipo.getText()) {
const text = tipo.getText();

switch (text) {
case "inteiro":
case "real":
case "cadeia":
case "logico":
case "vazio":
case "caracter":
return tipo.getText() as TipoPrimitivo;
return text as TipoPrimitivo;

default:
throw new Error(`Tipo desconhecido: ${tipo.getText()}`);
throw new Error(`Tipo desconhecido: ${text}`);
}
}
2 changes: 1 addition & 1 deletion packages/parser/src/helpers/expressões.ts
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ export function resolverResultadoExpressão(expressão: Expressão, escopo: Esco
case IncrementoUnárioPósfixadoExpr:
case DecrementoUnárioPrefixadoExpr:
case DecrementoUnárioPósfixadoExpr:
return resolverResultadoExpressão((expressão as ExpressãoUnária).variável, escopo);
return resolverResultadoExpressão((expressão as ExpressãoUnária<any>).variável, escopo);

case ExpressãoEntreParênteses:
return resolverResultadoExpressão((expressão as ExpressãoEntreParênteses).expressão, escopo);
Expand Down
29 changes: 12 additions & 17 deletions packages/parser/src/nodes/Arquivo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,27 +5,22 @@ import { Função } from "./Função.js";
import { InclusãoBiblioteca } from "./InclusãoBiblioteca.js";
import { Node } from "./Node.js";

export class Arquivo extends Node {
export class Arquivo extends Node<ArquivoContext> {
bibliotecas: InclusãoBiblioteca[] = [];
declarações: DeclaraçãoCmd[] = [];
funções: Função[] = [];

constructor(
public ctx: ArquivoContext,
public children: Node[],
) {
super();

for (const child of children) {
if (child instanceof Função) {
this.funções.push(child);
} else if (child instanceof InclusãoBiblioteca) {
this.bibliotecas.push(child);
} else if (child instanceof DeclaraçãoCmd) {
this.declarações.push(child);
} else {
this.unexpectedChild(child);
}
addChild(child: Node) {
if (child instanceof Função) {
this.funções.push(child);
} else if (child instanceof InclusãoBiblioteca) {
this.bibliotecas.push(child);
} else if (child instanceof DeclaraçãoCmd) {
this.declarações.push(child);
} else {
this.unexpectedChild(child);
}

this.children.push(child);
}
}
42 changes: 18 additions & 24 deletions packages/parser/src/nodes/AtribuiçãoCmd.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ParserRuleContext } from "antlr4ng";
import { ParseTree } from "antlr4ng";

import { Comando } from "./Comando.js";
import { Expressão } from "./Expressão.js";
Expand All @@ -8,34 +8,28 @@ import { ReferênciaMatrizExpr } from "./ReferênciaMatrizExpr.js";
import { ReferênciaVarExpr } from "./ReferênciaVarExpr.js";
import { invariant } from "../helpers/nodes.js";

export class AtribuiçãoCmd extends Comando {
export class AtribuiçãoCmd<T extends ParseTree = ParseTree> extends Comando<T> {
variável: ReferênciaVarExpr | ReferênciaArrayExpr | ReferênciaMatrizExpr;
expressão: Expressão;

constructor(
public ctx: ParserRuleContext,
public children: Node[],
) {
super(ctx, children);
addChild(child: Node) {
super.addChild(child);

for (const child of children) {
if (
(child instanceof ReferênciaVarExpr ||
child instanceof ReferênciaArrayExpr ||
child instanceof ReferênciaMatrizExpr) &&
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
!this.variável
) {
this.variável = child;
} else if (child instanceof Expressão) {
invariant(!this.expressão, child.ctx, "Expressão já definida");
this.expressão = child;
} else {
this.unexpectedChild(child);
}
if (
(child instanceof ReferênciaVarExpr ||
child instanceof ReferênciaArrayExpr ||
child instanceof ReferênciaMatrizExpr) &&
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
!this.variável
) {
this.variável = child;
} else if (child instanceof Expressão) {
invariant(!this.expressão, child.ctx, "Expressão já definida");
this.expressão = child;
} else {
this.unexpectedChild(child);
}

invariant(this.variável, ctx, "Variável não definida");
invariant(this.expressão, ctx, "Expressão não definida");
this.children.push(child);
}
}
10 changes: 1 addition & 9 deletions packages/parser/src/nodes/AtribuiçãoCompostaDivisãoCmd.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,5 @@
import { AtribuicaoCompostaDivisaoContext } from "@portugol-webstudio/antlr";

import { AtribuiçãoCmd } from "./AtribuiçãoCmd.js";
import { Node } from "./Node.js";

export class AtribuiçãoCompostaDivisãoCmd extends AtribuiçãoCmd {
constructor(
public ctx: AtribuicaoCompostaDivisaoContext,
public children: Node[],
) {
super(ctx, children);
}
}
export class AtribuiçãoCompostaDivisãoCmd extends AtribuiçãoCmd<AtribuicaoCompostaDivisaoContext> {}
Original file line number Diff line number Diff line change
@@ -1,13 +1,5 @@
import { AtribuicaoCompostaMultiplicacaoContext } from "@portugol-webstudio/antlr";

import { AtribuiçãoCmd } from "./AtribuiçãoCmd.js";
import { Node } from "./Node.js";

export class AtribuiçãoCompostaMultiplicaçãoCmd extends AtribuiçãoCmd {
constructor(
public ctx: AtribuicaoCompostaMultiplicacaoContext,
public children: Node[],
) {
super(ctx, children);
}
}
export class AtribuiçãoCompostaMultiplicaçãoCmd extends AtribuiçãoCmd<AtribuicaoCompostaMultiplicacaoContext> {}
10 changes: 1 addition & 9 deletions packages/parser/src/nodes/AtribuiçãoCompostaSomaCmd.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,5 @@
import { AtribuicaoCompostaSomaContext } from "@portugol-webstudio/antlr";

import { AtribuiçãoCmd } from "./AtribuiçãoCmd.js";
import { Node } from "./Node.js";

export class AtribuiçãoCompostaSomaCmd extends AtribuiçãoCmd {
constructor(
public ctx: AtribuicaoCompostaSomaContext,
public children: Node[],
) {
super(ctx, children);
}
}
export class AtribuiçãoCompostaSomaCmd extends AtribuiçãoCmd<AtribuicaoCompostaSomaContext> {}
10 changes: 1 addition & 9 deletions packages/parser/src/nodes/AtribuiçãoCompostaSubtraçãoCmd.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,5 @@
import { AtribuicaoCompostaSubtracaoContext } from "@portugol-webstudio/antlr";

import { AtribuiçãoCmd } from "./AtribuiçãoCmd.js";
import { Node } from "./Node.js";

export class AtribuiçãoCompostaSubtraçãoCmd extends AtribuiçãoCmd {
constructor(
public ctx: AtribuicaoCompostaSubtracaoContext,
public children: Node[],
) {
super(ctx, children);
}
}
export class AtribuiçãoCompostaSubtraçãoCmd extends AtribuiçãoCmd<AtribuicaoCompostaSubtracaoContext> {}
11 changes: 1 addition & 10 deletions packages/parser/src/nodes/Bypass.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,3 @@
import { ParserRuleContext } from "antlr4ng";

import { Node } from "./Node.js";

export class Bypass extends Node {
constructor(
public ctx: ParserRuleContext,
public children: Node[] = [],
) {
super();
}
}
export class Bypass extends Node {}
Loading

0 comments on commit 5c5293d

Please sign in to comment.