I've run the following code in flex and got yyparse() error, The target output I'm hoping to get is :
P
font-size: 8px
font-family: arial
color: red
TD
background-color: yellow
border: 1px solid black
Here is my program:
%{
#include<stdio.h>
#include"yousuf.h"
int yylineno;
%}
%%
"<"[^>]*> ;
[P] {printf("P\n",yytext);}
"font-size: 8 px" {printf("font-size: 8 px\n"); return FONTSIZE;}
"font-family: arial" {printf("font-family: arial\n"); return FONTFAMILY;}
"color: red" {printf("color: red\n"); return COLOR;}
[TD] {printf("TD\n",yytext);}
"background-color: yellow" {printf("background-color: yellow\n"); return BACKGROUNDCOLOR;}
"border: 1px solid black" {printf("border: 1px solid black"); return BORDER;}
[ \t\n] ;
. ;
%%
int main(int argc, char **argv)
{
char string[]= "<style>P{font-size: 8px; font-family: arial; color: red;}TD{background-color: yellow; border: 1px solid black;}</style>";
YY_BUFFER_STATE buffer= yy_scan_string(string);
yyparse();
yy_delete_buffer(buffer);
return 0;
}
int yywrap(void)
{
return 0;
}
Also, is there any other way to feed input to flex other than fopen("filename.txt","r"); because it doesn't seem to read the file and take it as input.
The function defined by (f)lex is called yylex. yyparse is generated by bison/yacc, which you do not appear to be using.
Flex takes its input from yyin, declared as:
extern FILE* yyin;
So it's not sufficient to just call fopen; you need to assign the return value to yyin. You should also make sure that the fopen call succeeded:
yyin = fopen("filename.txt","r");
if (yyin == NULL) {
fprintf(stderr, "Could not open 'filename.txt': %s\n", strerror(errno));
exit(1);
}
By the way, [TD] recognises either a T or a D. So with input TD, your rule will print TD twice.
Related
I'm trying to use a var defined for one mixin in another mixin.
In my case, I definee the $gutter variable in the container() mixin.
I don't want to define it again for the col() mixin, so I was trying to get it into the col() mixin.
Here is what I've done so far:
#mixin container($gutter, $placeholder:"cols") {
margin: 0 -#{$gutter / 2};
%#{$placeholder} {
margin-left: #{$gutter / 2};
margin-right: #{$gutter / 2};
}
}
#mixin cols($cols, $placeholder:"cols") {
#extend %#{$placeholder};
width: #{(100% / $cols) - $gutter};
}
.wrap {
#include container(2%);
> .half {
#include cols(2);
}
> .third {
#include cols(3);
}
> .fourth {
#include cols(4);
}
}
The css result I need is the following:
.wrap {
margin: 0 -1%;
}
.wrap > .half, .wrap > .third, .wrap > .fourth {
margin-left: 1%;
margin-right: 1%;
}
.wrap > .half {
width: 48%;
}
.wrap > .third {
width: 31.33333%;
}
.wrap > .fourth {
width: 23%;
}
Is there a way to do this? It fails in line 11 because $gutter is undefined. A global variable isn't the solution i need, because I have to use this mixin in different breakpoints with different gutters. So for each breakpoint will define container() and cols() for the elements again.
You are creating a variable inside a mixin. Variables inside mixins are local they are not global. If you want to create a global variable from a mixin then you have to use the !global flag
you can rewrite the container mixin like this
#mixin container($gutter, $placeholder:"cols") {
$gutter: $gutter !global;
margin: 0 -#{$gutter / 2};
%#{$placeholder} {
margin-left: #{$gutter / 2};
margin-right: #{$gutter / 2};
}
}
I'm trying to do a mixin that have optional arguments. This is a simplified version:
#mixin marginCalculator($size, $size2:"") {
margin: $size * 1px unquote($size2 * 1px);
}
I'm just passing in numbers as arguments. But i only want the first one to be mandatory. No problem if it only would output the number but i need to add a unit to it.
As can be seen in the snippet above i'm trying to multiplicate 1px with "" which ouputs an error message. As it should! But i was hoping for the empty quote to be returned. Is there another way to achieve this?
You have 2 options:
Check the type of the value being passed in
#mixin marginCalculator($size, $size2: "") {
margin: ($size * 1px) (if(type-of($size2) == number, $size2 * 1px, null));
}
Loop over a list
This is a much better solution since it will allow you to gracefully handle 3-value margins as well.
#mixin marginCalculator($size...) {
$xs: ();
#each $s in $size {
$xs: append($xs, $s * 1px);
}
margin: $xs;
}
.foo {
#include marginCalculator(1);
#include marginCalculator(1, 2);
#include marginCalculator(1, 2, 3);
}
Alternately:
#mixin marginCalculator($sizes) {
$xs: ();
#each $s in $size {
$xs: append($xs, $s * 1px);
}
margin: $xs;
}
.foo {
#include marginCalculator(1);
#include marginCalculator(1 2);
#include marginCalculator(1 2 3);
}
Output:
.foo .foo {
margin: 1px;
margin: 1px 2px;
margin: 1px 2px 3px;
}
You can use an if() function to check if it has no value:
#mixin marginCalculator($size, $size2:"") {
margin: ($size * 1px) if($size2!="", $size2 * 1px, null);
}
Here, i check it against the default, an empty string, and return the calculation if it isn't that, and null if it is. If we return an empty string, it'll cause a CSS error.
I have a mixin that converts px to rem PX TO REM, I have this code:
.button {
#include rem(font-size, 24px);
#include rem(padding, 10px);
#include rem(border-radius, 5px);
}
This would produce this CSS:
.button {
font-size: 1.5rem;
padding: 0.625rem;
border-radius: 0.3125rem; }
But I'd like to use some mixins from compass and for example I want to use border-radius from compass
.box {
#include border-radius(10px);
}
And it would generate this CSS:
.box {
-moz-border-radius: 10px;
-webkit-border-radius: 10px;
border-radius: 10px; }
Is there a way to do something like this:
.box {
#include rem(#include border-radius(10));
}
You can't add two mixins together the way you'd like. So you just have to make the rem mixin do what you want it to do. So I wrote new code to handle that for you.
#function parseInt($n) {
#return $n / ($n * 0 + 1);
}
#mixin rem($property, $values, $prefix: false) {
$px: ();
$rem: ();
#each $value in $values {
#if $value == 0 or $value == auto or unit($value) == "%" {
$px: append($px, $value);
$rem: append($rem, $value);
} #else {
$unit: unit($value);
$val: parseInt($value);
#if $unit == "px" {
$px: append($px, $value);
$rem: append($rem, ($val / 16 + rem));
}
#if $unit == "rem" {
$px: append($px, ($val * 16 + px));
$rem: append($rem, $value);
}
}
}
#if $px == $rem {
#{$property}: $px;
} #else if $prefix == true {
#{-moz- + $property}: $px;
#{-moz- +$property}: $rem;
#{-webkit- +$property}: $px;
#{-webkit- +$property}: $rem;
#{$property}: $px;
#{$property}: $rem;
} #else {
#{$property}: $px;
#{$property}: $rem;
}
}
Now all you have to do add prefixes to any property is add the value true to the end of the mixin like so...
#include rem(border-radius, 10px, true);
Otherwise if you don't want any prefixs on property like fon-size or something you just don't add a last value like so...
#include rem(font-size, 10px);
I have a working demo here...
*Also on a side note I modified this mixin to handle percentages too.
see this codepen
it is super basic
$span1Width: 10;
$marginWidth: 5;
#mixin span-width($spannr) {
width: $span1Width * $spannr *1%;
*width: $marginWidth* $spannr -1 *1%;
}
div{
#use span-width(10);
}
resulting in "empty rule" when doing a analyse css with codepen.
If you check the example on sass documentation on how to use mixins you can see:
$color: white;
#mixin colors($color: blue) {
background-color: $color;
#content;
border-color: $color;
}
.colors {
#include colors { color: $color; }
}
So you should use #include and { } instead. Like (using default 5 in this example):
$span1Width: 10;
$marginWidth: 5;
#mixin span-width($spannr: 5) {
width: $span1Width * $spannr *1%;
*width: $marginWidth* $spannr -1 *1%;
}
div{
#include span-width{ spannr: 10};
}
That should give you the correct result
This question already has an answer here:
Ampersand (&) at the end, and part of, a selector in SASS
(1 answer)
Closed 7 years ago.
I have a class semantic which I apply to many different elements. Depending on which html tag the class is applied to, I would like it to apply a different style. This is how I tried to do it:
.semantic {
&ul {
padding: 0;
margin: 0;
}
&p {
margin: 0;
}
}
This doesn't work. Of course I could write it like this, but it wouldn't be very "DRY":
.semantic ul {
padding: 0;
margin: 0;
}
.semantic p {
margin: 0;
}
Is this possible?
Edit: For clarification, here is an example of what my HTML looks like:
<ul class='semantic'>
<li>An Item</li>
</ul>
<p class='semantic'>This text is semantically a paragraph, but should not be displayed as such</p>
On Sass 3.4:
.semantic {
#at-root {
ul#{&} {
padding: 0;
margin: 0;
}
p#{&} {
margin: 0;
}
}
}
Generates:
ul.semantic {
padding: 0;
margin: 0;
}
p.semantic {
margin: 0;
}
#at-root moves the block to the top-level. This has several uses (see link) but here it's being used to keep take advantage of the & syntax without implying that the rules are child selectors of .semantic.
What you're wanting for would in theory look like this:
.semantic {
ul& {
padding: 0;
margin: 0;
}
p& {
margin: 0;
}
}
This is not possible because the & must be first. You're just going to have to deal with the fact that it isn't DRY and write it out by hand:
ul.semantic {
padding: 0;
margin: 0;
}
p.semantic {
margin: 0;
}
As of Sass 3.3 or 3.4, it is possible using this syntax:
.semantic {
ul#{&} {
padding: 0;
margin: 0;
}
p#{&} {
margin: 0;
}
}
Because of how CSS specificity works you could just do this:
.semantic {
margin: 0;
}
ul.semantic {
padding: 0;
}
In your HTML, p.semantic and ul.semantic would have margin: 0; and only ul.semantic would have padding: 0;
Less Sass, less CSS. DRY.
If, unlike your example, elements on the real site have even less in common, you might want to rethink why they need to have the same class name.