Skip to content

[golang] Fixes for #4460 and #4462 (ambiguities) #4461

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 13 commits into from
Apr 9, 2025
4 changes: 2 additions & 2 deletions _scripts/templates/Cpp/cmake/st.ExternalAntlr4Cpp.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ include(ExternalProject)
#set(ANTLR4_ROOT ${CMAKE_CURRENT_BINARY_DIR}/antlr4_runtime/src/antlr4_runtime)
set(ANTLR4_ROOT <temp_dir>/antlr4_runtime/src/antlr4_runtime)
set(ANTLR4_INCLUDE_DIRS ${ANTLR4_ROOT}/runtime/Cpp/runtime/src)
set(ANTLR4_GIT_REPOSITORY https://github.com/antlr/antlr4.git)
set(ANTLR4_GIT_REPOSITORY https://github.com/kaby76/antlr4.git)
if(NOT DEFINED ANTLR4_TAG)
# Set to branch name to keep library updated at the cost of needing to rebuild after 'clean'
# Set to commit hash to keep the build stable and does not need to rebuild after 'clean'
Expand Down Expand Up @@ -96,7 +96,7 @@ else()
antlr4_runtime
PREFIX <temp_dir>/antlr4_runtime
GIT_REPOSITORY ${ANTLR4_GIT_REPOSITORY}
GIT_TAG df4d68c09cdef73e023b8838a8bc7ca4dff1d1de # ${ANTLR4_TAG}
GIT_TAG f5bd4bec221ca5d916839eca52759720fa28d24c # df4d68c09cdef73e023b8838a8bc7ca4dff1d1de # ${ANTLR4_TAG}
DOWNLOAD_DIR ${CMAKE_CURRENT_BINARY_DIR}
BUILD_COMMAND ""
BUILD_IN_SOURCE 1
Expand Down
114 changes: 107 additions & 7 deletions golang/Antlr4ng/GoParserBase.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,126 @@
import { Parser, TokenStream, BufferedTokenStream, Token } from 'antlr4ng';
import { GoLexer } from './GoLexer.js';
import { GoParser, ImportSpecContext } from './GoParser.js';

export default abstract class GoParserBase extends Parser {

debug: boolean;
table: Set<string>;

constructor(input: TokenStream) {
super(input);
}

protected myreset(): void {
this.debug = false;
this.table = new Set<string>();
}

protected closingBracket(): boolean {
const stream = this.inputStream as BufferedTokenStream;
const la = stream.LA(1);
return la === GoLexer.R_CURLY || la === GoLexer.R_PAREN || la === Token.EOF;
const la = stream.LT(1);
return la.type === GoParser.R_CURLY || la.type === GoParser.R_PAREN || la.type === Token.EOF;
}

public isNotReceive(): boolean
{
const stream = this.inputStream as BufferedTokenStream;
const la = stream.LT(2);
return la.type !== GoParser.RECEIVE;
}

public addImportSpec(): void
{
const ctx = this.context;
const count = ctx.getChildCount();
if (!(ctx instanceof ImportSpecContext)) {
return;
}
const importSpec = ctx;
var packageName = importSpec.packageName();
if (packageName != null)
{
var name = packageName.getText();
if (this.debug) console.log("Entering " + name);
this.table.add(name);
}
else
{
var name = importSpec.importPath().getText();
name = name.replaceAll("\"", "");
name = name.replaceAll("\\", "/");
const pathArr = name.split('/');
const fileArr = pathArr.at(-1).split('.');
const fileName = fileArr.at(-1).toString();
if (this.debug) console.log("Entering " + fileName);
this.table.add(fileName);
}
}

protected isType(): boolean {
const stream = this.inputStream as BufferedTokenStream;
const la = stream.LA(1);
return la !== GoLexer.IDENTIFIER;
return la !== GoParser.IDENTIFIER;
}

public isOperand(): boolean
{
const stream = this.inputStream as BufferedTokenStream;
const la = stream.LT(1);
if (la.text === "err") return true;
var result = true;
if (la.type !== GoParser.IDENTIFIER) {
if (this.debug) console.log("isOperand Returning " + result + " for " + la);
return result;
}
result = this.table.has(la.text);
var la2 = stream.LT(2);
// If it's not followed by a '.', then it really should be
// considered as operand.
if (la2.type !== GoParser.DOT) {
result = true;
if (this.debug) console.log("isOperand Returning " + result + " for " + la);
return result;
}
// If it's followed by '.', and then followed by '(', then
// it is a typeAssertion, and so la must be an operand.
var la3 = stream.LT(3);
if (la3.type === GoParser.L_PAREN)
{
result = true;
if (this.debug) console.log("isOperand Returning " + result + " for " + la);
return result;
}
if (this.debug) console.log("isOperand Returning " + result + " for " + la);
return result;
}

protected isNotReceive(): boolean {
public isConversion(): boolean
{
const stream = this.inputStream as BufferedTokenStream;
const la = stream.LA(2);
return la !== GoLexer.RECEIVE;
}
const la = stream.LT(1);
var result = la.type !== GoParser.IDENTIFIER;
if (this.debug) console.log("isConversion Returning " + result + " for " + la);
return result;
}

public isMethodExpr(): boolean
{
const stream = this.inputStream as BufferedTokenStream;
const la = stream.LT(1);
var result = true;
// See if it looks like a method expr.
if (la.type === GoParser.STAR) {
if (this.debug) console.log("isMethodExpr Returning " + result + " for " + la);
return result;
}
if (la.type !== GoParser.IDENTIFIER) {
result = false;
if (this.debug) console.log("isMethodExpr Returning " + result + " for " + la);
return result;
}
result = ! this.table.has(la.text);
if (this.debug) console.log("isMethodExpr Returning " + result + " for " + la);
return result;
}
}
108 changes: 97 additions & 11 deletions golang/CSharp/GoParserBase.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Antlr4.Runtime;

public abstract class GoParserBase : Parser
{
const bool debug = false;
HashSet<string> table = new HashSet<string>();

protected GoParserBase(ITokenStream input)
: base(input)
{
Expand All @@ -15,30 +19,112 @@ protected GoParserBase(ITokenStream input, TextWriter output, TextWriter errorOu
{
}

private ITokenStream tokenStream
{
get
{
return TokenStream;
}
}

protected void myreset()
{
table = new HashSet<string>();
}

protected bool closingBracket()
{
int la = tokenStream.LA(1);
return la == GoLexer.R_PAREN || la == GoLexer.R_CURLY || la == Eof;
var la = tokenStream.LT(1);
return la.Type == GoParser.R_PAREN || la.Type == GoParser.R_CURLY || la.Type == Eof;
}

private ITokenStream tokenStream
public bool isNotReceive()
{
get
var la = tokenStream.LT(2);
return la.Type != GoParser.RECEIVE;
}

public void addImportSpec()
{
var ctx = this.Context;
var count = ctx.ChildCount;
var importSpec = ctx as GoParser.ImportSpecContext;
if (importSpec == null) return;
var packageName = importSpec.packageName();
if (packageName != null)
{
return TokenStream;
var name = packageName.GetText();
if (debug) System.Console.WriteLine("Entering " + name);
table.Add(name);
}
else
{
var name = importSpec.importPath().GetText();
name = name.Replace("\"", "");
name = name.Replace("\\", "/");
string[] pathArr = name.Split('/');
string[] fileArr = pathArr.Last().Split('.');
string fileName = fileArr.Last().ToString();
if (debug) System.Console.WriteLine("Entering " + fileName);
table.Add(fileName);
}
}

public bool isType()
public bool isOperand()
{
int la = tokenStream.LA(1);
return la != GoLexer.IDENTIFIER;
var la = tokenStream.LT(1);
if (la.Text == "err") return true;
bool result = true;
if (la.Type != GoParser.IDENTIFIER) {
if (debug) System.Console.WriteLine("isOperand Returning " + result + " for " + la);
return result;
}
result = table.Contains(la.Text);
var la2 = tokenStream.LT(2);
// If it's not followed by a '.', then it really should be
// considered as operand.
if (la2.Type != GoParser.DOT) {
result = true;
if (debug) System.Console.WriteLine("isOperand Returning " + result + " for " + la);
return result;
}
// If it's followed by '.', and then followed by '(', then
// it is a typeAssertion, and so la must be an operand.
var la3 = tokenStream.LT(3);
if (la3.Type == GoParser.L_PAREN)
{
result = true;
if (debug) System.Console.WriteLine("isOperand Returning " + result + " for " + la);
return result;
}
if (debug) System.Console.WriteLine("isOperand Returning " + result + " for " + la);
return result;
}

public bool isNotReceive()
public bool isConversion()
{
int la = tokenStream.LA(2);
return la != GoLexer.RECEIVE;
var la = tokenStream.LT(1);
var result = la.Type != GoParser.IDENTIFIER;
if (debug) System.Console.WriteLine("isConversion Returning " + result + " for " + la);
return result;
}

public bool isMethodExpr()
{
var la = tokenStream.LT(1);
bool result = true;
// See if it looks like a method expr.
if (la.Type == GoParser.STAR) {
if (debug) System.Console.WriteLine("isMethodExpr Returning " + result + " for " + la);
return result;
}
if (la.Type != GoParser.IDENTIFIER) {
result = false;
if (debug) System.Console.WriteLine("isMethodExpr Returning " + result + " for " + la);
return result;
}
result = ! table.Contains(la.Text);
if (debug) System.Console.WriteLine("isMethodExpr Returning " + result + " for " + la);
return result;
}
}
Loading
Loading