- how to implement dynamically adjusting views based on total number of result records?? - sqlite with_v3=yes perl perl-dbi with_dbd_sqlite=yes perl-www perl-xml perl-util apache - apache.conf: Alias /quos/ /u/rse/wrk/ossp/quos/ Options +ExecCGI - prepare: - purpose of all files - OpenPKG RDF as example - perldoc IO::File - perldoc CGI - perldoc String::Divert - perldoc DBI - design for HTML form for boolean expression based query! (RT, perldoc DBIx::SearchBuilder) - UI Query Part (boolean expression to HTML form): Boolean Expression: expr ::= field op value | "!" expr | expr "||" expr | expr "&&" expr | "(" expr ")" field ::= /^[A-Z]+$/ op ::= "==" | "!=" | "<" | "<=" | ">" | ">=" | "=~" | "!~" value ::= /^.*$/ HTML Form: ------------------------------ ( field op value & field op value ) & ( | field op value & field op value | ! field op value & ! field op value ) ------------------------------ <:NN V:NN UPDATE CLEAR SUBMIT ------------------------------ NAME LOAD DELETE NAME SAVE HYPERLINK ------------------------------ - modules: * transformation module: - format 1: 2d form elements (input after submit of web form) lo2 lo1 lo0 fn fo fv +---+ +---+ +---+ +---------+ +---+ +---------+ 0 ...| | | | | | | grp | |== | | Mail | +---+ +---+ +---+ +---------+ +---+ +---------+ +---+ +---+ +---+ +---------+ +---+ +---------+ 1 ...| | | | ||| | | desc | |=~ | | \bMTA\b | +---+ +---+ +---+ +---------+ +---+ +---------+ +---+ +---+ +---+ +---------+ +---+ +---------+ 2 ...| | |&& | | | | class | |== | | CORE | +---+ +---+ +---+ +---------+ +---+ +---------+ +---+ +---+ +---+ +---------+ +---+ +---------+ 3 ...| | | | ||| | | class | |== | | BASE | +---+ +---+ +---+ +---------+ +---+ +---------+ : : : : : : fn-0="grp"&fo-0="=="&fv-0="Mail"&lo0-1="||"&fn-1="desc"&fo-1="=~"&fv-1="\bMTA\b" lo1-2="&&"&fn-2="class"&fo-2="=="&fv-2="CORE"&lo0-3="||"&fn-3="class"&fo-3="=="&fv-3="BASE" - format 2a: astract syntax tree for query expression (internal representation) function-style: AND( OR( EQ(grp,"Mail"), RE(desc,"\bMTA\b") ), OR( EQ(class,"CORE"), EQ(class,"BASE") ) ) in-core-style: my $expr = [ "AND", [ "OR", [ "EQ", "grp", "Mail" ], [ "RE", "desc", "\bMTA\b"] ], [ "OR", [ "EQ", "class", "CORE" ], [ "EQ", "class", "BASE" ] ] ]; "print $expr->[2]->[1]->[2];" -> "CORE" my $format2b = &transform_tree($expr, \&transform_style_perl); my $format2c = &transform_tree($expr, \&transform_style_sql); sub transform_tree { my ($expr, $style) = @_; my $str = ''; my ($op, $a1, $a2) = @{$expr}; $op = &style($op); $a1 = ref($a1) ? &style(&transform_tree($a1, $style)) : &style($a1); $a2 = ref($a2) ? &style(&transform_tree($a2, $style)) : &style($a2); $str = "$a1 $op $a2"; return $str; } sub transform_style_perl { my ($token) = @_; $token =~ s/^AND$/&&/; $token =~ s/^OR$/||/; $token =~ s/^EQ$/==/; $token =~ s/^RE$/=~/; return $token; } sub transform_style_sql { my ($token) = @_; $token =~ s/^EQ$/=/; $token =~ s/^RE$/MATCH/; return $token; } - format 2b: C-style query expression (input after hyperlink in web page) (grp == "Mail" || desc =~ "\bMTA\b") && (class == "CORE || class == "BASE") - format 2c: SQL-style query expression (output for database query) (quos.q_grp = 'Mail' OR quos.q_desc MATCH? '\bMTA\b') AND (quos.q_class = 'CORE' OR quos.q_class = 'BASE') * creation of web formular (render query) sub_render_form (cgi-Object | expression, row, column - Parsing CFG: OSSP shiela (with tricks) OSSP ac (uses Parse::RecDescent) Parse::RecDescent (full featured recursive-descend parsing) GENERAL: config ::= directive(s) directive ::= word arg ";" arg ::= "{" config "}" | word word ::= m/"[^"]*"/ | m/'[^']*'/ | m/[^\s+;]+/ SPECIAL: config ::= directive(s) directive ::= options | queries | views options ::= "option" "{" options-directive(s) "}" ";" options-directive ::= webpage | database webpage ::= "webpage" word word ";" database ::= "database" "{" database-directive(s) "}" ";" database-directive ::= ... ... queries ::= group(s) ... views ::= view(s) ... word ::= m/"[^"]*"/ | m/'[^']*'/ | m/[^\s+;]+/ - Parsing RDF: my $str = ...; # string representation my $rdf = {}; # AST representation $str =~ s/]+)>(.+?)<\/Repository>/&do_repository($rdf, $1, $2)/sge; sub do_repository { my ($rdf, $attr, $str) = @_; my ($name) = ($attr =~ m/rdf:resource="([^"]+)"/s); $rdf->{$name} = {}; $str =~ s/]+)>(.+?)<\/rdf:Description>/&do_destription($rdf->{$name}, $1, $2)/sge; sub do_description { my ($rdf, $attr, $str) = @_; $rdf->{...} = ...; } } 1. geht nur, wenn die Sprache keine rekursiven Elemente enthält, d.h. ein Element kann nicht in sich selber (in beliebiger Tiefe) vorkommen (Hinweis: Für Compilerbauer uninteressant) 2. Blockstruktur der Sprache wird direkt Substitution+Funktionsaufruf umgesetzt 3. Auf jeder Ebene wird die bereits erkannte Information in einer internen Datenstruktur aufgesammelt ($rdf)