1 /* $XConsortium: style.y /main/4 1996/11/11 11:51:33 drk $ */
9 #include "StyleSheetExceptions.h"
10 #include "VariableTable.h"
11 #include "FeatureValue.h"
12 #include "Expression.h"
14 #include "PathTable.h"
16 #include "PathQualifier.h"
18 #include "ParserConst.h"
19 #include "FeatureDefDictionary.h"
20 #include <utility/funcs.h>
22 #include "HardCopy/autoNumberFP.h"
23 extern autoNumberFP gAutoNumberFP;
26 #define alloca(x) (malloc(x))
28 extern void yyerror(char*);
31 extern void enter_sgmlgi_context();
33 extern featureDefDictionary* g_FeatureDefDictionary;
34 extern unsigned g_validation_mode;
35 extern unsigned g_hasSemanticError;
37 static char localCharToCharPtrBuf[2];
41 const char* toUpperCase(unsigned char* string)
43 static char buffer[512];
45 for ( int i=0; i<strlen((const char*)string); i++ )
47 if (islower(string[i]))
48 buffer[j] = toupper(string[i]) ;
50 buffer[j] = (char)string[i] ;
61 unsigned char charData;
62 unsigned char* charPtrData;
63 unsigned int boolData;
66 Expression* expPtrData;
67 TermNode* termNodePtrData;
68 FeatureValue* FeatureValuePtrData;
69 FeatureSet* FeatureSetPtrData;
70 Feature* FeaturePtrData;
72 PathTerm* PathTermPtrData;
73 charPtrDlist* charPtrDlistData;
74 PathFeatureList* PathFeatureListPtrData;
75 CompositeVariableNode* CompositeVariableNodePtrData;
77 CC_TPtrSlist<FeatureValue>* FeatureValueSlistPtrData;
79 PQExpr* PQExprPtrData;
144 %type<termNodePtrData>
151 %type<FeatureSetPtrData>
155 %type<FeatureValuePtrData>
160 %type<CompositeVariableNodePtrData>
163 %type<FeatureValueSlistPtrData>
166 %type<FeaturePtrData>
172 %type<PathTermPtrData>
175 %type<PathFeatureListPtrData>
179 %type<charPtrDlistData>
191 %nonassoc OPER_period
192 %nonassoc SGMLGI_STRING
196 stylesheet : sensitivityOPTL statement.gpOPTL
201 sensitivity : GI_CASE_SENSITIVE OPER_assign BOOLVAL
203 gGI_CASE_SENSITIVE = $3;
207 statement.gp : var_assignment
212 /* copy items form the feature list into the path table */
213 PathFeatureListIterator l_Iter(*($1));
221 if ( g_validation_mode == true )
222 if ( g_FeatureDefDictionary -> checkSemantics(x -> featureSet()) == false )
223 g_hasSemanticError = true;
225 gPathTab -> addPathFeatureSet( x );
230 /* clear out the first list so the elements are not deleted
231 with the list because they are still referenced by the
240 var_assignment : STRING OPER_assign rhs.gp
242 Expression *x = new Expression(new ConstantNode($3));
244 if ( gAutoNumberFP.accept((const char*)$1, x) ) {
250 gVariableTable -> enter( gSymTab -> intern((const char*)$1), x);
266 const Symbol* x = $1 -> convertableToVariable();
268 $$=new VariableNode(*x);
275 string_list : string_list OPER_feature STRING
278 $1->appendItem(gSymTab->intern(toUpperCase($3)));
284 $$=new CompositeVariableNode;
285 $$ -> appendItem(gSymTab->intern(toUpperCase($1)));
290 parent : OPER_parent SGMLGI
294 ParentNode(gSymTab->intern((const char*)$1));
296 MESSAGE(cerr, "^ operator not supported.");
297 throw(StyleSheetException());
301 attr : OPER_attr SGMLGI
304 SgmlAttributeNode(gSymTab->intern((const char*)$2));
311 $$=new FeatureValueExpression($1);
319 $$=new FeatureValueFeatureSet($1);
324 simple_expr : simple_expr OPER_add multi_expr
326 BinaryOperatorNode::operatorType opType;
328 case '+': opType=BinaryOperatorNode::PLUS; break;
329 case '-': opType=BinaryOperatorNode::MINUS; break;
331 throw(badEvaluationException());
334 FeatureValueExpression* FVexprL = new FeatureValueExpression($1);
335 FeatureValueExpression* FVexprR = new FeatureValueExpression($3);
338 new BinaryOperatorNode(opType,
339 new ConstantNode(FVexprL),
340 new ConstantNode(FVexprR)
350 multi_expr : multi_expr OPER_mult term
352 BinaryOperatorNode::operatorType opType;
354 case '*': opType=BinaryOperatorNode::TIMES; break;
355 case '/': opType=BinaryOperatorNode::DIVIDE; break;
357 throw(badEvaluationException());
360 FeatureValueExpression* FVexpr = new FeatureValueExpression($1);
363 new BinaryOperatorNode(opType, new ConstantNode(FVexpr), $3)
368 $$ = new Expression($1);
372 OPER_binop : OPER_mult
382 OPER_mult : OPER_star
394 $$=new ConstantNode(new FeatureValueInt(int($1)));
398 FeatureValueExpression* fve =
399 new FeatureValueExpression(new Expression($1));
400 FeatureValueDimension* x =
401 new FeatureValueDimension(fve, (const char*)$2);
403 $$=new ConstantNode(x);
415 $$=new ConstantNode(new FeatureValueString((const char*)$1));
418 | INTEGER UNIT_STRING
420 $$=new ConstantNode(new FeatureValueDimension(new FeatureValueInt($1), (const char*)$2));
425 $$=new ConstantNode(new FeatureValueDimension(new FeatureValueReal($1), (const char*)$2));
430 $$=new ConstantNode(new FeatureValueInt($1));
434 $$=new ConstantNode(new FeatureValueReal($1));
436 | OPER_parenopen simple_expr OPER_parenclose
438 $$=new ConstantNode(new FeatureValueExpression($2));
442 array : array_name ARRAYOPEN array_member_list ARRAYCLOSE
444 FeatureValueArray* x =
445 new FeatureValueArray((const char*)$1, $3 -> entries());
446 CC_TPtrSlistIterator<FeatureValue> iter(*$3);
450 (*x)[i++] = iter.key();
458 | array_name ARRAYOPEN ARRAYCLOSE
460 $$ = new FeatureValueArray((const char*)$1, 0);
471 $$ = new unsigned char[1];
476 array_member_list : array_member SEPARATOR array_member_list
483 $$=new CC_TPtrSlist<FeatureValue>;
488 array_member : simple_expr
490 $$ = new FeatureValueExpression($1);
498 featureset : FSOPEN feature_list SEPARATOR_OPTL FSCLOSE
504 $$ = new FeatureSet ();
508 feature_list : feature_list SEPARATOR feature
510 if ($3 -> name() == Symbol(gSymTab->intern("FAMILY"))) {
511 // the evaluate() call clones $3
512 FeatureValueFeatureSet *fvfs =
513 (FeatureValueFeatureSet*) $3->evaluate();
514 const FeatureSet* fs = fvfs->value();
515 const Feature* charsetF =
516 fs->lookup(gSymTab->intern("CHARSET"));
517 // charsetF is a mandatory entry in fontfamily
519 const FeatureValueString* fv_string =
520 (FeatureValueString*)charsetF->value();
521 const char* charset = *fv_string;
524 int entries = $1 -> entries();
525 for (int i=0; i<entries; i++) {
526 const Feature* entry = $1->at(i);
527 if (! (entry->name() == Symbol(gSymTab->intern("FAMILY"))))
529 const FeatureSet* entry_fs =
530 ((FeatureValueFeatureSet*)(entry->evaluate()))->value();
531 const Feature* entry_charsetF =
532 entry_fs->lookup(gSymTab->intern("CHARSET"));
533 assert( entry_charsetF );
534 const char* entry_charset =
535 *((FeatureValueString*)(entry_charsetF->value()));
536 assert( entry_charset );
537 if (! strcmp(charset, entry_charset)) {
538 delete $1 -> removeAt(i);
539 break; // escape from for-loop
548 if ( $1 -> find((Feature*)$3) ) {
549 FeatureSet* fs = new FeatureSet();
552 $$ =new FeatureSet(*$1, *fs);
569 SEPARATOR_OPTL : SEPARATOR
577 feature : feature_name_list OPER_modify rhs.gp
579 CC_TPtrDlistIterator<char> l_Iter(*($1));
583 FeatureValue *fv = $3;
584 const char* cptr = 0;
589 const char *c = cptr ;
593 buffer[index] = toupper(*c) ;
600 /* fprintf(stderr, "converted: %s to %s\n", cptr, buffer); */
601 f = new Feature(gSymTab -> intern(buffer), fv);
603 if ( $1 -> last() != cptr ) {
604 fs = new FeatureSet();
606 fv = new FeatureValueFeatureSet(fs);
610 $1->clearAndDestroy();
616 feature_name_list : feature_name_list OPER_feature STRING
618 $1 -> prepend((char *)$3);
624 $$=new CC_TPtrDlist<char>;
625 $$ -> append((char *)$1);
629 path_expr : path_term_list featureset
631 $$=new PathFeatureList;
632 $$ -> append(new PathFeature($1, $2));
634 | path_term_list OPER_parenopen path_expr_list OPER_parenclose
637 PathFeatureListIterator l_Iter(*($3));
640 (l_Iter.key()) -> path() -> prependPath(*$1);
647 path_expr_list : path_expr_list SEPARATOR path_expr
650 $$ -> appendList(*$3);
658 path_term_list : path_term_list path_term
660 $1 -> appendPathTerm($2);
666 $$ -> appendPathTerm($1);
670 path_term : SGMLGI path_selectorOPTL
672 $$=new PathTerm((const char*)$1, $2);
677 localCharToCharPtrBuf[0]=$1; localCharToCharPtrBuf[1]=0;
678 $$=new PathTerm(localCharToCharPtrBuf, 0);
682 localCharToCharPtrBuf[0]=$1; localCharToCharPtrBuf[1]=0;
683 $$=new PathTerm(localCharToCharPtrBuf, 0);
687 OPER_feature : OPER_period
699 SGMLGI : SGMLGI_CONTENT
701 // char % can start an OLIAS internal element which
702 // is used only by the browser.
703 // Example %BOGUS within HEAD1 in OLIAS book
705 if ( $1[0] != '%' && isalnum($1[0]) == 0 ) {
706 MESSAGE(cerr, form("%s is not a SGMLGI", $1));
707 throw(badEvaluationException());
709 /* note, should probably be using RCStrings, would make wide */
710 /* char handling better too? */
711 if ( gGI_CASE_SENSITIVE == false )
713 for (int i=0; i<strlen((const char*)$1); i++)
714 if ( islower($1[i]) )
715 $1[i] = toupper($1[i]);
721 SGMLGI_CONTENT : STRING OPER_period {enter_sgmlgi_context();} SGMLGI_STRING
723 int l = strlen((char*)$1) + strlen((char*)$4) + 2;
724 $$=new unsigned char[l];
725 strcpy((char*)$$, (char*)$1);
726 strcat((char*)$$, ".");
727 strcat((char*)$$, (char*)$4);
733 int l = strlen((char*)$1) + 2;
734 $$=new unsigned char[l];
735 strcpy((char*)$$, (char*)$1);
736 strcat((char*)$$, ".");
746 dimension : DIMENSION
750 for (i=0; i<strlen((const char*)$1); i++) {
752 if ( isalpha($1[i]) )
760 x = atof((const char*)$1);
765 $$=new ConstantNode(new FeatureValueDimension(new FeatureValueReal(x), (const char*)&$1[i]));
770 STRING : NORMAL_STRING
780 path_selector : ARRAYOPEN boolean_expr ARRAYCLOSE
786 boolean_expr : logical_and_expr
788 //////////////////////////////////////////////////////
789 // This portion of the code (up to equality_expr) is
790 // hacked for V1.1 only. Due to the way
791 // PathQualifier.h is written, this code is not
792 // general at all. qfc 8/16/94
793 //////////////////////////////////////////////////////
796 | boolean_expr OPER_or logical_and_expr
798 $$ = new PQLogExpr($1, PQor, $3);
802 logical_and_expr : equality_expr
806 | logical_and_expr OPER_and equality_expr
808 $$ = new PQLogExpr($1, PQand, $3);
812 equality_expr : OPER_attr SGMLGI OPER_equality QUOTED_STRING
814 $$ = new PQAttributeSelector(
815 gSymTab->intern((const char*)$2),
816 ( $3 == EQUAL ) ? PQEqual : PQNotEqual,
822 | NORMAL_STRING OPER_equality POSITION_VALUE
824 if ( strcasecmp((char*)$1, "position") == 0 ) {
826 ( $2 == EQUAL ) ? PQEqual : PQNotEqual,
830 if ( strcasecmp((char*)$1, "sibling") == 0 ) {
832 ( $2 == EQUAL ) ? PQEqual : PQNotEqual,
836 throw(StyleSheetException());
842 POSITION_VALUE : INTEGER
848 if ( strcasecmp((char*)$1, "#LAST") != 0 )
849 throw(StyleSheetException());
856 sensitivityOPTL : sensitivity
866 statement.gpOPTL : statement.gpPLUS
874 statement.gpPLUS : statement.gpPLUS statement.gp
884 path_selectorOPTL : path_selector