Основной частью этого примера программы является использование собственного редактора ячеек EpisodeEditor
. Он динамически определяет «эпизоды» на основе «серий», выбранных в первом столбце.
(Я использовал фиктивный источник данных для этой демонстрации.)
import javax.swing.*;
import javax.swing.table.TableCellEditor;
import java.util.*;
public class ComboBoxTable
{
public static void main(String[] args)
{
// Mock data source
DataSource dataSource = new DataSource();
JComboBox<String> seriesComboBox = new JComboBox<>();
for (String s : dataSource.getSeries())
{
seriesComboBox.addItem(s);
}
JTable table = new JTable(
new String[][] {{"", ""}, {"", ""}, {"", ""}},
new String[] {"Series", "Episode"});
table.getColumn("Series").setCellEditor(new DefaultCellEditor(seriesComboBox));
table.getColumn("Episode").setCellEditor(new EpisodeEditor(dataSource));
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.getContentPane().add(new JScrollPane(table));
f.setBounds(300, 200, 400, 300);
f.setVisible(true);
}
}
class EpisodeEditor extends AbstractCellEditor implements TableCellEditor
{
private DataSource dataSource;
private JComboBox<String> episodesComboBox = new JComboBox<>();
EpisodeEditor(DataSource dataSource)
{
this.dataSource = dataSource;
}
@Override
public java.awt.Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected,
int row, int column)
{
String series = (String) table.getModel().getValueAt(row, 0);
List<String> episodes = dataSource.getEpisodes(series);
episodesComboBox.removeAllItems();
for (String ep : episodes)
{
episodesComboBox.addItem(ep);
}
episodesComboBox.setSelectedItem(value);
return episodesComboBox;
}
@Override
public Object getCellEditorValue()
{
return episodesComboBox.getSelectedItem();
}
}
class DataSource
{
List<String> getSeries()
{
return Arrays.asList("Prison Break", "Breaking Bad", "Pokemon");
}
List<String> getEpisodes(String series)
{
switch (series)
{
case "Prison Break":
return Arrays.asList("Break 1", "Break 2", "Break 3");
case "Breaking Bad":
return Arrays.asList("Bad 1", "Bad 2", "Bad 3");
case "Pokemon":
return Arrays.asList("P1", "P2", "P3");
default:
throw new IllegalArgumentException("Invalid series: " + series);
}
}
}
Вы могли записать немного, очень простая стандартная программа, которая делает это, не используя регулярное выражение:
pos
так, чтобы были точки к незадолго до открывающей скобки после Вашего for
или while
. openBr
к 0
. pos
, читая символы в соответствующих положениях, и увеличивают openBr
, когда Вы видите открывающую скобку и постепенно уменьшаете ее, когда Вы видите закрывающую скобку. Это увеличит его однажды вначале для первой открывающей скобки в" for (
", инкремент и постепенно уменьшает еще немного для некоторых промежуточных скобок, и задерживает его к 0
, когда Ваш for
скобка закрывается. openBr
будет 0
снова. останавливающееся положение является Вашей закрывающей скобкой [1 112]. Теперь можно проверить, существует ли точка с запятой после или нет.
Это - вид вещи, которую Вы действительно не должны делать с регулярным выражением. Просто проанализируйте строку один символ за один раз, отслеживание открытия/закрывающих скобок.
, Если это - все, которое Вы ищете, Вам определенно не нужен полноценный лексический анализатор/синтаксический анализатор грамматики C++. Если Вы хотите практику, можно записать немного рекурсивно-достойного синтаксического анализатора, но даже это - слишком для просто парных скобок.
Это - яркий пример использования неправильного инструмента для задания. Регулярные выражения не обрабатывают произвольно вложенные подсоответствия очень хорошо. Что необходимо сделать, вместо этого использование реальный лексический анализатор, и синтаксический анализатор (грамматику для C++ должно быть легко найти), и ищите неожиданно пустые тела циклов.
Я даже не обратил бы внимание на содержание parens.
Просто соответствие любая строка, которая запускается с for
и заканчивается точкой с запятой:
^\t*for.+;$
, Если Вы не имеете for
разделение операторов по поводу нескольких строк, которые будут хорошо работать?
Попробуйте этот regexp
^\s*(for|while)\s*
\(
(?P<balanced>
[^()]*
|
(?P=balanced)
\)
\s*;\s
, в который я удалил обертывание \( \)
приблизительно (?P=balanced)
и переместился *
позади любого не paren последовательность. Я имел эту работу с повышением xpressive и перепроверил что веб-сайт ( Xpressive) для обновления моей памяти.
Greg абсолютно корректен. Этот вид парсинга не может быть сделан с регулярными выражениями. Я предполагаю, что возможно создать некоторое ужасающее чудовище, которое работало бы на многие случаи, но затем Вы будете просто натыкаться на что-то, что делает.
действительно необходимо использовать более традиционные методы синтаксического анализа. Например, его довольно простое для записи рекурсивного достойного синтаксического анализатора, чтобы сделать то, в чем Вы нуждаетесь.
Я не знаю, что regex обработал бы что-то как этот очень хорошо. Попробуйте что-то вроде этого
line = line.Trim();
if(line.StartsWith("for") && line.EndsWith(";")){
//your code here
}
Другая мысль, которая игнорирует круглые скобки и рассматривает for
как конструкция, содержащая три разграниченных точкой с запятой значения:
for\s*\([^;]+;[^;]+;[^;]+\)\s*;
Эта опция работы, даже когда разделено по нескольким строкам (после того как МУЛЬТИЛИНИЯ включила), но предполагает, что for ( ... ; ... ; ... )
единственная допустимая конструкция, так не работал бы с for ( x in y )
конструкция или другие отклонения.
Также предполагает, что нет никаких функций, содержащих точки с запятой как аргументы, такие как:
for ( var i = 0; i < ListLen('a;b;c',';') ; i++ );
, Является ли это вероятным случаем, зависит от того, для чего Вы на самом деле делаете это.