Skip to content

Commit

Permalink
A large part of code generation works now
Browse files Browse the repository at this point in the history
  • Loading branch information
mike-lischke committed Nov 15, 2024
1 parent bae1768 commit b3d8cc6
Show file tree
Hide file tree
Showing 24 changed files with 274 additions and 244 deletions.
7 changes: 5 additions & 2 deletions src/analysis/AnalysisPipeline.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,14 @@ export class AnalysisPipeline {
}

/** Return whether lookahead sets are disjoint; no lookahead ⇒ not disjoint */
public static disjoint(altLook: IntervalSet[]): boolean {
public static disjoint(altLook: Array<IntervalSet | undefined>): boolean {
let collision = false;
const combined = new IntervalSet();
for (const look of altLook) {
// lookahead must've computation failed
if (look === undefined) {
return false; // lookahead must've computation failed
}

if (look.and(combined).length >= 0) {
collision = true;
break;
Expand Down
2 changes: 1 addition & 1 deletion src/analysis/LeftRecursiveRuleAnalyzer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -359,7 +359,7 @@ export class LeftRecursiveRuleAnalyzer extends LeftRecursiveRuleWalker {
(tok.type === ANTLRv4Parser.TOKEN_REF ||
tok.type === ANTLRv4Parser.STRING_LITERAL ||
tok.type === ANTLRv4Parser.RULE_REF)) {
// TODO elementOptions += "tokenIndex=" + tok.tokenIndex; unsupported 4 syntax
elementOptions += "tokenIndex=" + tok.tokenIndex;
}

if (node instanceof GrammarASTWithOptions) {
Expand Down
2 changes: 1 addition & 1 deletion src/antlr3/tree/TreeParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ export class TreeParser extends BaseRecognizer {

context = context.replaceAll("\\.\\.\\.", " ... "); // ensure spaces around ...
context = context.trim();
const nodes = context.split("\\s+");
const nodes = context.split(/\s+/);
let ni = nodes.length - 1;
t = adaptor.getParent(t);
while (ni >= 0 && t !== null) {
Expand Down
6 changes: 3 additions & 3 deletions src/automata/ParserATNFactory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -363,15 +363,15 @@ export class ParserATNFactory implements IParserATNFactory, IATNFactory {
}

switch (ebnfRoot.getType()) {
case ANTLRv4Parser.QUESTION: {
case ANTLRv4Parser.OPTIONAL: {
const start = this.newStateOfType(BasicBlockStartState, blkAST);
this.atn.defineDecisionState(start);
const h = this.makeBlock(start, blkAST, alts);

return this.optional(ebnfRoot, h);
}

case ANTLRv4Parser.STAR: {
case ANTLRv4Parser.CLOSURE: {
const star = this.newStateOfType(StarBlockStartState, ebnfRoot);
if (alts.length > 1) {
this.atn.defineDecisionState(star);
Expand All @@ -382,7 +382,7 @@ export class ParserATNFactory implements IParserATNFactory, IATNFactory {
return this.star(ebnfRoot, h);
}

case ANTLRv4Parser.PLUS: {
case ANTLRv4Parser.POSITIVE_CLOSURE: {
const plus = this.newStateOfType(PlusBlockStartState, ebnfRoot);
if (alts.length > 1) {
this.atn.defineDecisionState(plus);
Expand Down
4 changes: 2 additions & 2 deletions src/codegen/BlankOutputModelFactory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,11 +85,11 @@ export abstract class BlankOutputModelFactory implements OutputModelFactory {
return null;
}

public tokenRef(id: GrammarAST, label: GrammarAST, args: GrammarAST | null): SrcOp[] | null {
public tokenRef(id: GrammarAST, label: GrammarAST | null, args: GrammarAST | null): SrcOp[] | null {
return null;
}

public stringRef(id: GrammarAST, label: GrammarAST): SrcOp[] | null {
public stringRef(id: GrammarAST, label: GrammarAST | null): SrcOp[] | null {
return this.tokenRef(id, label, null);
}

Expand Down
24 changes: 6 additions & 18 deletions src/codegen/CodeGenerator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,9 +100,7 @@ export class CodeGenerator {
}

public generateParser(header?: boolean): IST {
if (!header) {
return this.generateParser(false);
}
header ??= false;

return this.walk(this.createController().buildParserOutputModel(header), header);
}
Expand Down Expand Up @@ -189,41 +187,31 @@ export class CodeGenerator {
}

public getRecognizerFileName(header?: boolean): string {
if (!header) {
return this.getRecognizerFileName(false);
}
header ??= false;

return this.target.getRecognizerFileName(header);
}

public getListenerFileName(header?: boolean): string {
if (!header) {
return this.getListenerFileName(false);
}
header ??= false;

return this.target.getListenerFileName(header);
}

public getVisitorFileName(header?: boolean): string {
if (!header) {
return this.getVisitorFileName(false);
}
header ??= false;

return this.target.getVisitorFileName(header);
}

public getBaseListenerFileName(header?: boolean): string {
if (!header) {
return this.getBaseListenerFileName(false);
}
header ??= false;

return this.target.getBaseListenerFileName(header);
}

public getBaseVisitorFileName(header?: boolean): string {
if (!header) {
return this.getBaseVisitorFileName(false);
}
header ??= false;

return this.target.getBaseVisitorFileName(header);
}
Expand Down
6 changes: 3 additions & 3 deletions src/codegen/OutputModelController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,11 @@ export class OutputModelController {
public treeLevel = -1;
public root: OutputModelObject; // normally ParserFile, LexerFile, ...
public currentRule = new Array<RuleFunction>();
public currentOuterMostAlt: Alternative;
public currentBlock: CodeBlock;
public currentOuterMostAlternativeBlock: CodeBlockForOuterMostAlt;

private currentOuterMostAlt: Alternative;

public constructor(factory: OutputModelFactory) {
this.delegate = factory;
}
Expand Down Expand Up @@ -298,8 +299,7 @@ export class OutputModelController {
// TRIGGER factory functions for rule alts, elements
const adaptor = new GrammarASTAdaptor(r.ast.token?.inputStream ?? undefined);

// XXX: Originally used BLOCK.
const blk = r.ast.getFirstChildWithType(ANTLRv4Parser.LPAREN) as GrammarAST;
const blk = r.ast.getFirstChildWithType(ANTLRv4Parser.BLOCK) as GrammarAST;
const nodes = new CommonTreeNodeStream(adaptor, blk);
this.walker = new SourceGenTriggers(nodes, this);

Expand Down
141 changes: 61 additions & 80 deletions src/codegen/OutputModelWalker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,7 @@ export class OutputModelWalker {
protected tool: Tool;
protected templates: STGroup;

public constructor(tool: Tool,
templates: STGroup) {
public constructor(tool: Tool, templates: STGroup) {
this.tool = tool;
this.templates = templates;
}
Expand All @@ -53,90 +52,72 @@ export class OutputModelWalker {
return new ST("[" + templateName + " invalid]");
}

/*
if (!st.impl?.formalArguments) {
ErrorManager.get().toolError(ErrorType.CODE_TEMPLATE_ARG_ISSUE, templateName, "<none>");
return st;
}
let formalArgs = st.impl.formalArguments;
// PASS IN OUTPUT MODEL OBJECT TO TEMPLATE AS FIRST ARG
let [modelArgName] = [...formalArgs.keys()];
st.add(modelArgName, omo);
// COMPUTE STs FOR EACH NESTED MODEL OBJECT MARKED WITH AND MAKE ST ATTRIBUTE
let usedFieldNames = new Set<string>();
let fields = Object.getOwnPropertyNames(omo.constructor.prototype);
for (let fi of fields) {
let annotation = fi.getAnnotation(ModelElement.class);
if (annotation === null) {
continue;
}
let fieldName = fi.getName();
if (!usedFieldNames.add(fieldName)) {
ErrorManager.get().toolError(ErrorType.INTERNAL_ERROR, "Model object " + omo.getClass()
.getSimpleName() + " has multiple fields named '" + fieldName + "'");
continue;
}
if (!st.impl?.formalArguments) {
ErrorManager.get().toolError(ErrorType.CODE_TEMPLATE_ARG_ISSUE, templateName, "<none>");

// Just don't set fields w/o formal arg in target ST
if (formalArgs.get(fieldName) === null) {
continue;
}
try {
let o = fi.get(omo);
if (o instanceof OutputModelObject) { // SINGLE MODEL OBJECT?
let nestedOmo = o as OutputModelObject;
let nestedST = this.walk(nestedOmo, header);
st.add(fieldName, nestedST);
}
else {
if (o instanceof Collection || o instanceof OutputModelObject[]) {
// LIST OF MODEL OBJECTS?
if (o instanceof OutputModelObject[]) {
o = Arrays.asList(o as OutputModelObject[]);
}
let nestedOmos = o as Array<unknown>;
for (let nestedOmo of nestedOmos) {
if (nestedOmo === null) {
continue;
}
let nestedST = this.walk(nestedOmo as OutputModelObject, header);
st.add(fieldName, nestedST);
}
}
else {
if (o instanceof Map) {
let nestedOmoMap = o as Map<unknown, unknown>;
let m = new LinkedHashMap<Object, ST>();
for (let entry of nestedOmoMap.entrySet()) {
let nestedST = this.walk(entry.getValue() as OutputModelObject, header);
m.put(entry.getKey(), nestedST);
}
st.add(fieldName, m);
}
else {
if (o !== null) {
}
}
}
return st;
}

const formalArgs = st.impl.formalArguments;

// PASS IN OUTPUT MODEL OBJECT TO TEMPLATE AS FIRST ARG
const [modelArgName] = [...formalArgs.keys()];
st.add(modelArgName, omo);

// COMPUTE STs FOR EACH NESTED MODEL OBJECT MARKED WITH @ModelElement AND MAKE ST ATTRIBUTE
const usedFieldNames = new Set<string>();
const fields = Object.keys(omo);
for (const fieldName of fields) {
/* let annotation = fi.getAnnotation(ModelElement.class);
if (annotation === null) {
continue;
}*/

if (usedFieldNames.has(fieldName)) {
ErrorManager.get().toolError(ErrorType.INTERNAL_ERROR, "Model object " + omo.constructor.name +
" has multiple fields named '" + fieldName + "'");
continue;
}
usedFieldNames.add(fieldName);

// Just don't set fields w/o formal arg in target ST
if (!formalArgs.get(fieldName)) {
continue;
}

//const o = fi.get(omo);
const o = omo[fieldName];
if (o instanceof OutputModelObject) { // SINGLE MODEL OBJECT?
const nestedOmo = o;
const nestedST = this.walk(nestedOmo, header);
st.add(fieldName, nestedST);
} else {
if (Array.isArray(o)) {
const nestedOmos = o as unknown[];
for (const nestedOmo of nestedOmos) {
if (nestedOmo === null) {
continue;
}

} catch (iae) {
if (iae instanceof IllegalAccessException) {
ErrorManager.get().toolError(ErrorType.CODE_TEMPLATE_ARG_ISSUE, templateName, fieldName);
} else {
throw iae;
const nestedST = this.walk(nestedOmo as OutputModelObject, header);
st.add(fieldName, nestedST);
}
} else {
if (o instanceof Map) {
const nestedOmoMap = o as Map<string, OutputModelObject>;
const m = new Map<string, IST>();
for (const [key, value] of nestedOmoMap) {
const nestedST = this.walk(value, header);
m.set(key, nestedST);
}
st.add(fieldName, m);
} else if (o !== undefined) {
ErrorManager.get().toolError(ErrorType.INTERNAL_ERROR,
"not recognized nested model element: " + fieldName);
}
}*/
}
}
}

return st;
}
Expand Down
Loading

0 comments on commit b3d8cc6

Please sign in to comment.