Для простоты я попытаюсь привести пример, используя всего несколько элементов грамматики, описываемых этими правилами:
- Операторы начинаются с начала строка, предшествующие пробелы игнорируется.
- Присвоение определяется как SingleExpression := SingleExpression, например a := 1 или a := b := 1. Пробелы не являются обязательными, а символы новой строки допускаются с обеих сторон оператора присваивания.
Код: Выделить всё
a:=
1
3. Оператор вызова функции начинается с идентификатора или выражения в скобках (или доступа к члену, выходит за рамки этой статьи), за ним следуют пробелы, а затем следует список аргументов, разделенных запятыми.
4. Любые два отдельных выражения могут быть неявно объединены в строку, по крайней мере, с одним пробелом между ними. Например, a := 1 2 объединяет цифры до 12 и присваивает их значению a. Конец строки допускается только в том случае, если конкатенация заключена в скобки или круглые скобки.
Код: Выделить всё
a := 1
hello
Код: Выделить всё
a := (1
2)
- < li>Горячая клавиша определяется идентификатором клавиши, за которым следует ::, за которым следует либо другая горячая клавиша (в отдельной строке), либо оператор. Например, a::b := 1 означает «создать горячую клавишу для клавиши a, которая затем присваивает 1 переменной b. a::MsgBox вызывает вызов функции для MsgBox.
- Переназначение — это идентификатор ключа, за которым следует ::, за которым следует другой ключ. Например, a::b создает функциональность, при которой нажатие клавиши вместо этого отправляет b. Переназначение имеет приоритет над горячей клавишей, поэтому, если второй идентификатор клавиши соответствует имени клавиши, оно считается переназначением, в противном случае горячая клавиша a::MsgBox является горячей клавишей только потому, что клавиша с именем MsgBox. не существует.
using System.Text;
using Antlr4.Runtime;
using Antlr4.Runtime.Atn;
using System.Diagnostics;
namespace AntlrCSharp
{
class Program
{
private static void Main(string[] args)
{
try
{
string input = "";
StringBuilder text = new StringBuilder();
string filePath = @"test.txt";
try
{
string fileContent = File.ReadAllText(filePath);
text.Append(fileContent);
}
catch (FileNotFoundException)
{
Console.WriteLine($"The file at {filePath} was not found.");
}
catch (Exception ex)
{
Console.WriteLine($"An error occurred: {ex.Message}");
}
StartSimpleParser(text);
}
catch (Exception ex)
{
Console.WriteLine("Error: " + ex);
}
}
public static void StartSimpleParser(StringBuilder text)
{
Console.WriteLine("Start");
AntlrInputStream inputStream = new AntlrInputStream(text.ToString());
SimpleLexer simpleLexer = new SimpleLexer(inputStream);
CommonTokenStream commonTokenStream = new CommonTokenStream(simpleLexer);
SimpleParser simpleParser = new SimpleParser(commonTokenStream);
/*
foreach (var token in SimpleLexer.GetAllTokens())
{
Console.WriteLine($"Token: {SimpleLexer.Vocabulary.GetSymbolicName(token.Type)}, Text: '{token.Text}'" + (token.Channel == MainLexer.Hidden ? " (hidden)" : ""));
}
*/
simpleParser.ErrorHandler = new BailErrorStrategy();
simpleParser.AddErrorListener(new DiagnosticErrorListener());
simpleParser.Interpreter.PredictionMode = PredictionMode.LL_EXACT_AMBIG_DETECTION;
SimpleParser.ProgramContext programContext = simpleParser.program();
Console.WriteLine("Parsed");
MainVisitor visitor = new MainVisitor();
visitor.Visit(programContext);
Console.WriteLine("End");
}
}
}
[/code]
Однако с этой грамматикой есть несколько проблем.
- Я не могу включить одновременно необязательные пробелы и конец -строки в выражениях присваивания: singleExpression s? ':=' s? SingleExpression вызывает ошибку reportAttemptingFullContext с LL_EXACT_AMBIG_DETECTION.
- Я не могу понять, как разбить синтаксис переназначения на два ключа. Текущее определение RemapKey HotkeyCharacter '::' HotkeyCharacter означает, что мне придется отдельно анализировать его позже в посетителе.
- Грамматика будет засорена EOL и WS.
Подробнее здесь: https://stackoverflow.com/questions/793 ... ohotkey-v2
Мобильная версия