Skip to content

Commit

Permalink
Add token alias support
Browse files Browse the repository at this point in the history
  • Loading branch information
babyraging committed Jun 1, 2020
1 parent 7b5d702 commit bb66b54
Show file tree
Hide file tree
Showing 6 changed files with 64 additions and 8 deletions.
53 changes: 49 additions & 4 deletions src/languages/parser/yaccParser.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { binarySearch } from './utils';
import { binarySearch, _SQO } from './utils';
import { createScanner } from './yaccScanner';
import { parse as parseUnion, YYType } from './unionParser';
import { TokenType } from '../yaccLanguageTypes';
Expand Down Expand Up @@ -28,13 +28,16 @@ export interface ISymbol {
used: boolean;
definition: [number, number];
references: [number, number][];

alias?: ISymbol
};

export interface YACCDocument {
readonly embedded: Node[];
readonly nodes: Node[];
readonly types: { [name: string]: ISymbol };
readonly tokens: { [name: string]: ISymbol };
readonly aliases: { [name: string]: ISymbol };
readonly symbols: { [name: string]: ISymbol };
readonly components: ISymbol[];
readonly rulesRange: [number, number];
Expand Down Expand Up @@ -73,6 +76,7 @@ export function parse(text: string): YACCDocument {
const nodes: Node[] = [];
const types: { [name: string]: ISymbol } = {};
const tokens: { [name: string]: ISymbol } = {};
const aliases: { [name: string]: ISymbol } = {};
const symbols: { [name: string]: ISymbol } = {};
const components: ISymbol[] = [];
const rulesRange: [number, number] = [0, text.length];
Expand All @@ -82,6 +86,7 @@ export function parse(text: string): YACCDocument {
nodes,
types,
tokens,
aliases,
symbols,
components,
rulesRange,
Expand Down Expand Up @@ -124,14 +129,15 @@ export function parse(text: string): YACCDocument {
});
}

function addSymbolToMap(symbols: { [name: string]: ISymbol }, terminal: boolean, offset: number, end: number, name: string, type: string) {
function addSymbolToMap(symbols: { [name: string]: ISymbol }, terminal: boolean, offset: number, end: number, name: string, type: string): ISymbol | undefined {
const old = symbols[name];
if (old) {
addProblem(`Symbol was already declared/defined.`, offset, end, ProblemType.Error, {
offset: old.offset,
end: old.end,
message: "Was declared/defined here."
});
return undefined;
} else {
symbols[name] = {
terminal: terminal,
Expand All @@ -144,6 +150,7 @@ export function parse(text: string): YACCDocument {
definition: [offset, end],
references: [[offset, end]]
};
return symbols[name];
}
}
let end = -2;
Expand All @@ -155,6 +162,7 @@ export function parse(text: string): YACCDocument {
let tokenText = '';
let lastNode: Node | undefined;
let lastToken = token;
let lastTokenSymbol = undefined;
while (end < 0 && token !== TokenType.EOS) {
offset = scanner.getTokenOffset();
switch (token) {
Expand Down Expand Up @@ -260,7 +268,7 @@ export function parse(text: string): YACCDocument {
offset, scanner.getTokenEnd(), ProblemType.Error);
break;
}
addSymbolToMap(document.tokens, true, offset, scanner.getTokenEnd(), word, type);
lastTokenSymbol = addSymbolToMap(document.tokens, true, offset, scanner.getTokenEnd(), word, type);
break;
case ParserState.WaitingSymbol:
addSymbolToMap(document.symbols, true, offset, scanner.getTokenEnd(), word, type);
Expand Down Expand Up @@ -344,8 +352,37 @@ export function parse(text: string): YACCDocument {
case TokenType.EndComment:
case TokenType.Comment:
case TokenType.Param:
case TokenType.Literal:
break;
case TokenType.Literal: {
const word = scanner.getTokenText();
const code = word.charCodeAt(0)
if (code == _SQO) break;
switch (state) {
case ParserState.WaitingToken:
if (lastTokenSymbol && lastTokenSymbol.alias == undefined) {
lastTokenSymbol.alias = addSymbolToMap(document.aliases, true, offset, scanner.getTokenEnd(), word, lastTokenSymbol.type)
if (lastTokenSymbol.alias)
lastTokenSymbol.alias.alias = lastTokenSymbol
} else {
addProblem(`Alias not associated with an token.`, scanner.getTokenOffset(), scanner.getTokenEnd(), ProblemType.Error);
}
break;
case ParserState.WaitingRule:
document.components.push({
terminal: true,
offset: offset,
length: scanner.getTokenLength(),
end: scanner.getTokenEnd(),
name: scanner.getTokenText(),
type: '',
used: true,
definition: [-1, -1],
references: [[offset, scanner.getTokenEnd()]]
});
break;
}
break;
}
case TokenType.Bar:
if (state !== ParserState.WaitingRule) {
addProblem(`Unexpected | symbol.`, scanner.getTokenOffset(), scanner.getTokenEnd(), ProblemType.Error);
Expand Down Expand Up @@ -376,6 +413,14 @@ export function parse(text: string): YACCDocument {
component.references = symbol.references;
symbol.references.push([component.offset, component.end]);
symbol.used = true;
} else if ((symbol = document.aliases[component.name])) {
component.definition = symbol.definition;
component.type = symbol.type;
component.references = symbol.references;
symbol.references.push([component.offset, component.end]);
symbol.used = true;
if (symbol.alias)
symbol.alias.used = true;
} else if (!predefined[component.name]) {
document.problems.push({
offset: component.offset,
Expand Down
2 changes: 1 addition & 1 deletion src/languages/services/yaccDefinitions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export function doYACCFindDefinition(document: TextDocument, position: Position,
}

const word = document.getText(document.getWordRangeAtPosition(position));
var symbol: ISymbol | undefined = yaccDocument.types[word] || yaccDocument.symbols[word] || yaccDocument.tokens[word];
var symbol: ISymbol | undefined = yaccDocument.types[word] || yaccDocument.symbols[word] || yaccDocument.tokens[word] || yaccDocument.aliases[`"${word}"`];
let location: Location | null = null;
if (symbol) {
location = new Location(document.uri, new Range(document.positionAt(symbol.definition[0]), document.positionAt(symbol.definition[1])));
Expand Down
7 changes: 7 additions & 0 deletions src/languages/services/yaccHover.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,13 @@ export function doYACCHover(document: TextDocument, position: Position, yaccDocu
const node = yaccDocument.getNodeByOffset(symbol.offset)!;
const head = document.getText(document.getWordRangeAtPosition(document.positionAt(node!.offset + 1)));
message = createMarkedCodeString(`%${head} <${symbol.type ? symbol.type : '?'}> ${symbol.name}`, 'yacc');
} else if ((symbol = yaccDocument.aliases[`"${word}"`])) {
if (symbol.alias) {
symbol = symbol.alias;
const node = yaccDocument.getNodeByOffset(symbol.offset)!;
const head = document.getText(document.getWordRangeAtPosition(document.positionAt(node!.offset + 1)));
message = createMarkedCodeString(`%${head} <${symbol.type ? symbol.type : '?'}> ${symbol.name}`, 'yacc');
}
} else if (predefined[word]) {
message = createMarkedCodeString(predefined[word], 'yacc');
}
Expand Down
5 changes: 4 additions & 1 deletion src/languages/services/yaccReferences.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,13 @@ export function doYACCFindReferences(document: TextDocument, position: Position,
}

const word = document.getText(document.getWordRangeAtPosition(position));
var symbol: ISymbol | undefined = yaccDocument.types[word] || yaccDocument.symbols[word] || yaccDocument.tokens[word];
var symbol: ISymbol | undefined = yaccDocument.types[word] || yaccDocument.symbols[word] || yaccDocument.tokens[word] || yaccDocument.aliases[`"${word}"`];
let location: Location[] = [];
symbol?.references.forEach(reference => {
location.push(new Location(document.uri, new Range(document.positionAt(reference[0]), document.positionAt(reference[1]))));
})
symbol?.alias?.references.forEach(reference => {
location.push(new Location(document.uri, new Range(document.positionAt(reference[0]), document.positionAt(reference[1]))));
})
return location;
}
3 changes: 2 additions & 1 deletion src/languages/services/yaccRename.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@ export function doYACCRename(document: TextDocument, position: Position, newName
}

const word = document.getText(document.getWordRangeAtPosition(position));
var symbol: ISymbol | undefined = yaccDocument.types[word] || yaccDocument.symbols[word] || yaccDocument.tokens[word];
var symbol: ISymbol | undefined = yaccDocument.types[word] || yaccDocument.symbols[word] || yaccDocument.tokens[word] || yaccDocument.aliases[`"${word}"`];
const edits = new WorkspaceEdit();
if (symbol && symbol.name.startsWith('"')) newName = `"${newName}"`
symbol?.references.forEach(reference => {
edits.replace(document.uri, new Range(document.positionAt(reference[0]), document.positionAt(reference[1])), newName);
})
Expand Down
2 changes: 1 addition & 1 deletion src/languages/services/yaccTypeDefinition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export function doYACCFindTypeDefinition(document: TextDocument, position: Posit
}

const word = document.getText(document.getWordRangeAtPosition(position));
var symbol: ISymbol | undefined = yaccDocument.symbols[word] || yaccDocument.tokens[word];
var symbol: ISymbol | undefined = yaccDocument.symbols[word] || yaccDocument.tokens[word] || yaccDocument.aliases[`"${word}"`];
let location: Location | null = null;
if (symbol && symbol.type) {
const type = yaccDocument.types[symbol.type];
Expand Down

0 comments on commit bb66b54

Please sign in to comment.