From 6ce3396bec42e5c59aafd71ec06d6ba83002b0a9 Mon Sep 17 00:00:00 2001 From: Jon Crussell Date: Thu, 20 Jun 2024 06:54:31 -0700 Subject: [PATCH] add support for rust with the go runtime Tested on rust/examples/*.rs and works for all the examples except `intellijrust_test_allinone.rs` which takes forever to analyze. --- rust/Go/rust_lexer_base.go | 81 +++++++++++++++++++++++++++++++++++++ rust/Go/rust_parser_base.go | 14 +++++++ rust/Go/transformGrammar.py | 56 +++++++++++++++++++++++++ 3 files changed, 151 insertions(+) create mode 100644 rust/Go/rust_lexer_base.go create mode 100644 rust/Go/rust_parser_base.go create mode 100644 rust/Go/transformGrammar.py diff --git a/rust/Go/rust_lexer_base.go b/rust/Go/rust_lexer_base.go new file mode 100644 index 0000000000..72f924a44f --- /dev/null +++ b/rust/Go/rust_lexer_base.go @@ -0,0 +1,81 @@ +package parser + +import ( + "github.com/antlr4-go/antlr/v4" +) + +type RustLexerBase struct { + *antlr.BaseLexer + + lastToken antlr.Token + lastToken2 antlr.Token +} + +func (l *RustLexerBase) NextToken() antlr.Token { + next := l.BaseLexer.NextToken() + + if next.GetChannel() == antlr.LexerDefaultTokenChannel { + // keep track of the last token on the default channel + l.lastToken2 = l.lastToken + l.lastToken = next + } + + return next +} + +func (l *RustLexerBase) SOF() bool { + return l.GetInputStream().LA(-1) <= 0 +} + +func (l *RustLexerBase) floatDotPossible() bool { + next := rune(l.GetInputStream().LA(1)) + if next == '.' || next == '_' { + return false + } + if next == 'f' { + // 1.f32 + if rune(l.GetInputStream().LA(2)) == '3' && rune(l.GetInputStream().LA(3)) == '2' { + return true + } + //1.f64 + if rune(l.GetInputStream().LA(2)) == '6' && rune(l.GetInputStream().LA(3)) == '4' { + return true + } + return false + } + if next >= 'a' && next <= 'z' { + return false + } + if next >= 'A' && next <= 'Z' { + return false + } + + return false +} + +func (l *RustLexerBase) floatLiteralPossible() bool { + if l.lastToken == nil || l.lastToken2 == nil { + return true + } + if l.lastToken.GetTokenType() != RustLexerDOT { + return true + } + + switch l.lastToken2.GetTokenType() { + case RustLexerCHAR_LITERAL, RustLexerSTRING_LITERAL, + RustLexerRAW_STRING_LITERAL, RustLexerBYTE_LITERAL, + RustLexerBYTE_STRING_LITERAL, RustLexerRAW_BYTE_STRING_LITERAL, + RustLexerINTEGER_LITERAL, RustLexerDEC_LITERAL, RustLexerHEX_LITERAL, + RustLexerOCT_LITERAL, RustLexerBIN_LITERAL, RustLexerKW_SUPER, + RustLexerKW_SELFVALUE, RustLexerKW_SELFTYPE, RustLexerKW_CRATE, + RustLexerKW_DOLLARCRATE, RustLexerGT, RustLexerRCURLYBRACE, + RustLexerRSQUAREBRACKET, RustLexerRPAREN, RustLexerKW_AWAIT, + RustLexerNON_KEYWORD_IDENTIFIER, RustLexerRAW_IDENTIFIER, + RustLexerKW_MACRORULES: + return false + default: + return true + } + + return false +} diff --git a/rust/Go/rust_parser_base.go b/rust/Go/rust_parser_base.go new file mode 100644 index 0000000000..899bde4511 --- /dev/null +++ b/rust/Go/rust_parser_base.go @@ -0,0 +1,14 @@ +package parser + +import ( + "github.com/antlr4-go/antlr/v4" +) + +// RustParserBase implementation. +type RustParserBase struct { + *antlr.BaseParser +} + +func (p *RustParserBase) next(expect int) bool { + return p.GetInputStream().LA(1) == expect +} diff --git a/rust/Go/transformGrammar.py b/rust/Go/transformGrammar.py new file mode 100644 index 0000000000..56a0ccb026 --- /dev/null +++ b/rust/Go/transformGrammar.py @@ -0,0 +1,56 @@ +import sys, os, re, shutil +from glob import glob +from pathlib import Path + +def main(argv): + for file in glob("./*Lexer.g4"): + fix_lexer(file) + for file in glob("./*Parser.g4"): + fix_parser(file) + +def fix_lexer(file_path): + print("Altering " + file_path) + if not os.path.exists(file_path): + print(f"Could not find file: {file_path}") + sys.exit(1) + parts = os.path.split(file_path) + file_name = parts[-1] + + shutil.move(file_path, file_path + ".bak") + input_file = open(file_path + ".bak",'r') + output_file = open(file_path, 'w') + for x in input_file: + if 'this.' in x and '}?' in x: + x = x.replace('this.', 'p.') + elif 'this.' in x: + x = x.replace('this.', 'l.') + output_file.write(x) + output_file.flush() + + print("Writing ...") + input_file.close() + output_file.close() + +def fix_parser(file_path): + print("Altering " + file_path) + if not os.path.exists(file_path): + print(f"Could not find file: {file_path}") + sys.exit(1) + parts = os.path.split(file_path) + file_name = parts[-1] + + shutil.move(file_path, file_path + ".bak") + input_file = open(file_path + ".bak",'r') + output_file = open(file_path, 'w') + for x in input_file: + if 'this.' in x: + x = x.replace('this.', 'p.') + output_file.write(x) + output_file.flush() + + print("Writing ...") + input_file.close() + output_file.close() + +if __name__ == '__main__': + main(sys.argv)